Работа с Modbus RTU
- Войдите на сайт для отправки комментариев
Здравствуйте. Имеется частотный преобразователь, подключаемый по интерфейсу RS485 и работающий по протоколу Modbus RTU. Так же имеется USB to RS485 Converter. С помощью программы QModbus, мне удалось прочитать нужный мне регистр и получить значение.
Так же имеется Arduino Uno и преобразователь MAX 485, RS485 TTL.
Подключал по вот такой вот схеме:
Только у меня не задействованы провода на VCC и GND, так как когда я их подключаю, перестает работать соединение с ПЧ.
Вот фото подключения:
Можно ли вообще с помощью Arduino, считать нужный мне регистр и вывести его через Serial.Print в мониторе порта Arduino?
Подключение RS485 в ПЧ подключается 2 проводами виой пары, на A+ и B-, так же там имеются входа под 5V и GND, но они не задействованы.





Что значит "имеются входа под 5V и GND, но они не задействованы."? Как без них передача будет работать?
А считать можно с помощью библиотеки modbusrtu.
Это значит что к ПЧ подключено 2 провода + и - и этого достаточно, чтобы работал RS 485 интерфейс. Возможно я что то не так делаю)
Нет не достаточно. + - или А В это сигнальные. Питание на том же разёме крайние пины. Микросхему интерфейса запитать надо. Как на схеме.
Вот так сейчас выглядит моё подключение.
Но когда я подсоединяю VCC и GND к Arduino, перестает работать USB конвертер и больше не передает данные.
Можете подсказать, как правильно подключить? Я так понял нужно из самого ПЧ брать 5V и GND, присоединять к MAX485 и уже от него на ардуину?
Плату USB to RS485 Converter питать необходимо. Связывать её землю и питание с соответствующими ПЧ ненужно. Первая схема в #1 верная. Назначение разема USB с зеленым раземчиком какое? Если для запитки USB to RS485 Converter то чего подключили на A и B?
...
Вот какой парадокс. Когда я не питаю USB to RS485 и он подключен как на схеме, всё работает. Как только я даю питание на ардуино, USB to RS485 перестает работать.
В общем запитал 5V и GND ПЧ с MAX485, всё заработало. Работает как USB to RS485, так и сам Arduino.
А если питаю MAX485 от питания Arduino, USB to RS485 перестает работать)
Вроде бы разобрался. Теперь нужен скетч для теста. Никто не подскажет, где можно найти пример, опроса допустим 29 регистра Modbus?
В примерах библиотеки есть чтение регистра. Достаточно свой номер подставить.
А можно ссылочку на библиотеку? (:
https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino
simple_master.ino
Еще глупый вопрос, как вывести в монитор порта Arduino, то что он принимает? :)
И что нужно здесь указывать? :)
В общем попытаюсь описать всё подробно.
У меня ПЧ висит на 4 COM порте, ардуино висит на 3 COM порте.
Всё соеднинено через MAX485, как на фото которые выше.
ПЧ имеет BUS адрес #2.
Как мне правильно обратиться к ПЧ через Arduino, считать 29 регистр и вывести его в мониторе порта Arduino?
У меня ПЧ висит на 4 COM порте, ардуино висит на 3 COM порте.
В каком смысле?)))
В общем вот что получилось:
Скетч:
Терминал Termite:
Терминал Arduino:
Я так понимаю, приём идет, так как и RX на Arduino мигает.
Но как перевести эту T, в значение? Должно быть не T, а 1,500.
У вас в программе нет вывода в терминал ардуины. Откуда там что берётся? С линии 485? Так там живут не буквы а двоичные данные. В инициализации третий параметр - номер ноги разрешения передачи модуля 485. На схеме провод есть в инициализации 0. Подключить модуль 485 к ардуине и одновременно к компьютеру можно при условии установки 1к резисторов между модулем и ардуиной. Иначе будет конфликт. Но и потом будет конфликт передачи. 485 надо вешать на софтком, если хотите получать с него данные на ардуину и выводить их в буквенном виде на компьютер.
Вот смотрите:
telegram.u16RegAdd = 29; // Это адрес регистра, который легко читается через USB to RS485 в программе QModBus telegram.u16CoilsNo = 2; // Это номер поля, в котором видно параметр 1500, как на скриншоте сверху.Что я делаю неправильно?
Вот что пишет в Termite:
Я так понимаю это запрос который отправляется на мой ПЧ, а как увидеть ответ самого ПЧ?
Подключал и через резистор на 1кОм и на 120 Ом. Толку нет.
Да. Это ваш запрос. Если нет ответа, то скорее всего ваш запрос не доходит до устройства. Может быть по тому, что у него адрес 2 , а у вас в запросе 1?
Раньше был 2, сейчас 1.
предлагаю мой вариант как считать из модбаса и отправить на сериал. Только зачем тут конвертер usb to RS485?
Подключаем по схеме
Скетч мастера
// Модбас подключить к софтсериалу #include <SoftwareSerial.h> SoftwareSerial Serial100(7, 8); // 7 - Rx; 8 - Tx; // Ниже переменные для модбаса int _modbusMasterDataTable_4_reg_1[1]; int _modbusMasterAddressTable_4_reg_1[1] = {29}; byte _modbusMasterBufferSize = 0; byte _modbusMasterState = 1; long _modbusMasterSendTime; byte _modbusMasterLastRec = 0; long _modbusMasterStartT35; byte _modbusMasterBuffer[64]; byte _modbusMasterCurrentReg = 0; byte _modbusMasterCurrentVariable = 0; struct _modbusMasterTelegramm { byte slaveId; byte function; int startAddres; int numbeRegs; int valueIndex; }; _modbusMasterTelegramm _modbusTelegramm; long _startTimeMasterRegs[1]; long _updateTimeMasterRegsArray[] = {2000}; const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16}; // тут уже наши переменные int Frequency = 0; // переменная частоты, куда будет записываться данные из регистра 29 Holding Registers модбаса long previousMillis = 0; // храним время последнего обновления вывода в сериал порт long interval = 1; // время интервала обновления информации в сериал порте, сек - 1c void setup() { Serial.begin (9600); // для монитора порта - используем железный порт ардуино Serial100.begin(19200); // софтсериал модбаса pinMode(10, OUTPUT); // пин DE RE RS-485 НЕ МЕНЯТЬ! digitalWrite(10, LOW); for(int i=0; i<1; i++) {_startTimeMasterRegs[i] = millis();} } void loop() { //Плата:1 Frequency = (_modbusMasterDataTable_4_reg_1[0]); // чтение данных из регистра 29 Holding Registers модбаса и запись в переменную ///// периодически скидываем переменную Frequency в монитор порта unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval*1000) { Serial.println (Frequency); previousMillis = currentMillis;} ////// всё что ниже - для модбаса switch ( _modbusMasterState ) { case 1: _nextModbusMasterQuery(); break; case 2: pollModbusMaster(); break; } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));} } int modbusCalcCRC(byte length, byte bufferArray[]) { unsigned int temp, temp2, flag; temp = 0xFFFF; for (unsigned char i = 0; i < length; i++) { temp = temp ^ bufferArray[i]; for (unsigned char j = 1; j <= 8; j++) { flag = temp & 0x0001; temp >>= 1; if (flag) temp ^= 0xA001; } } temp2 = temp >> 8; temp = (temp << 8) | temp2; temp &= 0xFFFF; return temp; } void _nextModbusMasterQuery() { _selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable); if (_modbusMasterCurrentReg == 0) return; _createMasterTelegramm(); _modbusMasterSendQuery(); } void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar) { bool isNeeded = 1; if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;} if (!(_isTimer ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;} if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}} if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;} byte temp; switch (oldReg) { case 1: temp = 1; break; } if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;} _startTimeMasterRegs[oldReg -1] = millis(); if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} _modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return; } void _createMasterTelegramm() { switch (_modbusMasterCurrentReg) { case 1: _modbusTelegramm.slaveId = 1; switch (_modbusMasterCurrentVariable) { case 1: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 29; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 0; break; } break; } } void _modbusMasterSendQuery() { byte currentIndex = _modbusTelegramm.valueIndex; _modbusMasterBuffer[0] = _modbusTelegramm.slaveId; _modbusMasterBuffer[1] = _modbusTelegramm.function; _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres ); _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres ); switch ( _modbusTelegramm.function ) { case 3: _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs ); _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs ); _modbusMasterBufferSize = 6; break; } _modbusMasterSendTxBuffer(); _modbusMasterState = 2; } void _modbusMasterSendTxBuffer() { byte i = 0; int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer ); _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8; _modbusMasterBufferSize++; _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff; _modbusMasterBufferSize++; digitalWrite(10, 1 ); delay(3); Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize ); digitalWrite(10, 0 ); Serial100.flush(); _modbusMasterBufferSize = 0; _modbusMasterSendTime = millis(); } void pollModbusMaster() { if (_modbusTelegramm.slaveId == 0) { _modbusMasterState = 1; return;} if (_isTimer(_modbusMasterSendTime, 1000)) { _modbusMasterState = 1; return; } byte avalibleBytes = Serial100.available(); if (avalibleBytes == 0) return; if (avalibleBytes != _modbusMasterLastRec) { _modbusMasterLastRec = avalibleBytes; _modbusMasterStartT35 = millis(); return; } if (!(_isTimer(_modbusMasterStartT35, 3 ))) return; _modbusMasterLastRec = 0; byte readingBytes = _modbusMasterGetRxBuffer(); if (readingBytes < 5) { _modbusMasterState = 1; return ; } byte exeption = validateAnswer(); if (exeption != 0) { _modbusMasterState = 1; return; } switch ( _modbusMasterBuffer[1] ) { case 3: get_FC3(4); break; } _modbusMasterState = 1; return; } byte _modbusMasterGetRxBuffer() { boolean bBuffOverflow = false;digitalWrite(10, LOW ); _modbusMasterBufferSize = 0; while (Serial100.available() ) { _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read(); _modbusMasterBufferSize ++; if (_modbusMasterBufferSize >= 64) bBuffOverflow = true; } if (bBuffOverflow) {return -3;} return _modbusMasterBufferSize; } byte validateAnswer() { uint16_t u16MsgCRC = ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]); if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; } if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;} boolean isSupported = false; for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) { if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) { isSupported = 1; break; } } if (!isSupported) {return 1;} return 0; } void get_FC3(byte table) { int currentIndex = _modbusTelegramm.valueIndex; byte currentByte = 3; int value; for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) { value = word( _modbusMasterBuffer[ currentByte], _modbusMasterBuffer[ currentByte + 1 ]); switch ( _modbusMasterCurrentReg ) { case 1 : if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;} break; } currentByte += 2; } }почитайте тему может поможет вам, я долго сам ковырялся с модбас пока до меня дошло что и к чему
http://arduino.ru/forum/programmirovanie/modbus-rtu
Я его не использую в подключении. Я имею ввиду, что на прямую, он работает. А ардуино нет. Вот моя схема подключения.
всё же попробуйте по моей схеме и скетч. Должно заработать
Сейчас попробую и отпишусь.
Подключил по Вашей схеме, залил скетч.
Вот подключил к USB to RS485 на А+ и B- без питания и земли. Работает и показывает значение.
Если я считываю регистр №29, здесь в скобках тоже его прописывать?
В ардуине мало памяти, поэтому в скобках прописываются не номера регитров, а количество, которое будет в обработке. У вас два регистра. Т.е.достаточно [2]. При этом 29 регистр будет иметь индекс массива [0], 1500 будет лежать в [1]. Во всех приведённых вами скечах я ни разу не видел вывода из ардуины в компьютер данных. Как вы собираетесь понять - получила ардуина что то или нет? И как отправлять дальше в комп?
Вот подключил к USB to RS485 на А+ и B- без питания и земли. Работает и показывает значение.
Мне кажется или там у вас на картинке 0 показывает в регистре 29? Дак что же вам не нравится в моем варианте? 0 и должен быть. Считайте по моему методу регистр 30 и получите свои 1500
вот тебе скетч твоего мастера
// Модбас подключить к софтсериалу #include <SoftwareSerial.h> SoftwareSerial Serial100(7, 8); // Rx-7; Tx-8 int _modbusMasterDataTable_4_reg_1[2]; int _modbusMasterAddressTable_4_reg_1[2] = {29, 30}; // тут адреса регистров. 4_reg означает что это Holding Registers // т.е. на _modbusMasterDataTable_4_reg_1[0] будет 29 адрес, на _modbusMasterDataTable_4_reg_1[1] будет 30 адрес byte _modbusMasterBufferSize = 0; byte _modbusMasterState = 1; long _modbusMasterSendTime; byte _modbusMasterLastRec = 0; long _modbusMasterStartT35; byte _modbusMasterBuffer[64]; byte _modbusMasterCurrentReg = 0; byte _modbusMasterCurrentVariable = 0; struct _modbusMasterTelegramm { byte slaveId; byte function; int startAddres; int numbeRegs; int valueIndex; }; _modbusMasterTelegramm _modbusTelegramm; long _startTimeMasterRegs[1]; long _updateTimeMasterRegsArray[] = {2000}; // интервал обмена со слейвом (2 сек) const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16}; int Register_29 = 29; int Register_30 = 30; long previousMillis = 0; // храним время последнего обновления вывода в сериал порт long interval = 2; void setup() { Serial.begin (9600); // для монитора порта - используем железный порт ардуино Serial100.begin(19200); // софтсериал для модбаса pinMode(10, OUTPUT); //пин DE-RE RS-485 НЕ МЕНЯТЬ! digitalWrite(10, LOW); //пин DE-RE RS-485 НЕ МЕНЯТЬ! // ниже требуха для функционирования модбаса for(int i=0; i<1; i++) {_startTimeMasterRegs[i] = millis();} } void loop() { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval*1000) { Serial.print ("Reg29: "); Serial.print (Register_29); Serial.print (" Reg30: "); Serial.println (Register_30); previousMillis = currentMillis;} Register_29 = (_modbusMasterDataTable_4_reg_1[0]); Register_30 = (_modbusMasterDataTable_4_reg_1[1]); // ниже требуха для функционирования модбаса switch ( _modbusMasterState ) { case 1: _nextModbusMasterQuery(); break; case 2: pollModbusMaster(); break; } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));} } int modbusCalcCRC(byte length, byte bufferArray[]) { unsigned int temp, temp2, flag; temp = 0xFFFF; for (unsigned char i = 0; i < length; i++) { temp = temp ^ bufferArray[i]; for (unsigned char j = 1; j <= 8; j++) { flag = temp & 0x0001; temp >>= 1; if (flag) temp ^= 0xA001; } } temp2 = temp >> 8; temp = (temp << 8) | temp2; temp &= 0xFFFF; return temp; } void _nextModbusMasterQuery() { _selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable); if (_modbusMasterCurrentReg == 0) return; _createMasterTelegramm(); _modbusMasterSendQuery(); } void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar) { bool isNeeded = 1; if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;} if (!(_isTimer ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;} if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}} if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;} byte temp; switch (oldReg) { case 1: temp = 2; break; } if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;} _startTimeMasterRegs[oldReg -1] = millis(); if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} _modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return; } void _createMasterTelegramm() { switch (_modbusMasterCurrentReg) { case 1: _modbusTelegramm.slaveId = 1; switch (_modbusMasterCurrentVariable) { case 1: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 29; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 0; break; case 2: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 30; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 1; break; } break; } } void _modbusMasterSendQuery() { byte currentIndex = _modbusTelegramm.valueIndex; _modbusMasterBuffer[0] = _modbusTelegramm.slaveId; _modbusMasterBuffer[1] = _modbusTelegramm.function; _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres ); _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres ); switch ( _modbusTelegramm.function ) { case 3: _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs ); _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs ); _modbusMasterBufferSize = 6; break; } _modbusMasterSendTxBuffer(); _modbusMasterState = 2; } void _modbusMasterSendTxBuffer() { byte i = 0; int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer ); _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8; _modbusMasterBufferSize++; _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff; _modbusMasterBufferSize++; digitalWrite(10, 1 ); delay(3); Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize ); digitalWrite(10, 0 ); Serial100.flush(); _modbusMasterBufferSize = 0; _modbusMasterSendTime = millis(); } void pollModbusMaster() { if (_modbusTelegramm.slaveId == 0) { _modbusMasterState = 1; return;} if (_isTimer(_modbusMasterSendTime, 1000)) { _modbusMasterState = 1; return; } byte avalibleBytes = Serial100.available(); if (avalibleBytes == 0) return; if (avalibleBytes != _modbusMasterLastRec) { _modbusMasterLastRec = avalibleBytes; _modbusMasterStartT35 = millis(); return; } if (!(_isTimer(_modbusMasterStartT35, 3 ))) return; _modbusMasterLastRec = 0; byte readingBytes = _modbusMasterGetRxBuffer(); if (readingBytes < 5) { _modbusMasterState = 1; return ; } byte exeption = validateAnswer(); if (exeption != 0) { _modbusMasterState = 1; return; } switch ( _modbusMasterBuffer[1] ) { case 3: get_FC3(4); break; } _modbusMasterState = 1; return; } byte _modbusMasterGetRxBuffer() { boolean bBuffOverflow = false;digitalWrite(10, LOW ); _modbusMasterBufferSize = 0; while (Serial100.available() ) { _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read(); _modbusMasterBufferSize ++; if (_modbusMasterBufferSize >= 64) bBuffOverflow = true; } if (bBuffOverflow) {return -3;} return _modbusMasterBufferSize; } byte validateAnswer() { uint16_t u16MsgCRC = ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]); if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; } if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;} boolean isSupported = false; for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) { if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) { isSupported = 1; break; } } if (!isSupported) {return 1;} return 0; } void get_FC3(byte table) { int currentIndex = _modbusTelegramm.valueIndex; byte currentByte = 3; int value; for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) { value = word( _modbusMasterBuffer[ currentByte], _modbusMasterBuffer[ currentByte + 1 ]); switch ( _modbusMasterCurrentReg ) { case 1 : if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;} break; } currentByte += 2; } }Всё подключил по схеме, результата нет.
Я не знаю почему оно показывает данные в 30 регистре. Вообще по даташиту, должны храниться в 29 регистре. Если через QModBus я указываю считать 30 регистр, выбивает ошибку. Если указываю считать 29 регистр и выставляю 2 Coils, оно показывает.
В строке 41 попробуй выставить скорость сериала порта 9600 бод. Сюдя по картинке у тебя 9600. Незнаю почему я 19200 поставил.
Вот так надо
041
Serial100.begin(9600);// софтсериал для модбасаИ еще у тебя точно адрес слейва "1" ?
Да. Тут проблема с самим регистром.
Вот твой код, и мой другой регистр. Считало без проблем. Спасибо огромное за это тебе, кстати.
// Модбас подключить к софтсериалу #include <SoftwareSerial.h> SoftwareSerial Serial100(7, 8); // 7 - Rx; 8 - Tx; // Ниже переменные для модбаса int _modbusMasterDataTable_4_reg_1[1]; int _modbusMasterAddressTable_4_reg_1[1] = {1039}; byte _modbusMasterBufferSize = 0; byte _modbusMasterState = 1; long _modbusMasterSendTime; byte _modbusMasterLastRec = 0; long _modbusMasterStartT35; byte _modbusMasterBuffer[64]; byte _modbusMasterCurrentReg = 0; byte _modbusMasterCurrentVariable = 0; struct _modbusMasterTelegramm { byte slaveId; byte function; int startAddres; int numbeRegs; int valueIndex; }; _modbusMasterTelegramm _modbusTelegramm; long _startTimeMasterRegs[1]; long _updateTimeMasterRegsArray[] = {2000}; const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16}; // тут уже наши переменные int Frequency = 0; // переменная частоты, куда будет записываться данные из регистра 29 Holding Registers модбаса long previousMillis = 0; // храним время последнего обновления вывода в сериал порт long interval = 10; // время интервала обновления информации в сериал порте, сек - 1c void setup() { Serial.begin(9600); // для монитора порта - используем железный порт ардуино Serial100.begin(9600); // софтсериал модбаса pinMode(10, OUTPUT); // пин DE RE RS-485 НЕ МЕНЯТЬ! digitalWrite(10, LOW); for(int i=0; i<1; i++) {_startTimeMasterRegs[i] = millis();} } void loop() { //Плата:1 Frequency = (_modbusMasterDataTable_4_reg_1[0]); // чтение данных из регистра 29 Holding Registers модбаса и запись в переменную ///// периодически скидываем переменную Frequency в монитор порта unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval*1000) { Serial.println (Frequency); previousMillis = currentMillis;} ////// всё что ниже - для модбаса switch ( _modbusMasterState ) { case 1: _nextModbusMasterQuery(); break; case 2: pollModbusMaster(); break; } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));} } int modbusCalcCRC(byte length, byte bufferArray[]) { unsigned int temp, temp2, flag; temp = 0xFFFF; for (unsigned char i = 0; i < length; i++) { temp = temp ^ bufferArray[i]; for (unsigned char j = 1; j <= 8; j++) { flag = temp & 0x0001; temp >>= 1; if (flag) temp ^= 0xA001; } } temp2 = temp >> 8; temp = (temp << 8) | temp2; temp &= 0xFFFF; return temp; } void _nextModbusMasterQuery() { _selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable); if (_modbusMasterCurrentReg == 0) return; _createMasterTelegramm(); _modbusMasterSendQuery(); } void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar) { bool isNeeded = 1; if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;} if (!(_isTimer ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;} if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}} if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;} byte temp; switch (oldReg) { case 1: temp = 1; break; } if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;} _startTimeMasterRegs[oldReg -1] = millis(); if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} _modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return; } void _createMasterTelegramm() { switch (_modbusMasterCurrentReg) { case 1: _modbusTelegramm.slaveId = 1; switch (_modbusMasterCurrentVariable) { case 1: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1039; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 0; break; } break; } } void _modbusMasterSendQuery() { byte currentIndex = _modbusTelegramm.valueIndex; _modbusMasterBuffer[0] = _modbusTelegramm.slaveId; _modbusMasterBuffer[1] = _modbusTelegramm.function; _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres ); _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres ); switch ( _modbusTelegramm.function ) { case 3: _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs ); _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs ); _modbusMasterBufferSize = 6; break; } _modbusMasterSendTxBuffer(); _modbusMasterState = 2; } void _modbusMasterSendTxBuffer() { byte i = 0; int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer ); _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8; _modbusMasterBufferSize++; _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff; _modbusMasterBufferSize++; digitalWrite(10, 1 ); delay(3); Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize ); digitalWrite(10, 0 ); Serial100.flush(); _modbusMasterBufferSize = 0; _modbusMasterSendTime = millis(); } void pollModbusMaster() { if (_modbusTelegramm.slaveId == 0) { _modbusMasterState = 1; return;} if (_isTimer(_modbusMasterSendTime, 1000)) { _modbusMasterState = 1; return; } byte avalibleBytes = Serial100.available(); if (avalibleBytes == 0) return; if (avalibleBytes != _modbusMasterLastRec) { _modbusMasterLastRec = avalibleBytes; _modbusMasterStartT35 = millis(); return; } if (!(_isTimer(_modbusMasterStartT35, 3 ))) return; _modbusMasterLastRec = 0; byte readingBytes = _modbusMasterGetRxBuffer(); if (readingBytes < 5) { _modbusMasterState = 1; return ; } byte exeption = validateAnswer(); if (exeption != 0) { _modbusMasterState = 1; return; } switch ( _modbusMasterBuffer[1] ) { case 3: get_FC3(4); break; } _modbusMasterState = 1; return; } byte _modbusMasterGetRxBuffer() { boolean bBuffOverflow = false;digitalWrite(10, LOW ); _modbusMasterBufferSize = 0; while (Serial100.available() ) { _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read(); _modbusMasterBufferSize ++; if (_modbusMasterBufferSize >= 64) bBuffOverflow = true; } if (bBuffOverflow) {return -3;} return _modbusMasterBufferSize; } byte validateAnswer() { uint16_t u16MsgCRC = ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]); if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; } if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;} boolean isSupported = false; for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) { if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) { isSupported = 1; break; } } if (!isSupported) {return 1;} return 0; } void get_FC3(byte table) { int currentIndex = _modbusTelegramm.valueIndex; byte currentByte = 3; int value; for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) { value = word( _modbusMasterBuffer[ currentByte], _modbusMasterBuffer[ currentByte + 1 ]); switch ( _modbusMasterCurrentReg ) { case 1 : if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;} break; } currentByte += 2; } }Подскажите пожалуйста, вот попытался считать 2 регистра сразу. Вроде бы делал всё как у Вас, но оно читает только один, во втором пишет: 0. Если по одному, тогда считывает норм.
Вот код:
// Модбас подключить к софтсериалу #include <SoftwareSerial.h> SoftwareSerial Serial100(7, 8); // 7 - Rx; 8 - Tx; // Ниже переменные для модбаса int _modbusMasterDataTable_4_reg_1[2]; int _modbusMasterAddressTable_4_reg_1[2] = {1019, 1039}; byte _modbusMasterBufferSize = 0; byte _modbusMasterState = 1; long _modbusMasterSendTime; byte _modbusMasterLastRec = 0; long _modbusMasterStartT35; byte _modbusMasterBuffer[64]; byte _modbusMasterCurrentReg = 0; byte _modbusMasterCurrentVariable = 0; struct _modbusMasterTelegramm { byte slaveId; byte function; int startAddres; int numbeRegs; int valueIndex; }; _modbusMasterTelegramm _modbusTelegramm; long _startTimeMasterRegs[1]; long _updateTimeMasterRegsArray[] = {2000}; const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16}; // тут уже наши переменные float Power = 0; int Frequency = 0; long previousMillis = 0; // храним время последнего обновления вывода в сериал порт long interval = 5; // время интервала обновления информации в сериал порте, сек - 5c void setup() { Serial.begin(9600); // для монитора порта - используем железный порт ардуино Serial100.begin(9600); // софтсериал модбаса pinMode(10, OUTPUT); // пин DE RE RS-485 НЕ МЕНЯТЬ! digitalWrite(10, LOW); for(int i=0; i<1; i++) {_startTimeMasterRegs[i] = millis();} } void loop() { ///// периодически скидываем переменную Frequency в монитор порта unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval*1000) { Serial.print("Motor Power: "); Serial.print(Power, 0); Serial.println(); Serial.print("Motor Frequency: "); Serial.print(Frequency); Serial.println(); previousMillis = currentMillis;} Power = (_modbusMasterDataTable_4_reg_1[0]); Frequency = (_modbusMasterDataTable_4_reg_1[1]); ////// всё что ниже - для модбаса switch ( _modbusMasterState ) { case 1: _nextModbusMasterQuery(); break; case 2: pollModbusMaster(); break; } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));} } int modbusCalcCRC(byte length, byte bufferArray[]) { unsigned int temp, temp2, flag; temp = 0xFFFF; for (unsigned char i = 0; i < length; i++) { temp = temp ^ bufferArray[i]; for (unsigned char j = 1; j <= 8; j++) { flag = temp & 0x0001; temp >>= 1; if (flag) temp ^= 0xA001; } } temp2 = temp >> 8; temp = (temp << 8) | temp2; temp &= 0xFFFF; return temp; } void _nextModbusMasterQuery() { _selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable); if (_modbusMasterCurrentReg == 0) return; _createMasterTelegramm(); _modbusMasterSendQuery(); } void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar) { bool isNeeded = 1; if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;} if (!(_isTimer ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;} if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}} if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;} byte temp; switch (oldReg) { case 1: temp = 1; break; } if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;} _startTimeMasterRegs[oldReg -1] = millis(); if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} _modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return; } void _createMasterTelegramm() { switch (_modbusMasterCurrentReg) { case 1: _modbusTelegramm.slaveId = 1; switch (_modbusMasterCurrentVariable) { case 1: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1019; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 0; break; case 2: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1039; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 1; break; } break; } } void _modbusMasterSendQuery() { byte currentIndex = _modbusTelegramm.valueIndex; _modbusMasterBuffer[0] = _modbusTelegramm.slaveId; _modbusMasterBuffer[1] = _modbusTelegramm.function; _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres ); _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres ); switch ( _modbusTelegramm.function ) { case 3: _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs ); _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs ); _modbusMasterBufferSize = 6; break; } _modbusMasterSendTxBuffer(); _modbusMasterState = 2; } void _modbusMasterSendTxBuffer() { byte i = 0; int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer ); _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8; _modbusMasterBufferSize++; _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff; _modbusMasterBufferSize++; digitalWrite(10, 1 ); delay(3); Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize ); digitalWrite(10, 0 ); Serial100.flush(); _modbusMasterBufferSize = 0; _modbusMasterSendTime = millis(); } void pollModbusMaster() { if (_modbusTelegramm.slaveId == 0) { _modbusMasterState = 1; return;} if (_isTimer(_modbusMasterSendTime, 1000)) { _modbusMasterState = 1; return; } byte avalibleBytes = Serial100.available(); if (avalibleBytes == 0) return; if (avalibleBytes != _modbusMasterLastRec) { _modbusMasterLastRec = avalibleBytes; _modbusMasterStartT35 = millis(); return; } if (!(_isTimer(_modbusMasterStartT35, 3 ))) return; _modbusMasterLastRec = 0; byte readingBytes = _modbusMasterGetRxBuffer(); if (readingBytes < 5) { _modbusMasterState = 1; return ; } byte exeption = validateAnswer(); if (exeption != 0) { _modbusMasterState = 1; return; } switch ( _modbusMasterBuffer[1] ) { case 3: get_FC3(4); break; } _modbusMasterState = 1; return; } byte _modbusMasterGetRxBuffer() { boolean bBuffOverflow = false;digitalWrite(10, LOW ); _modbusMasterBufferSize = 0; while (Serial100.available() ) { _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read(); _modbusMasterBufferSize ++; if (_modbusMasterBufferSize >= 64) bBuffOverflow = true; } if (bBuffOverflow) {return -3;} return _modbusMasterBufferSize; } byte validateAnswer() { uint16_t u16MsgCRC = ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]); if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; } if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;} boolean isSupported = false; for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) { if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) { isSupported = 1; break; } } if (!isSupported) {return 1;} return 0; } void get_FC3(byte table) { int currentIndex = _modbusTelegramm.valueIndex; byte currentByte = 3; int value; for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) { value = word( _modbusMasterBuffer[ currentByte], _modbusMasterBuffer[ currentByte + 1 ]); switch ( _modbusMasterCurrentReg ) { case 1 : if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;} break; } currentByte += 2; } }Попробуй этот код
#include <SoftwareSerial.h> SoftwareSerial Serial100(7, 8); int _modbusMasterDataTable_4_reg_1[2]; int _modbusMasterAddressTable_4_reg_1[2] = {1019, 1039}; byte _modbusMasterBufferSize = 0; byte _modbusMasterState = 1; long _modbusMasterSendTime; byte _modbusMasterLastRec = 0; long _modbusMasterStartT35; byte _modbusMasterBuffer[64]; byte _modbusMasterCurrentReg = 0; byte _modbusMasterCurrentVariable = 0; struct _modbusMasterTelegramm { byte slaveId; byte function; int startAddres; int numbeRegs; int valueIndex; }; _modbusMasterTelegramm _modbusTelegramm; long _startTimeMasterRegs[1]; long _updateTimeMasterRegsArray[] = {1000}; const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16}; int Power_1019 ; int Frequency_1039 ; long previousMillis = 0; // храним время последнего обновления вывода в сериал порт long interval = 2; void setup() { Serial.begin (9600); Serial100.begin(9600); pinMode(10, OUTPUT); digitalWrite(10, LOW); for(int i=0; i<1; i++) {_startTimeMasterRegs[i] = millis();} } void loop() { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval*1000) { Serial.print("Motor Power: "); Serial.print(Power_1019, 0); Serial.println(); Serial.print("Motor Frequency: "); Serial.print(Frequency_1039); Serial.println(); previousMillis = currentMillis;} Power_1019 = (_modbusMasterDataTable_4_reg_1[0]); Frequency_1039 = (_modbusMasterDataTable_4_reg_1[1]); switch ( _modbusMasterState ) { case 1: _nextModbusMasterQuery(); break; case 2: pollModbusMaster(); break; } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));} } int modbusCalcCRC(byte length, byte bufferArray[]) { unsigned int temp, temp2, flag; temp = 0xFFFF; for (unsigned char i = 0; i < length; i++) { temp = temp ^ bufferArray[i]; for (unsigned char j = 1; j <= 8; j++) { flag = temp & 0x0001; temp >>= 1; if (flag) temp ^= 0xA001; } } temp2 = temp >> 8; temp = (temp << 8) | temp2; temp &= 0xFFFF; return temp; } void _nextModbusMasterQuery() { _selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable); if (_modbusMasterCurrentReg == 0) return; _createMasterTelegramm(); _modbusMasterSendQuery(); } void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar) { bool isNeeded = 1; if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;} if (!(_isTimer ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;} if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}} if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;} byte temp; switch (oldReg) { case 1: temp = 2; break; } if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;} _startTimeMasterRegs[oldReg -1] = millis(); if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} _modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return; } void _createMasterTelegramm() { switch (_modbusMasterCurrentReg) { case 1: _modbusTelegramm.slaveId = 1; switch (_modbusMasterCurrentVariable) { case 1: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1019; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 0; break; case 2: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1039; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 1; break; } break; } } void _modbusMasterSendQuery() { byte currentIndex = _modbusTelegramm.valueIndex; _modbusMasterBuffer[0] = _modbusTelegramm.slaveId; _modbusMasterBuffer[1] = _modbusTelegramm.function; _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres ); _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres ); switch ( _modbusTelegramm.function ) { case 3: _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs ); _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs ); _modbusMasterBufferSize = 6; break; } _modbusMasterSendTxBuffer(); _modbusMasterState = 2; } void _modbusMasterSendTxBuffer() { byte i = 0; int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer ); _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8; _modbusMasterBufferSize++; _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff; _modbusMasterBufferSize++; digitalWrite(10, 1 ); delay(5); Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize ); digitalWrite(10, 0 ); Serial100.flush(); _modbusMasterBufferSize = 0; _modbusMasterSendTime = millis(); } void pollModbusMaster() { if (_modbusTelegramm.slaveId == 0) { _modbusMasterState = 1; return;} if (_isTimer(_modbusMasterSendTime, 1000)) { _modbusMasterState = 1; return; } byte avalibleBytes = Serial100.available(); if (avalibleBytes == 0) return; if (avalibleBytes != _modbusMasterLastRec) { _modbusMasterLastRec = avalibleBytes; _modbusMasterStartT35 = millis(); return; } if (!(_isTimer(_modbusMasterStartT35, 5 ))) return; _modbusMasterLastRec = 0; byte readingBytes = _modbusMasterGetRxBuffer(); if (readingBytes < 5) { _modbusMasterState = 1; return ; } byte exeption = validateAnswer(); if (exeption != 0) { _modbusMasterState = 1; return; } switch ( _modbusMasterBuffer[1] ) { case 3: get_FC3(4); break; } _modbusMasterState = 1; return; } byte _modbusMasterGetRxBuffer() { boolean bBuffOverflow = false;digitalWrite(10, LOW ); _modbusMasterBufferSize = 0; while (Serial100.available() ) { _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read(); _modbusMasterBufferSize ++; if (_modbusMasterBufferSize >= 64) bBuffOverflow = true; } if (bBuffOverflow) {return -3;} return _modbusMasterBufferSize; } byte validateAnswer() { uint16_t u16MsgCRC = ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]); if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; } if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;} boolean isSupported = false; for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) { if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) { isSupported = 1; break; } } if (!isSupported) {return 1;} return 0; } void get_FC3(byte table) { int currentIndex = _modbusTelegramm.valueIndex; byte currentByte = 3; int value; for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) { value = word( _modbusMasterBuffer[ currentByte], _modbusMasterBuffer[ currentByte + 1 ]); switch ( _modbusMasterCurrentReg ) { case 1 : if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;} break; } currentByte += 2; } }в твоем скетче ошибка в строке 115, у тебя там temp=1, а должно быть temp=2
Не помогло. Скетч считывает всё нужные мне регистры. Но по одному, если добавляю еще какой то, не работает.
а ты скетч из сообщения #40 тоже попробовал?
Ну да, скрин из него и сделал.
Вот допустим когда вот так, оно работает, если вывожу в терминал другин переменные, нули пишет.
// Модбас подключить к софтсериалу #include <SoftwareSerial.h> SoftwareSerial Serial100(7, 8); // 7 - Rx; 8 - Tx; // Ниже переменные для модбаса int _modbusMasterDataTable_4_reg_1[3]; int _modbusMasterAddressTable_4_reg_1[3] = {29,1019,1039}; byte _modbusMasterBufferSize = 0; byte _modbusMasterState = 1; long _modbusMasterSendTime; byte _modbusMasterLastRec = 0; long _modbusMasterStartT35; byte _modbusMasterBuffer[64]; byte _modbusMasterCurrentReg = 0; byte _modbusMasterCurrentVariable = 0; struct _modbusMasterTelegramm { byte slaveId; byte function; int startAddres; int numbeRegs; int valueIndex; }; _modbusMasterTelegramm _modbusTelegramm; long _startTimeMasterRegs[1]; long _updateTimeMasterRegsArray[] = {2000}; const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16}; // тут уже наши переменные long previousMillis = 0; // храним время последнего обновления вывода в сериал порт long interval = 5; // время интервала обновления информации в сериал порте, сек - 5c void setup() { Serial.begin(9600); // для монитора порта - используем железный порт ардуино Serial100.begin(9600); // софтсериал модбаса pinMode(10, OUTPUT); // пин DE RE RS-485 НЕ МЕНЯТЬ! digitalWrite(10, LOW); for(int i=0; i<1; i++) {_startTimeMasterRegs[i] = millis();} } void loop() { int Power = (_modbusMasterDataTable_4_reg_1[0]); int Frequency = (_modbusMasterDataTable_4_reg_1[1]); int Frequency2 = (_modbusMasterDataTable_4_reg_1[2]); ///// периодически скидываем переменную Frequency в монитор порта unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval*1000) { Serial.print("Local Reference: "); Serial.print(Frequency); Serial.println(); previousMillis = currentMillis;} ////// всё что ниже - для модбаса switch ( _modbusMasterState ) { case 1: _nextModbusMasterQuery(); break; case 2: pollModbusMaster(); break; } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));} } int modbusCalcCRC(byte length, byte bufferArray[]) { unsigned int temp, temp2, flag; temp = 0xFFFF; for (unsigned char i = 0; i < length; i++) { temp = temp ^ bufferArray[i]; for (unsigned char j = 1; j <= 8; j++) { flag = temp & 0x0001; temp >>= 1; if (flag) temp ^= 0xA001; } } temp2 = temp >> 8; temp = (temp << 8) | temp2; temp &= 0xFFFF; return temp; } void _nextModbusMasterQuery() { _selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable); if (_modbusMasterCurrentReg == 0) return; _createMasterTelegramm(); _modbusMasterSendQuery(); } void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar) { bool isNeeded = 1; if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;} if (!(_isTimer ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;} if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}} if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;} byte temp; switch (oldReg) { case 1: temp = 1; break; } if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;} _startTimeMasterRegs[oldReg -1] = millis(); if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} _modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return; } void _createMasterTelegramm() { switch (_modbusMasterCurrentReg) { case 1: _modbusTelegramm.slaveId = 1; switch (_modbusMasterCurrentVariable) { case 1: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 29; _modbusTelegramm.numbeRegs = 2; _modbusTelegramm.valueIndex = 0; break; case 2: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1019; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 1; break; case 3: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1039; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 2; break; } break; } } void _modbusMasterSendQuery() { byte currentIndex = _modbusTelegramm.valueIndex; _modbusMasterBuffer[0] = _modbusTelegramm.slaveId; _modbusMasterBuffer[1] = _modbusTelegramm.function; _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres ); _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres ); switch ( _modbusTelegramm.function ) { case 3: _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs ); _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs ); _modbusMasterBufferSize = 6; break; } _modbusMasterSendTxBuffer(); _modbusMasterState = 2; } void _modbusMasterSendTxBuffer() { byte i = 0; int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer ); _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8; _modbusMasterBufferSize++; _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff; _modbusMasterBufferSize++; digitalWrite(10, 1 ); delay(3); Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize ); digitalWrite(10, 0 ); Serial100.flush(); _modbusMasterBufferSize = 0; _modbusMasterSendTime = millis(); } void pollModbusMaster() { if (_modbusTelegramm.slaveId == 0) { _modbusMasterState = 1; return;} if (_isTimer(_modbusMasterSendTime, 1000)) { _modbusMasterState = 1; return; } byte avalibleBytes = Serial100.available(); if (avalibleBytes == 0) return; if (avalibleBytes != _modbusMasterLastRec) { _modbusMasterLastRec = avalibleBytes; _modbusMasterStartT35 = millis(); return; } if (!(_isTimer(_modbusMasterStartT35, 3 ))) return; _modbusMasterLastRec = 0; byte readingBytes = _modbusMasterGetRxBuffer(); if (readingBytes < 5) { _modbusMasterState = 1; return ; } byte exeption = validateAnswer(); if (exeption != 0) { _modbusMasterState = 1; return; } switch ( _modbusMasterBuffer[1] ) { case 3: get_FC3(4); break; } _modbusMasterState = 1; return; } byte _modbusMasterGetRxBuffer() { boolean bBuffOverflow = false;digitalWrite(10, LOW ); _modbusMasterBufferSize = 0; while (Serial100.available() ) { _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read(); _modbusMasterBufferSize ++; if (_modbusMasterBufferSize >= 64) bBuffOverflow = true; } if (bBuffOverflow) {return -3;} return _modbusMasterBufferSize; } byte validateAnswer() { uint16_t u16MsgCRC = ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]); if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; } if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;} boolean isSupported = false; for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) { if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) { isSupported = 1; break; } } if (!isSupported) {return 1;} return 0; } void get_FC3(byte table) { int currentIndex = _modbusTelegramm.valueIndex; byte currentByte = 3; int value; for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) { value = word( _modbusMasterBuffer[ currentByte], _modbusMasterBuffer[ currentByte + 1 ]); switch ( _modbusMasterCurrentReg ) { case 1 : if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;} break; } currentByte += 2; } }дак как так то? у тебя опять в строке 111 temp =1, ты точно скетч из сообщения #40 взял? Там у меня temp=2. Это число должно быть равно числу считываемых регистров. Т.е. для последнего выложенного тобой скетча должно быть temp =3
Вот смотри сам.
// Модбас подключить к софтсериалу #include <SoftwareSerial.h> SoftwareSerial Serial100(7, 8); // 7 - Rx; 8 - Tx; // Ниже переменные для модбаса int _modbusMasterDataTable_4_reg_1[3]; int _modbusMasterAddressTable_4_reg_1[3] = {29,1019,1039}; byte _modbusMasterBufferSize = 0; byte _modbusMasterState = 1; long _modbusMasterSendTime; byte _modbusMasterLastRec = 0; long _modbusMasterStartT35; byte _modbusMasterBuffer[64]; byte _modbusMasterCurrentReg = 0; byte _modbusMasterCurrentVariable = 0; struct _modbusMasterTelegramm { byte slaveId; byte function; int startAddres; int numbeRegs; int valueIndex; }; _modbusMasterTelegramm _modbusTelegramm; long _startTimeMasterRegs[1]; long _updateTimeMasterRegsArray[] = {2000}; const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16}; int Power = 0; int Frequency = 0; int Frequency2 = 0; long previousMillis = 0; // храним время последнего обновления вывода в сериал порт long interval = 5; // время интервала обновления информации в сериал порте, сек - 5c void setup() { Serial.begin(9600); // для монитора порта - используем железный порт ардуино Serial100.begin(9600); // софтсериал модбаса pinMode(10, OUTPUT); // пин DE RE RS-485 НЕ МЕНЯТЬ! digitalWrite(10, LOW); for(int i=0; i<1; i++) {_startTimeMasterRegs[i] = millis();} } void loop() { Power = (_modbusMasterDataTable_4_reg_1[0]); Frequency = (_modbusMasterDataTable_4_reg_1[1]); Frequency2 = (_modbusMasterDataTable_4_reg_1[2]); ///// периодически скидываем переменную Frequency в монитор порта unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval*1000) { Serial.print("Value_1: "); Serial.print(Frequency); Serial.println(); Serial.print("Value_2: "); Serial.print(Power); Serial.println(); Serial.print("Value_3: "); Serial.print(Frequency2); Serial.println(); previousMillis = currentMillis;} ////// всё что ниже - для модбаса switch ( _modbusMasterState ) { case 1: _nextModbusMasterQuery(); break; case 2: pollModbusMaster(); break; } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));} } int modbusCalcCRC(byte length, byte bufferArray[]) { unsigned int temp, temp2, flag; temp = 0xFFFF; for (unsigned char i = 0; i < length; i++) { temp = temp ^ bufferArray[i]; for (unsigned char j = 1; j <= 8; j++) { flag = temp & 0x0001; temp >>= 1; if (flag) temp ^= 0xA001; } } temp2 = temp >> 8; temp = (temp << 8) | temp2; temp &= 0xFFFF; return temp; } void _nextModbusMasterQuery() { _selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable); if (_modbusMasterCurrentReg == 0) return; _createMasterTelegramm(); _modbusMasterSendQuery(); } void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar) { bool isNeeded = 1; if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;} if (!(_isTimer ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;} if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}} if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;} byte temp; switch (oldReg) { case 1: temp = 3; break; } if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;} _startTimeMasterRegs[oldReg -1] = millis(); if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} _modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return; } void _createMasterTelegramm() { switch (_modbusMasterCurrentReg) { case 1: _modbusTelegramm.slaveId = 1; switch (_modbusMasterCurrentVariable) { case 1: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 29; _modbusTelegramm.numbeRegs = 2; _modbusTelegramm.valueIndex = 0; break; case 2: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1019; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 1; break; case 3: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1039; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 2; break; } break; } } void _modbusMasterSendQuery() { byte currentIndex = _modbusTelegramm.valueIndex; _modbusMasterBuffer[0] = _modbusTelegramm.slaveId; _modbusMasterBuffer[1] = _modbusTelegramm.function; _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres ); _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres ); switch ( _modbusTelegramm.function ) { case 3: _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs ); _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs ); _modbusMasterBufferSize = 6; break; } _modbusMasterSendTxBuffer(); _modbusMasterState = 2; } void _modbusMasterSendTxBuffer() { byte i = 0; int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer ); _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8; _modbusMasterBufferSize++; _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff; _modbusMasterBufferSize++; digitalWrite(10, 1 ); delay(3); Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize ); digitalWrite(10, 0 ); Serial100.flush(); _modbusMasterBufferSize = 0; _modbusMasterSendTime = millis(); } void pollModbusMaster() { if (_modbusTelegramm.slaveId == 0) { _modbusMasterState = 1; return;} if (_isTimer(_modbusMasterSendTime, 1000)) { _modbusMasterState = 1; return; } byte avalibleBytes = Serial100.available(); if (avalibleBytes == 0) return; if (avalibleBytes != _modbusMasterLastRec) { _modbusMasterLastRec = avalibleBytes; _modbusMasterStartT35 = millis(); return; } if (!(_isTimer(_modbusMasterStartT35, 3 ))) return; _modbusMasterLastRec = 0; byte readingBytes = _modbusMasterGetRxBuffer(); if (readingBytes < 5) { _modbusMasterState = 1; return ; } byte exeption = validateAnswer(); if (exeption != 0) { _modbusMasterState = 1; return; } switch ( _modbusMasterBuffer[1] ) { case 3: get_FC3(4); break; } _modbusMasterState = 1; return; } byte _modbusMasterGetRxBuffer() { boolean bBuffOverflow = false;digitalWrite(10, LOW ); _modbusMasterBufferSize = 0; while (Serial100.available() ) { _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read(); _modbusMasterBufferSize ++; if (_modbusMasterBufferSize >= 64) bBuffOverflow = true; } if (bBuffOverflow) {return -3;} return _modbusMasterBufferSize; } byte validateAnswer() { uint16_t u16MsgCRC = ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]); if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; } if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;} boolean isSupported = false; for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) { if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) { isSupported = 1; break; } } if (!isSupported) {return 1;} return 0; } void get_FC3(byte table) { int currentIndex = _modbusTelegramm.valueIndex; byte currentByte = 3; int value; for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) { value = word( _modbusMasterBuffer[ currentByte], _modbusMasterBuffer[ currentByte + 1 ]); switch ( _modbusMasterCurrentReg ) { case 1 : if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;} break; } currentByte += 2; } }Щас последний раз скетч выложу для трех регистров, если не поможет, я пас.
Хорошо)
код для 3 регистров
#include <SoftwareSerial.h> SoftwareSerial Serial100(7, 8); int _modbusMasterDataTable_4_reg_1[3]; int _modbusMasterAddressTable_4_reg_1[3] = {29, 1019, 1039}; byte _modbusMasterBufferSize = 0; byte _modbusMasterState = 1; long _modbusMasterSendTime; byte _modbusMasterLastRec = 0; long _modbusMasterStartT35; byte _modbusMasterBuffer[64]; byte _modbusMasterCurrentReg = 0; byte _modbusMasterCurrentVariable = 0; struct _modbusMasterTelegramm { byte slaveId; byte function; int startAddres; int numbeRegs; int valueIndex; }; _modbusMasterTelegramm _modbusTelegramm; long _startTimeMasterRegs[1]; long _updateTimeMasterRegsArray[] = {1000}; const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16}; int Frequency; //Frequency1 1 int Frequency2; //Frequency2 2 int Power; //Power 3 long previousMillis = 0; // храним время последнего обновления вывода в сериал порт long interval = 5; // время интервала обновления информации в сериал порте, сек - 5c void setup() { Serial.begin (9600); Serial100.begin(9600); pinMode(10, OUTPUT); digitalWrite(10, LOW); for(int i=0; i<1; i++) {_startTimeMasterRegs[i] = millis();} } void loop() { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval*1000) { Serial.print("Value_1: "); Serial.print(Frequency); Serial.print(" Value_2: "); Serial.print(Power); Serial.print(" Value_3: "); Serial.println(Frequency2); previousMillis = currentMillis;} //Плата:1 Power = (_modbusMasterDataTable_4_reg_1[0]); Frequency = (_modbusMasterDataTable_4_reg_1[1]); Frequency2 = (_modbusMasterDataTable_4_reg_1[2]); switch ( _modbusMasterState ) { case 1: _nextModbusMasterQuery(); break; case 2: pollModbusMaster(); break; } } bool _isTimer(unsigned long startTime, unsigned long period ) { unsigned long currentTime; currentTime = millis(); if (currentTime>= startTime) {return (currentTime>=(startTime + period));} else {return (currentTime >=(4294967295-startTime+period));} } int modbusCalcCRC(byte length, byte bufferArray[]) { unsigned int temp, temp2, flag; temp = 0xFFFF; for (unsigned char i = 0; i < length; i++) { temp = temp ^ bufferArray[i]; for (unsigned char j = 1; j <= 8; j++) { flag = temp & 0x0001; temp >>= 1; if (flag) temp ^= 0xA001; } } temp2 = temp >> 8; temp = (temp << 8) | temp2; temp &= 0xFFFF; return temp; } void _nextModbusMasterQuery() { _selectNewModbusMasterCurrentReg(_modbusMasterCurrentReg, _modbusMasterCurrentVariable); if (_modbusMasterCurrentReg == 0) return; _createMasterTelegramm(); _modbusMasterSendQuery(); } void _selectNewModbusMasterCurrentReg(byte oldReg, byte oldVar) { bool isNeeded = 1; if (oldReg == 0) {_selectNewModbusMasterCurrentReg(1, 0); return;} if (!(_isTimer ((_startTimeMasterRegs[oldReg - 1]),(_updateTimeMasterRegsArray[oldReg -1])))) {isNeeded = 0;} if( ! isNeeded ) {if(oldReg < 1) {_selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} else {_modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return;}} if (oldVar == 0) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = 1; return;} byte temp; switch (oldReg) { case 1: temp = 3; break; } if (oldVar < temp) {_modbusMasterCurrentReg = oldReg; _modbusMasterCurrentVariable = oldVar +1; return;} _startTimeMasterRegs[oldReg -1] = millis(); if(oldReg < 1) { _selectNewModbusMasterCurrentReg(oldReg+1, 0); return;} _modbusMasterCurrentReg = 0; _modbusMasterCurrentVariable = 0; return; } void _createMasterTelegramm() { switch (_modbusMasterCurrentReg) { case 1: _modbusTelegramm.slaveId = 1; switch (_modbusMasterCurrentVariable) { case 1: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 29; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 0; break; case 2: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1019; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 1; break; case 3: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 1039; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 2; break; } break; } } void _modbusMasterSendQuery() { byte currentIndex = _modbusTelegramm.valueIndex; _modbusMasterBuffer[0] = _modbusTelegramm.slaveId; _modbusMasterBuffer[1] = _modbusTelegramm.function; _modbusMasterBuffer[2] = highByte(_modbusTelegramm.startAddres ); _modbusMasterBuffer[3] = lowByte( _modbusTelegramm.startAddres ); switch ( _modbusTelegramm.function ) { case 3: _modbusMasterBuffer[4] = highByte(_modbusTelegramm.numbeRegs ); _modbusMasterBuffer[5] = lowByte( _modbusTelegramm.numbeRegs ); _modbusMasterBufferSize = 6; break; } _modbusMasterSendTxBuffer(); _modbusMasterState = 2; } void _modbusMasterSendTxBuffer() { byte i = 0; int crc = modbusCalcCRC( _modbusMasterBufferSize, _modbusMasterBuffer ); _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc >> 8; _modbusMasterBufferSize++; _modbusMasterBuffer[ _modbusMasterBufferSize ] = crc & 0x00ff; _modbusMasterBufferSize++; digitalWrite(10, 1 ); delay(5); Serial100.write( _modbusMasterBuffer, _modbusMasterBufferSize ); digitalWrite(10, 0 ); Serial100.flush(); _modbusMasterBufferSize = 0; _modbusMasterSendTime = millis(); } void pollModbusMaster() { if (_modbusTelegramm.slaveId == 0) { _modbusMasterState = 1; return;} if (_isTimer(_modbusMasterSendTime, 1000)) { _modbusMasterState = 1; return; } byte avalibleBytes = Serial100.available(); if (avalibleBytes == 0) return; if (avalibleBytes != _modbusMasterLastRec) { _modbusMasterLastRec = avalibleBytes; _modbusMasterStartT35 = millis(); return; } if (!(_isTimer(_modbusMasterStartT35, 5 ))) return; _modbusMasterLastRec = 0; byte readingBytes = _modbusMasterGetRxBuffer(); if (readingBytes < 5) { _modbusMasterState = 1; return ; } byte exeption = validateAnswer(); if (exeption != 0) { _modbusMasterState = 1; return; } switch ( _modbusMasterBuffer[1] ) { case 3: get_FC3(4); break; } _modbusMasterState = 1; return; } byte _modbusMasterGetRxBuffer() { boolean bBuffOverflow = false;digitalWrite(10, LOW ); _modbusMasterBufferSize = 0; while (Serial100.available() ) { _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial100.read(); _modbusMasterBufferSize ++; if (_modbusMasterBufferSize >= 64) bBuffOverflow = true; } if (bBuffOverflow) {return -3;} return _modbusMasterBufferSize; } byte validateAnswer() { uint16_t u16MsgCRC = ((_modbusMasterBuffer[_modbusMasterBufferSize - 2] << 8) | _modbusMasterBuffer[_modbusMasterBufferSize - 1]); if ( modbusCalcCRC( _modbusMasterBufferSize - 2,_modbusMasterBuffer ) != u16MsgCRC ) { return 255; } if ((_modbusMasterBuffer[1] & 0x80) != 0) {return _modbusMasterBuffer[2] ;} boolean isSupported = false; for (byte i = 0; i < sizeof( _modbusMaster_fctsupported ); i++) { if (_modbusMaster_fctsupported[i] == _modbusMasterBuffer[1]) { isSupported = 1; break; } } if (!isSupported) {return 1;} return 0; } void get_FC3(byte table) { int currentIndex = _modbusTelegramm.valueIndex; byte currentByte = 3; int value; for (int i = 0; i < _modbusTelegramm.numbeRegs; i++) { value = word( _modbusMasterBuffer[ currentByte], _modbusMasterBuffer[ currentByte + 1 ]); switch ( _modbusMasterCurrentReg ) { case 1 : if(table == 3) {} else {_modbusMasterDataTable_4_reg_1[currentIndex + i] =value;} break; } currentByte += 2; } }Я так понимаю, Вы пас?)))