1. Обязательно представиться на русском языке кириллицей (заполнить поле "Имя").
  2. Фиктивные имена мы не приветствуем. Ивановых и Пупкиных здесь уже достаточно.
  3. Не надо писать свой вопрос в первую попавшуюся тему - всегда лучше создать новую тему.
  4. За поиск, предложение и обсуждение пиратского ПО и средств взлома - бан без предупреждения. Непонятно? - Читать здесь.
  5. Рекламу и частные объявления "куплю/продам/есть халтура" мы не размещаем ни на каких условиях.
  6. Перед тем как что-то написать - читать здесь, а затем здесь и здесь.
  7. Не надо писать в ЛС администраторам свои технические вопросы. Администраторы форума отлично знают как работает форум, а не все-все контроллеры, о которых тут пишут.

HCFA HCA8 Modbus

Altivar, Altistart, Tesys, Lexium, SoMove

Модераторы: Глоб.модераторы, Специалисты SE

Ответить

Автор темы
demonlibra
здесь недавно
здесь недавно
Сообщения: 37
Зарегистрирован: 21 сен 2024, 18:17
Имя: Дмитрий
Страна: РФ
Благодарил (а): 10 раз
Поблагодарили: 3 раза

HCFA HCA8 Modbus

Сообщение demonlibra »

Пытаюсь связать ПЛК HCFA HCA8 и частотный преобразователь ATV31 через Modbus.
Использую среду разработки GX Works2 1.620W.

Изображение

Действую по информации из статьи
Управление и получение данных не происходит.
Пытался также использовать документацию от Coolmay L02 (тоже клон FX3U), но так же безуспешно.
[+] ST

Код: Выделить всё

IF M8002 OR LDP(TRUE,M90) THEN
	D8120 :=2#1110_0000_1000_0111;
	(* _9.6kb_8e1 *)
	M8125 := TRUE;
	M8196 := TRUE;
	D8397 := K0;	
	D8121 := K0;
END_IF;

(* STATUS *)
ADPRW(M91, H1 , H3 , K3201 , K1 , D28);

(* SYSTEM START *)
IF LDP(TRUE,M92) THEN
	ADPRW(TRUE, K1 , H6 , H2135 , K0 , K4);
END_IF;

(* RESET FAULT *)
IF LDP(TRUE,M93) THEN
	ADPRW(TRUE, K1 , H6 , H2135 , K0 , K128);
END_IF;

(* SET FREQUENCY*)
IF LDP(TRUE,M94) THEN
	ADPRW(TRUE, K1 , H6 , H2136 , K0 , D20);
END_IF;

(* SELECT DIRECTION FORWARD *)
IF LDP(TRUE,M95) THEN
	D30 := K15;
END_IF;

(* SELECT DIRECTION BACKWARD *)
IF LDP(TRUE,M96) THEN
	D30 := K2063;
END_IF;

(* RUN*)
IF LDP(TRUE,M97) THEN
	ADPRW(TRUE, K1 , H6 , H2135 , K0 , D30);
END_IF;
HCFA HCA8 вроде как является клоном Mitsubishi FX3U. Но в каталогах Mitsubishi не нашёл модуля расширения, который содержит одновременно порты RS232 и RS485. Не понятно к какому каналу относится R485.
На модуле расширения указано COM1-RS485, COM2-RS232. Но вроде как COM1 это разъём miniDIN для программирования ПЛК.
Предполагаю, что для ПЛК от HCFA с его модулем расширения надо как-то иначе задать параметры.

Может у кого-то есть рабочий пример получения данных через RS485 Modbus RTU с таким ПЛК.

Andreyit
не первый раз у нас
не первый раз у нас
Сообщения: 395
Зарегистрирован: 06 фев 2020, 16:09
Имя: Андрей
город/регион: Екатеринбург
Поблагодарили: 69 раз

HCFA HCA8 Modbus

Сообщение Andreyit »

Этот клон мицубиши точно так же не поддерживает modbus, как и оригинальный мицубиши. Для modbus, как и в статье, нужен спец. модуль "FX3U-485ADP-MB" - где MB это с поддержкой modbus.
Без модуля есть костыли через RS где посылку нужно ручками составлять с CRC, и принимать.
То что слева у HCA8 есть 485 вообще не говорит, что будет modbus.
Аватара пользователя

Jackson
администратор
администратор
Сообщения: 18747
Зарегистрирован: 17 июн 2008, 16:01
Имя: Евгений свет Брониславович
Страна: Россия
город/регион: Санкт-Петербург
Благодарил (а): 972 раза
Поблагодарили: 1852 раза

HCFA HCA8 Modbus

Сообщение Jackson »

RS-485 - это интерфейс, физика, как электроны по проводам бегают. ModBUS - это протокол, как байты группируются. Разные вещи. Если нигде в описаниях Вы не видите слова ModBUS - значит его там и нет. А порт RS-485 есть.
Andreyit писал(а): 05 окт 2024, 18:06 Без модуля есть костыли через RS где посылку нужно ручками составлять
Это не "костыли" а нормальная процедура обработки пользовательского протокола.
По вопросам работы Форума можно обратиться по этим контактам.

Автор темы
demonlibra
здесь недавно
здесь недавно
Сообщения: 37
Зарегистрирован: 21 сен 2024, 18:17
Имя: Дмитрий
Страна: РФ
Благодарил (а): 10 раз
Поблагодарили: 3 раза

HCFA HCA8 Modbus

Сообщение demonlibra »

В закромах диска GX IEC Developer 7.04 нашёл библиотеку 074bf4f2-0a6c-102b-bc25-001143e88a02_ModbusFX3UMaster_V100.zip, как раз для чтения/записи данных по протоколу Modbus через модули RS232/RS485 без приписки MB.
This function block is used by a Modbus Master FX3U PLC system to read from/write to Modbus Slave devices (using the Modbus RTU protocol over a serial line) using the RS instruction for serial communication. The Modbus Master is connected to the slave devices via serial communication using one or more serial communication options (FX3U-232-BD, FX3U-485-BD or FX3U-485-ADP).
[+]
Библиотеку можно найти в раздаче GX IEC Developer 7.04 на кх...кх...трекере
В GX Works2 программа с этим модулем не компилируется.
Попробую покопаться в содержимом.
Задача сугубо ради интереса. По проводу кинуть команды вперёд, назад и скорость поменять. Потом отключить и забыть ))

Автор темы
demonlibra
здесь недавно
здесь недавно
Сообщения: 37
Зарегистрирован: 21 сен 2024, 18:17
Имя: Дмитрий
Страна: РФ
Благодарил (а): 10 раз
Поблагодарили: 3 раза

HCFA HCA8 Modbus

Сообщение demonlibra »

Использую команду RS2
Судя по документации ответ на команду 06 должен быть идентичен запросу. Но частотник отвечает на все запросы 8601 0203 0061 0000
Удивительно, что CRC 0000
На дисплее частотника всегда nST.

Изображение
[+] ST

Код: Выделить всё

(* CH1 RS2 D8400 *)

IF M8002 OR MEP(M90) THEN
    D8400 := H1C87; (*0001 1100 1000 0111 -> 9600 8E1*)
    D8409 := K200; (*Slave response timeout*)
END_IF;

(* M8161 data bit length TRUE-8bit, FALSE-16bit *)

(*START*)
IF M91 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H2135; (* K8501 Control word address *)
    D302 := H0006; (* K6 START *)
    D303 := HACD5; (* CRC-16 Modbus 0106 3521 0600 *)
END_IF;

(*RESET*)
IF M92 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H2135; (* K8501 Control word address *)
    D302 := H0080; (* K128 RESET *)
    D303 := HCCB7; (* CRC-16 Modbus 0106 3521 8000 *)
END_IF;

RS2(TRUE, D300, K8, K8, K1, D310);
(* Sending request ch1 M8402 *)
(* When sending is completed, the sending request device (M8402) is automatically reset *)
IF MEP(M96) THEN
	SET(TRUE, M8402);
END_IF;

D305.0 := M8063; (* sThis device turns ON when a communication error occurs. *)
D306 := D8063; (* Error code*)

(* RUN Forward *)
IF M93 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H2135; (* K8501 Control word address *)
    D302 := H000F; (* K15 RUN Forward *)
    D303 := HFCD3; (* CRC-16 Modbus 0106 3521 0F00 *)
END_IF;

(* RUN Backward *)
IF M94 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H2135; (* K8501 Control word address *)
    D302 := H080F; (* K2063 RUN Reverse *)
    D303 := H3AD2; (* CRC-16 Modbus 0106 3521 0F08 *)
END_IF;

(* STOP *)
IF M95 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H2135; (* K8501 Control word address *)
    D302 := H100F; (* K4111 STOP *)
    D303 := H30D2; (* CRC-16 Modbus 0106 3521 0F10 *)
END_IF;

Andreyit
не первый раз у нас
не первый раз у нас
Сообщения: 395
Зарегистрирован: 06 фев 2020, 16:09
Имя: Андрей
город/регион: Екатеринбург
Поблагодарили: 69 раз

HCFA HCA8 Modbus

Сообщение Andreyit »

Сниффером вставали? Точно отправляете посылку не задом наперед в каждом байте?
Т.к. смотрите "Если устройство получило запрос, но запрос не может быть обработан, то устройство ответит кодом ошибки" - тут в главе "Какие бывают ошибки запроса Modbus?". У вас код 03 т.е. "Значение, содержащееся в поле данных запроса, является недопустимой величиной".
Отправлять надо прямо, а приходить будут задом наперед.

Автор темы
demonlibra
здесь недавно
здесь недавно
Сообщения: 37
Зарегистрирован: 21 сен 2024, 18:17
Имя: Дмитрий
Страна: РФ
Благодарил (а): 10 раз
Поблагодарили: 3 раза

HCFA HCA8 Modbus

Сообщение demonlibra »

Andreyit писал(а): 07 окт 2024, 16:53 Сниффером вставали?
С таким не знаком.

Спасибо за ссылку. Многое стало понятнее.

Например, у меня такой код

Код: Выделить всё

    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H2135; (* K8501 Control word address *)
    D302 := H0006; (* K6 START *)
    D303 := HACD5; (* CRC-16 Modbus 0106 3521 0600 *)
Запрос хранится в регистрах начиная с D300

D300 := H0601; (* 01 Slave adress, 06 Code write word *)
01 адрес частотника. Частотник отвечает, значит правильно.
06 код команды. Функциональный код ошибки 86, значит код команды отправлена верно.

D301 := H2135; (* K8501 Control word address *)
Из документации на ATV31_communication_variables_EN_1624595_04
Modbus address 8501 R/W
8501 = H2135

D302 := H0006; (* K6 START *)
6 записываем в адрес 8501

D303 := HACD5; (* CRC-16 Modbus 0106 3521 0600 *)
Вот тут я не уверен, в какой очерёдности вводить цифры для расчёт CRC
Я вводил так 0106 3521 0600 и судя по документации на частотник это неверно
Надо вводить 0106 2135 0006 и менять местами байты CRC
CRC FA13
Меняем местами байты и заносим в D303 := 13FA

Команда RS2
RS2(TRUE, D300, K8, K8, K1, D310);

Завтра попробую

https://www.se.com/ng/en/download/document/1624597/
Изображение
Последний раз редактировалось demonlibra 07 окт 2024, 18:26, всего редактировалось 1 раз.

Andreyit
не первый раз у нас
не первый раз у нас
Сообщения: 395
Зарегистрирован: 06 фев 2020, 16:09
Имя: Андрей
город/регион: Екатеринбург
Поблагодарили: 69 раз

HCFA HCA8 Modbus

Сообщение Andreyit »

demonlibra писал(а): 07 окт 2024, 18:01 С таким не знаком
Берете usb-rs485 и любой прослушиватель порта тип "Advanced Serial Port Monitor" или "Device monitoring studio" и смотрите что уходит и приходит.

Автор темы
demonlibra
здесь недавно
здесь недавно
Сообщения: 37
Зарегистрирован: 21 сен 2024, 18:17
Имя: Дмитрий
Страна: РФ
Благодарил (а): 10 раз
Поблагодарили: 3 раза

HCFA HCA8 Modbus

Сообщение demonlibra »

Завтра попробую.
Подозреваю, что я просто запутался в "байто-верчении" ))
Аватара пользователя

Jackson
администратор
администратор
Сообщения: 18747
Зарегистрирован: 17 июн 2008, 16:01
Имя: Евгений свет Брониславович
Страна: Россия
город/регион: Санкт-Петербург
Благодарил (а): 972 раза
Поблагодарили: 1852 раза

HCFA HCA8 Modbus

Сообщение Jackson »

demonlibra писал(а): 07 окт 2024, 18:01
Andreyit писал(а): 07 окт 2024, 16:53 Сниффером вставали?
С таким не знаком
Рекомендую познакомиться. Помогает понять и наглядно увидеть происходящее. Без этого Вы только догадываетесь, какие там посылки летают на самом деле.
По вопросам работы Форума можно обратиться по этим контактам.

Автор темы
demonlibra
здесь недавно
здесь недавно
Сообщения: 37
Зарегистрирован: 21 сен 2024, 18:17
Имя: Дмитрий
Страна: РФ
Благодарил (а): 10 раз
Поблагодарили: 3 раза

HCFA HCA8 Modbus

Сообщение demonlibra »

Разобрался. Спасибо всем за помощь.

Инструкция RS2 отправляет байты данных в порядке Lo-Hi.
Частотник читает данные в порядке Hi-Lo, а CRC в порядке Lo-Hi.
Т.е. при записи данных в регистры, байты данных меняем местами.
При расчёте и записи в регистры CRC пишем как есть.

Изображение Изображение Изображение
[+] Пример рабочей программы на ST для AVT31

Код: Выделить всё

IF M8002 OR MEP(M90) THEN
    D8400 := H1C87; (* D8400 CH1 RS2 *) (* 0001 1100 1000 0111 -> 9600 8E1 *)
    D8409 := K200; (*Slave response timeout*)
    RST(TRUE, M8403);
    RST(TRUE, M8161); (* data bit length TRUE-8bit, FALSE-16bit *)
    D300 := H0; D301 := H0; D302 := H0; D303 := H0;
    D310 := H0; D311 := H0; D312 := H0; D313 := H0;
END_IF;

RS2(M91, D300, K8, K7, K1, D310); (*READ 7 byte*)
RS2(M92 OR M93 OR M94 OR M95 OR M96 OR M97, D300, K8, K8, K1, D310); (*WRITE 8 byte*)

IF MEP(M99) THEN
	RST(TRUE, M8403); (* M8403 turns ON when receiving is completed *)
	(* While M8403 is ON, the PLC cannot receive any receive data *)
	SET(TRUE, M8402); (* When M8402 is set to ON, the PLC starts to send *)
	(* When sending is completed, the sending request device (M8402) is automatically reset *)
END_IF;

D305.0 := M8063; (* M8063 turns ON when a communication error occurs *)
D306 := D8063; (* D8063 stores the corresponding error code *)

(* READ DATA - from slave 1, start from K8501, read 1 word *)
IF M91 THEN
    D300 := H0301; (* 1byte - 01 Slave adress, 2byte - 03 Code read words *)
    D301 := H3521; (* Control word address: 2bytes PLC Lo-Hi H3521 -> VFD Modbus Hi-Lo H2135=K8501 *)
    D302 := H0100; (* Number of words: 2bytes PLC Lo-Hi H0100 -> Modbus VFD Hi-Lo H0001*)
    D303 := H389E; (* 0103 2135 0001 : CRC 389E *)
END_IF;

(*START need excecute before run forward or backward *)
IF M92 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3521; (* K8501 Control word address *)
    D302 := H0600; (* K6 START *)
    D303 := HFA13; (* 0106 2135 0006 : CRC FA13 *)
END_IF;

(*RESET*)
IF M93 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3521; (* K8501 Control word address *)
    D302 := H8000; (* K128 RESET *)
    D303 := H5892; (* 0106 2135 0080 : CRC 5892 *)
END_IF;

(* RUN Forward *)
IF M94 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3521; (* K8501 Control word address *)
    D302 := H0F00; (* K15 RUN Forward *)
    D303 := HFCD3; (* 0106 2135 000f : CRC FCD3 *)
END_IF;

(* RUN Backward *)
IF M95 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3521; (* K8501 Control word address *)
    D302 := H0F08; (* K2063 RUN Reverse *)
    D303 := H3CD4; (* 0106 2135 080f : CRC 3CD4 *)
END_IF;

(* STOP *)
IF M96 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3521; (* K8501 Control word address *)
    D302 := H0040; (* K16384 STOP *)
    D303 := H38A2; (* 0106 2135 4000 : CRC 38A2 *)
END_IF;

(* WRITE SPEED K8502=H2136*)
IF M97 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3621; (* K8502 Control word address *)
    D302 := HC800; (* 20Hz -> K0200 = H00C8 *)
    D303 := H6E62; (* 0106 2136 00c8 : CRC 6E62 *)
END_IF;
[+] Расчёт CRC на python

Код: Выделить всё

def modbusCrc(msg):
    crc = 0xFFFF
    for n in range(len(msg)):
        crc = crc ^ msg[n]
        for i in range(8):
            if crc & 1:
                crc = crc >> 1
                crc = crc ^ 0xA001
            else:
                crc = crc >> 1
    return crc

msg = list()

msg.append(bytes.fromhex("0103 2135 0001"))

msg.append(bytes.fromhex("0106 2135 0006"))
msg.append(bytes.fromhex("0106 2135 0080"))
msg.append(bytes.fromhex("0106 2135 000F"))
msg.append(bytes.fromhex("0106 2135 080F"))
msg.append(bytes.fromhex("0106 2135 100F"))
msg.append(bytes.fromhex("0106 2136 00C8"))

msg.append(bytes.fromhex("0106 2135 4000"))

print()

for i in range(len(msg)):
    crc = modbusCrc(msg[i])
    print()

    ba = crc.to_bytes(2, byteorder='little')
    print(f'D303 := H{ba[1]:02X}{ba[0]:02X}; (* {msg[i].hex(" ",2).upper()} : CRC {crc:04X} *)')
    print()
[+] Подключение
Подключение на стороне частотника, как в статье ATV312 Schneider “Modbus RTU” FX3U Tutorial.
На стороне ПЛК подключение только двумя проводами в два верхних вывода DA и DB.
Выводы TX, RX и заземление оставляем пустыми.

При отправке пакета данных кратковременно загорается индикатор DA.
При успешной отправке и получении пакета данных кратковременно загораются индикаторы DA и DB.
При некорректном формировании пакета данных частотник не ответит и кратковременно загорится только индикатор DA.
[+] Ссылки по теме

Автор темы
demonlibra
здесь недавно
здесь недавно
Сообщения: 37
Зарегистрирован: 21 сен 2024, 18:17
Имя: Дмитрий
Страна: РФ
Благодарил (а): 10 раз
Поблагодарили: 3 раза

HCFA HCA8 Modbus

Сообщение demonlibra »

Продолжаю веселиться

Вроде как в документации FX3U должен уметь выполнять инструкцию FCN188 CRC.
Компилятор ошибок не выдаёт, но симулятор ничего не считает. На ПЛК не проверял.

Написал на ST функцию расчёта CRC Modbus.
[+] Код

Код: Выделить всё

(* Заносим слова в массив для обработки в цикле*)
dataArray[0] := Word0;
dataArray[1] := Word1;
dataArray[2] := Word2;

crcCalc := HFFFF; (* Начальный полином *)

FOR counterWords:=0 TO 2 DO (* Перебираем слова в массиве *)
	dataWord := dataArray[counterWords];
	dataByte[1] := SHR(dataWord,8); (* Второй байт слова*)
	SWAP(TRUE,dataWord);
	dataByte[0] := SHR(dataWord,8); (* Первый байт слова*)
	
	FOR counterByte:=0 TO 1 DO (*Перебираем байты слова *)
		crcCalc := crcCalc XOR dataByte[counterByte];
		FOR counterBit:=1 TO 8 DO (*Перебираем и сдвигаем биты одного байта*)
			BON(TRUE , crcCalc, 0, lsb); (* Получаем первый бит *)
			IF  lsb THEN (* Если первый бит = 1 *)
				crcCalc := SHR(crcCalc,1);
				crcCalc := crcCalc XOR HA001;
			ELSE
				crcCalc := SHR(crcCalc,1);
			END_IF;
		END_FOR;
	END_FOR;
	
END_FOR;
crc_my := crcCalc; (* Возврат результата *)
[+] Список переменных

Код: Выделить всё

"project"
"Class"	"Label Name"	"Data Type"	"Constant"	"Comment"
"VAR_INPUT"	"Word0"	"WORD"	""	""
"VAR_INPUT"	"Word1"	"WORD"	""	""
"VAR_INPUT"	"Word2"	"WORD"	""	""

"VAR"	"counterWords"	"INT"	""	""
"VAR"	"counterByte"	"INT"	""	""
"VAR"	"counterBit"	"INT"	""	""
"VAR"	"lsb"	"BOOL"	""	""

"VAR"	"dataArray"	"ARRAY [0..2] OF WORD"	""	""
"VAR"	"dataWord"	"WORD"	""	""
"VAR"	"dataByte"	"ARRAY [0..1] OF WORD"	""	""
"VAR"	"crcCalc"	"WORD"	""	""
[+] Пример использования

Код: Выделить всё

D303 := crc_my(D300, D301, D302);

Автор темы
demonlibra
здесь недавно
здесь недавно
Сообщения: 37
Зарегистрирован: 21 сен 2024, 18:17
Имя: Дмитрий
Страна: РФ
Благодарил (а): 10 раз
Поблагодарили: 3 раза

HCFA HCA8 Modbus

Сообщение demonlibra »

Проверил на ПЛК функцию CRC. Работает.
Нашёл меню, в котором симулятор выводит команды, которые не может выполнить.
Изображение

Логика управления частотником описана схемой в документе Altivar 31 Communication variables User's manual
Изображение

В итоге получил следующий код для управления частотником Schneider Electric ATV31 через RS485:
[+] Код ST

Код: Выделить всё

IF M8002 THEN
    D8400 := H1C87; (* Параметры связи для команды RS2 через Ch1 *) (* 0001 1100 1000 0111 -> 9600 8E1 *)
    D8409 := K10; (* Задержка включения флагов M8409 и M8403 при НЕ получении ответа: 10x10 = 100ms *)
    M8161 := FALSE; (* data bit length TRUE-8bit, FALSE-16bit *)
    ZRST(TRUE , D300 , D303); (* Очистка памяти отправляемых данных *)
    ZRST(TRUE , D310 , D313); (* Очистка памяти принимаемых данных*)
    errorsCount := 0; (* Очистка счётчика ошибок *)
END_IF;

errorBit := M8063; (* M8063 включается при ошибке связи *)
errorsCode := D8063; (* D8063 хранит код ошибки связи *)

(* Заносим команды в очередь - inQueue *)
SET ( MEF(buttonEnable), atvReset_inQueue); (* Сброс аварийного состояния частотника *)
SET ( MEP(carriageMoveEnable) OR MEF(carriageMoveEnable), atvShutdown_inQueue); (* Переход в режим READY_TO_SWITCH_ON перед запуском или при остановке *)
SET ( MEP( carriageSpeedSlow) OR MEP (carriageSpeedWork) OR MEP(carriageSpeedFast), atvWriteSpeed_inQueue); (* Смена скорости *)
SET ( MEP(carriageMotorForward), atvForward_inQueue); (* Движение вперёд *)
SET ( MEP(carriageMotorBackward), atvBackward_inQueue); (* Движение назад *)
SET ( MEP(M8013), atvReadData_inQueue); (* Запрашивать состояние частотника каждую секунду *)

(* Измерение времени работы команды RS2 *)
SET(MEP(M8402), RS2running);
RST(MEP(M8403), RS2running);
IF RS2running THEN counter := counter + 1; END_IF; (* Счётчик циклов работы команды RS2 *)
IF MEP(M8403) THEN
	timeRS2 := counter * D8010; (* Время x0.1мс работы команды RS2 *)
	counter := 0;
END_IF;


TOFdelay ( IN:= M8402 , PT:=T#50ms, Q:=channelBussy); (* Минимальное время между отправкой команд *)
(* При задержке меньше 30 мс возникают ошибки *)

RS2 ( atvReadData_inProgress, D300, K8, K7, K1, D310); (* Команда для чтения данных из частотника (пакет 7 байт) *)
RS2 ( NOT atvReadData_inProgress, D300, K8, K8, K1, D310); (* Команда записи данных в частотник (пакет 8 байт) *)

IF MEP(M8403) THEN
	M8403 := FALSE; (* Перед отправкой очередного пакета необходимо сбросить M8403 *)
	IF (D300=H0601 AND D303=D313) OR (D300=H0301 AND D300=D310) THEN (* Проверка отправленного и полученного CRC *)
		IF atvReset_inProgress THEN
			atvReset_inQueue := FALSE;
			M8063 := FALSE; (* Сброс бита ошибки передачи данных *)
			D8063 := 0; (* Сброс кода ошибки передачи данных *)
		END_IF;
		RST(atvShutdown_inProgress, atvShutdown_inQueue);
	 	RST(atvWriteSpeed_inProgress, atvWriteSpeed_inQueue);
	 	RST(atvForward_inProgress, atvForward_inQueue);
	 	RST(atvBackward_inProgress, atvBackward_inQueue);
	 	RST(atvReadData_inProgress, atvReadData_inQueue);
	ELSE
	 	errorsCount := errorsCount + 1;
	END_IF;
	atvReset_inProgress := FALSE;
	atvShutdown_inProgress := FALSE;
	atvWriteSpeed_inProgress := FALSE;
	atvForward_inProgress := FALSE;
	atvBackward_inProgress := FALSE;
	atvReadData_inProgress := FALSE;
	(*ZRST(TRUE , D310 , D313);*)
END_IF;

(* FAULT RESET - Сброс ошибок частотника *)
IF atvReset_inQueue AND NOT M8402 AND NOT channelBussy AND NOT M8403 THEN
	atvShutdown_inQueue := FALSE;
	atvForward_inQueue := FALSE;
	atvBackward_inQueue := FALSE;
	atvReadData_inQueue := FALSE;
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3521; (* K8501 Control word address *)
    D302 := H8000; (* H80 FAULT RESET *)
    CRC( TRUE , D300 , K6 , D303 );
	M8402 := TRUE; (* Start sending package to ATV*)
	atvReset_inProgress := TRUE; (* RESET command was send *)
END_IF;

(* SHUTDOWN - Необходимо выполнить перед запуском и при остановке *)
IF atvShutdown_inQueue AND NOT M8402 AND NOT channelBussy AND NOT M8403 THEN
	atvForward_inQueue := FALSE;
	atvBackward_inQueue := FALSE;
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3521; (* K8501 Control word address *)
    D302 := H0600; (* H6 SHUT DOWN *)
    CRC( TRUE , D300 , K6 , D303 );
	M8402 := TRUE;
	atvShutdown_inProgress := TRUE;
END_IF;

(* WRITE SPEED - Задание скорости *)
IF atvWriteSpeed_inQueue AND NOT M8402 AND NOT channelBussy AND NOT M8403 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3621; (* K8502 Control word address *)
    IF carriageSpeedSlow THEN D302 := K120; (* 12.0 Hz  *)
    	ELSIF carriageSpeedWork THEN D302 := K200;
    	ELSIF carriageSpeedFast THEN D302 := K600;
    	ELSE D302 := 0;
    END_IF;
	SWAP(TRUE, D302);
    CRC( TRUE , D300 , K6 , D303 );
	M8402 := TRUE; (* Start sending package to ATV *)
	atvWriteSpeed_inProgress := TRUE; (* Команда смены скорости отправлена *)
END_IF;

(* ENABLE OPERATION - FORWARD - Вращение вперёд *)
IF atvForward_inQueue AND NOT M8402 AND NOT channelBussy AND NOT M8403 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3521; (* K8501 Control word address *)
    D302 := H0F00; (* HF ENABLE OPERATION *)
    CRC( TRUE , D300 , K6 , D303 );
	M8402 := TRUE; (* Start sending package to ATV*)
	atvForward_inProgress := TRUE; (* Команда FORWARD отправлена *)
END_IF;

(* ENABLE OPERATION - BACKWARD - Вращение назад *)
IF atvBackward_inQueue AND NOT M8402 AND NOT channelBussy AND NOT M8403 THEN
    D300 := H0601; (* 01 Slave adress, 06 Code write word *)
    D301 := H3521; (* K8501 Control word address *)
    D302 := H0F08; (* K2063 RUN BACKWARD *)
    CRC( TRUE , D300 , K6 , D303 );
	M8402 := TRUE; (* Start sending package to ATV*)
	atvBackward_inProgress := TRUE; (* Команда BACKWARD отправлена *)
END_IF;

(* READ DATA - Чтение данных из памяти частотника *)
IF atvReadData_inQueue AND NOT M8402 AND NOT channelBussy AND NOT M8403 THEN
    D300 := H0301; (* 1byte - 01 Slave adress, 2byte - 03 Code read words *)
    D301 := H3521; (* Control word address: 2bytes PLC Lo-Hi H3521 -> VFD Modbus Hi-Lo H2135=K8501 *)
    D302 := H0100; (* Number of words: 2bytes PLC Lo-Hi H0100 -> Modbus VFD Hi-Lo H0001*)
    CRC( TRUE , D300 , K6 , D303 );
	M8402 := TRUE;
	atvReadData_inProgress := TRUE;
END_IF;
[+] Переменные

Код: Выделить всё

"project"
"Class"	"Label Name"	"Data Type"	"Constant"	"Device"	"Address"	"Comment"
"VAR"	"errorBit"	"BOOL"	""	""	""	""
"VAR"	"errorsCode"	"INT"	""	""	""	""
"VAR"	"errorsCount"	"INT"	""	""	""	""
"VAR"	"channelBussy"	"BOOL"	""	""	""	""
"VAR"	"atvReadData_inProgress"	"BOOL"	""	""	""	""
"VAR"	"atvReset_inQueue"	"BOOL"	""	""	""	""
"VAR"	"atvShutdown_inQueue"	"BOOL"	""	""	""	""
"VAR"	"atvWriteSpeed_inQueue"	"BOOL"	""	""	""	""
"VAR"	"atvForward_inQueue"	"BOOL"	""	""	""	""
"VAR"	"atvBackward_inQueue"	"BOOL"	""	""	""	""
"VAR"	"atvReadData_inQueue"	"BOOL"	""	""	""	""
"VAR"	"atvReset_inProgress"	"BOOL"	""	""	""	""
"VAR"	"atvShutdown_inProgress"	"BOOL"	""	""	""	""
"VAR"	"atvWriteSpeed_inProgress"	"BOOL"	""	""	""	""
"VAR"	"atvForward_inProgress"	"BOOL"	""	""	""	""
"VAR"	"atvBackward_inProgress"	"BOOL"	""	""	""	""
"VAR"	"TOFdelay"	"TOF_10"	""	""	""	""
"VAR"	"counter"	"INT"	""	""	""	""
"VAR"	"RS2running"	"BOOL"	""	""	""	""
"VAR"	"timeRS2"	"INT"	""	""	""	""
Между началом отправки данных (включение M8402) и завершением приёма данных (включение M8403) проходит ~40 мс.
На время цикла это не влияет. У меня это ~4 мс.
Ответить

Вернуться в «Приводная техника»