Популярно о Модбас https://sites.google.com/site/fieldb...odbuseducation
Захват-2.png
Популярно о Модбас https://sites.google.com/site/fieldb...odbuseducation
Захват-2.png
Последний раз редактировалось petera; 28.10.2014 в 15:11.
Мой канал на ютубе
https://www.youtube.com/c/ПетрАртюков
Мой канал на РУТУБЕ
https://rutube.ru/channel/23641433/
Библиотека ГМ для СП300
https://disk.yandex.com/d/gHLMhLi8x1_HBg
Насколько я понимаю, соответствие RS-485 будет обеспечено терминалом при передаче (если порт правильно настроен), а соответствие стандарту Modbus и правильность ответа проверяет уже скрипт.
Вот новая функция, проверить по-прежнему нет возможностиКод:const BYTES_PER_REG = 2; const N_RETRIES = 3; const RETRY_TIMEOUT = 1000; //ms BOOL MWrites(int comID, int staID, int objType, int add1, int regs, void* pRegs) { BYTE bSend[256], bRecieve[256], i; WORD bBytesToSend = 0, bBytesRecieved = 65535; BYTE nRetry = N_RETRIES; //Количество попыток повтора BYTE offset_PSW_log; int CrcSum; switch (comID) { case DOWNLOAD: offset_PSW_log = 60; break; case PLC: offset_PSW_log = 70; break; default: return Writes(comID, staID, objType, add1, regs, pRegs); //don't know what to do } bSend[0] = staID; switch (objType) { case MODBUS_RTU_REGS_4X: bSend[1] = 0x10; break; default: return Writes(comID, staID, objType, add1, regs, pRegs); //don't know what to do } bSend[2] = HIBYTE(add1); bSend[3] = LOBYTE(add1); bSend[4] = HIBYTE(regs); bSend[5] = LOBYTE(regs); bSend[6] = regs * BYTES_PER_REG; bBytesToSend = 7; for (i=0; i<regs*2; i++) { bSend[bBytesToSend] = ((BYTE*)pRegs)[i]; bBytesToSend++; } CrcSum = Crc(bSend, bBytesToSend); bSend[bBytesToSend] = LOBYTE(CrcSum); bSend[bBytesToSend + 1] = HIBYTE(CrcSum); bBytesToSend += 2; if (bBytesToSend > 256) return FALSE; Enter(comID);//Захватить порт PLC do { if (bBytesRecieved != 65535) { //Была ошибка связи PSW[offset_PSW_log+1]++; if (bBytesRecieved != 0) // Ошибка данных PSW[offset_PSW_log+3]++; //else //Таймаут // PSW[offset_PSW_log+2]++; } Send(comID, bSend, bBytesToSend);//Отправить команду bBytesRecieved = Receive(comID, bRecieve, 256, RETRY_TIMEOUT, 6);//Получить ответ (тайм-аут 1000мс) } while ((bBytesRecieved == 0 || //Если данные получены bRecieve[0] != staID || //От правильного устройства bRecieve[1] != bSend[1] || //Правильной функцией MAKEWORD(bRecieve[3], bRecieve[2]) != add1 || // По правильному адресу MAKEWORD(bRecieve[5], bRecieve[4]) != regs || // Правильное количество регистров Crc(bRecieve, bBytesRecieved) != 0 //Контрольная сумма в порядке ) && (nRetry--)>0); //... то всё ок, иначе отнимаем попытку и, если они остались, пытаемся ещё Leave(comID);//Освободить порт if (nRetry>0) { //Если попытки остались, значит, последняя попытка связи была успешной PSW[offset_PSW_log]++; return TRUE; } else return FALSE; }
Последний раз редактировалось SokolovS; 03.11.2014 в 11:40.
Скрипт не проверяет ситуацию ошибок второго типа, например если мастер пытается записать регистр в слейв по несуществующему адресу регистра, то в ответ будет послан пакет из 5 байт, а не из 8.
//[0]-адрес устройства
//[1]-Код функции ModbusRTU с индикацией ошибки-запись нескольких регистров 0x90
//[2]-код ошибки (0x02)
//[3]-ст.байт CRC
//[4]-мл.байт CRC
см пост#620
ЗЫ. Стандартые процедуры обмена при ошибках записывают в регистре PSW61(PSW71) число не успешных попыток обмена без учета повторных попыток, а в PSW62(PSW72) и PSW64(PSW73) с учетом повторных попыток, т.е. если число повторов задано 3, то при тайм-ауте PSW61(PSW71)=N, а PSW62(PSW72)=3хN, где N-число команд записи
Последний раз редактировалось petera; 28.10.2014 в 16:01.
Мой канал на ютубе
https://www.youtube.com/c/ПетрАртюков
Мой канал на РУТУБЕ
https://rutube.ru/channel/23641433/
Библиотека ГМ для СП300
https://disk.yandex.com/d/gHLMhLi8x1_HBg
А теперь?![]()
По задумке эта строка проверяет чего там вернуло устройство, и в случае возвращённой ошибки там будет не 0х10, а 0х90. Скрипт ещё несколько раз помучает устройство и отстанет, записав всё в ошибки. По задумке.Код:bRecieve[1] != bSend[1] || //Правильной функцией
Если нам не важна причина ошибок, тот же неверный адрес регистра, для дальнейшего принятия решений, то тогда можно ограничится и просто констатацией ошибки.
Мой канал на ютубе
https://www.youtube.com/c/ПетрАртюков
Мой канал на РУТУБЕ
https://rutube.ru/channel/23641433/
Библиотека ГМ для СП300
https://disk.yandex.com/d/gHLMhLi8x1_HBg
Я не вижу других вариантов
Штатные функции не поддерживают такого и смысла расширять возможности нет
Самое интересное, что похоже без наших усилий в регистры PSW62(PSW72) панель и так сама пишет даже для команд Send() и Receive()
Регистры PSW63(PSW73) проверяю.
ЗЫ PSW60(PSW70) (Успешные попытки) автоматически не обновляются
Мой канал на ютубе
https://www.youtube.com/c/ПетрАртюков
Мой канал на РУТУБЕ
https://rutube.ru/channel/23641433/
Библиотека ГМ для СП300
https://disk.yandex.com/d/gHLMhLi8x1_HBg
В общем тайм-аут Receive() вызывает автоматическое увеличение PSW62(PSW72) на 1
PSW60(PSW71), PSW61(PSW71), PSW63(PSW73) автоматически не увеличиваются.
Мой канал на ютубе
https://www.youtube.com/c/ПетрАртюков
Мой канал на РУТУБЕ
https://rutube.ru/channel/23641433/
Библиотека ГМ для СП300
https://disk.yandex.com/d/gHLMhLi8x1_HBg
Правда? Хм... Ну убрал тогда таймауты
Помогите с проблемой: создаю проект (панель мастер, частотник слэцв) в проекте создаю две кнопки управления (пуск и стоп чп), в настройках этими кнопками указываю Регистр: 0х, адрес регистра пуска 0 для стоп 1. загружаю проект в панель, перезагружаю ее, все работает: нажимаю на пуск на частотнике загорается кнопка пуск - частотник стартует, нажимаю стоп - на частотник приходит команда стоп, частотник останавливается. все ок. на этом этапе нет проблем.
в проекте создаю "цифровой дисплей" регистр 4х (инпутЪ), адрес 1 (должен отображать частоту на выходе частотника), также добавляю цифровой ввод регистр 3х (холдинг) (типо задание Hz).
гружу в панель. перезагружаю ее и тут возникают проблемы, вылазиет окно в котором сообщается: потеря связи с плк.
ожидание в настройках панели выставил 250мс. когда были только кнопки проблем небыло со связью.