Вход

Просмотр полной версии : ПЛК160 + ПЧ Eaton DC1 по modbus



energvk
28.10.2015, 13:05
Столкнулся с необходимостью управлять преобразователем частоты Eaton DC1. Застрял на прочтении слова состояния и неисправности (они объединены в одно слово).

20576

То есть неисправность шифруется шестнадцатеричным кодом во втором байте слова состояния и неисправности.
20577

Соответственно, как я понимаю мне нужно вырезать нужный кусок информации из WORDа и его анализировать. Но с операторами сдвига у меня мягко говоря пока туго (то есть вообще ещё не сталкивался).

Если я правильно понял, то последовательность действий примерно такая:


VAR
pt :POINTER TO WORD;
avar_pch :BYTE;
stat_pch :WORD;
code_err :WORD;
END_VAR

pt:=ADR(stat_pch);
avar_pch:=WORD_TO_BYTE(SHR(pt^,??)); (*Смещаемся на 8 бит (или не 8??) вправо и остальное заполняем нулями*)

(*Анализируем коды ошибок*)
CASE avar_pch OF
16#00: code_err:=1;
16#01: code_err:=2;
...
...
END_CASE


Но почти уверен, что код не совсем верен. Так как на руках преобразователя ещё нет, хотел бы проконсультироваться по коду у профессионалов :rolleyes:

petera
28.10.2015, 13:47
Столкнулся с необходимостью управлять преобразователем частоты Eaton DC1. Застрял на прочтении слова состояния и неисправности (они объединены в одно слово).

20576

То есть неисправность шифруется шестнадцатеричным кодом во втором байте слова состояния и неисправности.
20577

Соответственно, как я понимаю мне нужно вырезать нужный кусок информации из WORDа и его анализировать. Но с операторами сдвига у меня мягко говоря пока туго (то есть вообще ещё не сталкивался).

Если я правильно понял, то последовательность действий примерно такая:


VAR
pt :POINTER TO WORD;
avar_pch :BYTE;
stat_pch :WORD;
code_err :WORD;
END_VAR

pt:=ADR(stat_pch);
avar_pch:=WORD_TO_BYTE(SHR(pt^,??)); (*Смещаемся на 8 бит (или не 8??) вправо и остальное заполняем нулями*)

(*Анализируем коды ошибок*)
CASE avar_pch OF
16#00: code_err:=1;
16#01: code_err:=2;
...
...
END_CASE


Но почти уверен, что код не совсем верен. Так как на руках преобразователя ещё нет, хотел бы проконсультироваться по коду у профессионалов :rolleyes:
1. Операцию сдвига SHR можно было использовать без всяких указателей срезу к stat_pch
2. А если уж использовать указатель, то так

VAR
stat_pch: WORD;
pt: POINTER TO BYTE;
avar_pch: BYTE;
END_VAR

pt:=ADR(stat_pch)+1;
avar_pch:=pt^;

energvk
28.10.2015, 14:05
Ага, понятно. Попробую сейчас.
А зачем +1 к pt?

energvk
28.10.2015, 14:10
В итоге написал такой ФБ:


FUNCTION_BLOCK avar_pch_dc1
VAR_INPUT
alarm_pch :BOOL; (*Вход аварийного состояния*)
stat_pch :WORD; (*Слово состояния с преобрзователя*)
END_VAR
VAR_OUTPUT
ovr_cur, ovr_dr, err_phase, ovr_heat :BOOL; (*Выходы аварий*)
END_VAR
VAR
(*pt :POINTER TO WORD; (*Адрес входной переменной*)*)
avar_pch :BYTE; (*Переменная в байтах*)
code_err :WORD; (*Код аварии*)
err :BOOL; (*Наличие аварии*)
END_VAR


(*
Коды аварий (hex)
00 Остановлен, готов к работе
01 Избыточный ток тормозного прерывателя
02 Перегрузка тормозного резистора
03 • Перегрузка по току на выходе преобразователя частоты
• Перегрузка двигателя
• Перегрев радиатора преобразователя частоты
04 Перегрев двигателя
05 Внутренняя неисправность (силовая схема)
06 Перенапряжение в звене постоянного тока
07 Недостаточное напряжение в звене постоянного тока
08 Перегрев радиатора охлаждения
09 Перегрев радиатора охлаждения
0A Настройки по умолчанию (параметры загружены)
C0 сообщение о внешней ошибке
0C Ошибка магистральной шины
0D Зарезервирован
0E Неисправность фазы (со стороны электрической сети)
0F Неисправность функции управления приемистостью двигателя (для подхвата вращающегося двигателя)
10 Неисправность встроенного термистора (радиатор)
11 Неисправность контрольной суммы EEPROM
12 Аналоговый вход:
• значение вне диапазона
• разрыв провода (контроль 4 мА)
*)

IF alarm_pch THEN
err:=TRUE; (*Установить признак аварии*)
(*pt:=ADR(stat_pch);*)
(*avar_pch:=WORD_TO_BYTE(SHR(pt^,8)); (*Смещаемся на 8 бит (или не 8??) вправо и остальное заполняем нулями*)*)
avar_pch:=WORD_TO_BYTE(SHR(stat_pch,8)); (*Смещаемся на 8 бит (или не 8??) вправо и остальное заполняем нулями*)

(*Коды ошибок, полученные с датчика*)
CASE avar_pch OF
16#00: code_err:=1; (*Остановлен, готов к работе*)
16#01: code_err:=2; (*Избыточный ток тормозного прерывателя*)
16#02: code_err:=3; (*Перегрузка тормозного резистора*)
16#03: code_err:=4; (*Перегрузка по току ПЧ, ЭД или перегрев радиатора преобразователя частоты*)
16#04: code_err:=5; (*Перегрев двигателя*)
16#05: code_err:=6; (*Внутренняя неисправность (силовая схема)*)
16#06: code_err:=7; (*Перенапряжение в звене постоянного тока*)
16#07: code_err:=8; (*Недостаточное напряжение в звене постоянного тока*)
16#08: code_err:=9; (*Перегрев радиатора охлаждения*)
16#09: code_err:=10; (*Перегрев радиатора охлаждения*)
16#C0: code_err:=11; (*сообщение о внешней ошибке*)
16#0C: code_err:=12; (*Ошибка магистральной шины*)
16#0E: code_err:=13; (*Неисправность фазы (со стороны электрической сети)*)
16#0F: code_err:=14; (*Неисправность функции управления приемистостью двигателя (для подхвата вращающегося двигателя)*)
16#10: code_err:=15; (*Неисправность встроенного термистора (радиатор)*)
16#11: code_err:=16; (*Неисправность контрольной суммы EEPROM*)
16#12: code_err:=17; (*Неисправность аналогового входа (вне диапазона или разрыв провода)*)
ELSE
err:=FALSE;
code_err:=0; (*Нет аварии ПЧ*)
END_CASE

IF code_err=4 THEN
ovr_cur:=TRUE;
ELSE ovr_cur:=FALSE; END_IF;
IF code_err=5 THEN
ovr_dr:=TRUE;
ELSE ovr_dr:=FALSE; END_IF;
IF code_err=13 THEN
err_phase:=TRUE;
ELSE err_phase:=FALSE; END_IF;
IF (code_err=9 OR code_err=10) THEN
ovr_heat:=TRUE;
ELSE ovr_heat:=FALSE; END_IF;

END_IF;


Надеюсь будет работать...

petera
28.10.2015, 14:10
По идее в avar_pch уже и есть код ошибки. Можно и без CASE обойтись и не использовать переменную code_err.
Но если хочется иметь коды ошибок по порядку, то и CASE можно уменьшить

VAR
stat_pch: WORD;
pt: POINTER TO BYTE;
avar_pch: WORD;
code_err: WORD;
END_VAR

pt:=ADR(stat_pch)+1;
avar_pch:=pt^;


(*Анализируем коды ошибок*)
CASE avar_pch OF
16#C0: code_err:=11;
16#0C: code_err:=12;
16#0D: code_err:=13;
16#0E: code_err:=14;
16#0F: code_err:=15;
16#10: code_err:=16;
16#11: code_err:=17;
16#12: code_err:=18;
ELSE
IF avar_pch <= 10 THEN
code_err:=avar_pch;
ELSE
code_err:=0;
END_IF
END_CASE

petera
28.10.2015, 14:13
Ага, понятно. Попробую сейчас.
А зачем +1 к pt?
Для того чтобы указатель указывал на старший BYTE в stat_pch

ЗЫ. А я смотрю Вы все равно и указатель и сдвиг используете, а зачем?

energvk
28.10.2015, 14:26
По идее в avar_pch уже и есть код ошибки. Можно и без CASE обойтись и не использовать переменную code_err.
Но если хочется иметь коды ошибок по порядку, то и CASE можно уменьшить

VAR
stat_pch: WORD;
pt: POINTER TO BYTE;
avar_pch: WORD;
code_err: WORD;
END_VAR

pt:=ADR(stat_pch)+1;
avar_pch:=pt^;


(*Анализируем коды ошибок*)
CASE avar_pch OF
16#C0: code_err:=11;
16#0C: code_err:=12;
16#0D: code_err:=13;
16#0E: code_err:=14;
16#0F: code_err:=15;
16#10: code_err:=16;
16#11: code_err:=17;
16#12: code_err:=18;
ELSE
IF avar_pch <= 10 THEN
code_err:=avar_pch;
ELSE
code_err:=0;
END_IF
END_CASE

Понятно, огромное спасибо за разъяснения


Для того чтобы указатель указывал на старший BYTE в stat_pch
И ещё раз спасибо


ЗЫ. А я смотрю Вы все равно и указатель и сдвиг используете, а зачем?
Я указатель закоментировал