NodeMcu V3 Lua + две платы MAX485: 2 сети Modbus с двумя вариантами настройки параметров порта (8N1 и 8N2)
- Войдите на сайт для отправки комментариев
Втр, 28/08/2018 - 00:22
Уважаемые знатоки !
Помогите советами по правильному построению сети Modbus на основе NodeMcu V3 Lua WI-FI.
Необходимо считывать данные по RS485 (модуль на MAX485) с 4-х Modbus-устройств с двумя вариантами настройки параметров последовательного порта (9600-SERIAL_8N1 и 9600-SERIAL_8N2) и отправлять данные в Blynk и через Modbus TCP на удалённый OPC-сервер.
Не смог задать параметры 8N2 (кроме скорости 9600) в FLProg, поскольку автором программы был задан единственный вариант конфигурации: 8N1 .
Пришлось править скетч в Arduino IDE, добавляя запись типа SoftwareSerial swSerial.begin(9600, SERIAL_8N2).
Далее в ходе реализации проекта на основе аппаратного последовательного порта столкнулся с проблемой компиляции (см. фрагмент скетча).
error: 'UCSR0A' was not declared in this scope
UCSR0A=UCSR0A |(1 << TXC0);
^
pr7:372: error: 'TXC0' was not declared in this scope
UCSR0A=UCSR0A |(1 << TXC0);
^
exit status 1
'UCSR0A' was not declared in this scopeПытался реализовать проект на программном последовательном порту, и понял, что программная реализация умеет только скорость менять. Может уже есть какая библиотека для этого ?
В общем, требуется подключить к контроллеру две платы RS485 (модуль на MAX485) и развернуть на двух последовательных портах NodeMcu две сети Modbus с двумя вариантами настройки параметров последовательного порта (9600-SERIAL_8N1 и 9600-SERIAL_8N2).
Ну или подскажите, как решить проблему компиляции и как добавить ещё один порт, который умеет работать с двумя стоповыми битами. :)
Далее в ходе реализации проекта на основе аппаратного последовательного порта столкнулся с проблемой компиляции
Скетч не подходит для платы NodeMcu, потому что она на микроконтроллере ESP8266. А в скетче используются регистры конфигурации интерфейса UART для платы Ардуино с микроконтроллером AVR.
Вы даже не представляете себе, как смешно это звучит.
Евгений, согласен с вами - сформулирована проблема коряво.
Dubser - мой коллега, который больше работает с паяльником , чем с кодом )
Попробую прояснить проблему, может вы что-то подскажете...
Мы в FLProg 3.1.2 создали проект под NodeMCU v3 для чтения по Modbus-RTU (через конвертер UART-RS485) SlaveModbus датчика.
При настройке в проекте Hardware SerialPort при компиляции в Arduino IDE выдается ошибка:
error: 'UCSR0A' was not declared in this scope
UCSR0A=UCSR0A |(1 << TXC0);
error: 'TXC0' was not declared in this scope
Затем попробовали перейти на SoftwareSerial port и скетч заработал (данные забегали по Modbus на тестовом датчике, работающему по протоколу 8N1).
Вопрос возник на последнем этапе - когда выяснилось, что один из SlaveModbus работает по протоколу 8N2(с двумя стоповыми битами)), а стандартная библиотека SoftwareSeria не поддерживает такую опцию.
Теперь у нас непонятка как быть - либо попытаться (с чьей-то помощью)))) разобраться что за проблема в FLProg и поднять Harware serial (а потом "руками" включить в коде опцию SERIAL_8N2), либо искать библиотеку Softwareserial c таким расширением.
Я не знаю, что Вам лучше делать, я бы, конечно, поднимал аппаратный сериал. UART на ноде имеется, значит поднять его как-то можно. Но я бы и flprog'ом не пользовался.
А смешно звучит это потому что, ну вот перечитайте
Далее в ходе реализации проекта на основе аппаратного последовательного порта столкнулся с проблемой компиляции
Первая часть фразы (зелёная) звучит как хорошо поставленная, грамотная речь и оставляет впечатление нормального, грамотного специалиста, а красная - как будто из другого текста, другого автора. Понимаете, при минимальной квалификации и грамотности специалиста, слова "компиляция" и "проблема" не могут соять рядом - он не совместимы между собой. Никаких "проблем компиляции" не существует в природе. Ну, это примерно, как если бы военная сводка выглядела так: "Продвижение 123 гв. танковой дивизии в обход фланга противника было остановлено внезапно возникшей проблемой - к поручням моста через ручей в деревне Гадюкино оказалась привязана собака, которая охраняет мост и никого на него не пускает". Понимаете, вот как ручей и собака не могут быть проблемой для танковой дивизии, так и компиляция не может быть проблемой для специалиста с отличной от нуля квалификацией. Первая и вторая части процитированной фразы настолько противоречат друг другу, что здорово улыбнуло.
Мы в FLProg 3.1.2 создали проект под NodeMCU
В этой поделке FLProg вообще поддерживаются платы NodeMCU (микроконтроллер ESP8266)? Если вы там выбираете NodeMCU (ESP8266), а оно генерит вам скетч для AVR, то передавайте пламенный привет автору FLProg...
#include <ESP8266WiFi.h> int _modbusSlaveDataTable_4[3]; int _modbusSlaveAddresTable_4[3] = {0, 1, 2}; int _modbusMasterDataTable_4_reg_16[3]; int _modbusMasterAddressTable_4_reg_16[3] = {258, 259, 260}; byte _modbusSlaveBufferSize = 0; byte _modbusSlaveBuffer[64]; const unsigned char _modbusSlave_fctsupported[] = {3, 6, 16}; WiFiServer _modbusSlaveTCPServer(502); WiFiClient _modbusSlaveTCPClient; byte _modbusSlaveMBAPBuffer[6]; 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[] = {5000}; const unsigned char _modbusMaster_fctsupported[] = {3, 6, 16}; const char* ESP8266ControllerWifi_SSID = "BLUE_ELEPHANT"; const char* ESP8266ControllerWifi_password = ""; bool ESP8266ControllerWifi_status = 0; void setup() { WiFi.mode(WIFI_STA ); WiFi.begin(ESP8266ControllerWifi_SSID, ESP8266ControllerWifi_password); Serial.begin(9600); pinMode(12, OUTPUT); digitalWrite(12, LOW); for(int i=0; i<1; i++) {_startTimeMasterRegs[i] = millis();} _modbusSlaveTCPServer.begin(); } void loop() {_modbusSlavePoll(); ESP8266ControllerWifi_status = WiFi.status() == WL_CONNECTED; //Плата:1 _modbusSlaveDataTable_4[0] = (_modbusMasterDataTable_4_reg_16[0]); _modbusSlaveDataTable_4[1] = (_modbusMasterDataTable_4_reg_16[1]); _modbusSlaveDataTable_4[2] = (_modbusMasterDataTable_4_reg_16[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; } byte _modbusSlavePoll() { if( !_modbusSlaveTCPClient.connected()) {_modbusSlaveTCPClient = _modbusSlaveTCPServer.available();} if (_modbusSlaveTCPClient) { _modbusGetSlaveRxBuffer();} else{return 0;} if(_modbusSlaveBufferSize ==0) {return 0;} if ((_modbusSlaveBuffer[0] != 1) && (_modbusSlaveBuffer[0] != 0)) return 0; byte exception = _modbusValidateRequest(); if (exception > 0) { if (exception != 255) { _modbusSlaveBuildException( exception ); _modbusSlaveSendTxBuffer(); } return exception; } switch ( _modbusSlaveBuffer[1] ) { case 3 : return process_modbus_FC3(4); break; case 6 : return process_modbus_FC6(); break; case 16 : return process_modbus_FC16(); break; default: break; } return 25; } byte _modbusValidateRequest() { boolean isSupported = false; for (uint8_t i = 0; i < sizeof( _modbusSlave_fctsupported ); i++) { if (_modbusSlave_fctsupported[i] == _modbusSlaveBuffer[1]) { isSupported = 1; break; } } if (!isSupported) { return 1;} int intRegs = 0; byte byteRegs; switch ( _modbusSlaveBuffer[1] ) { case 6 : if(!(checkModbusAddres(( word( _modbusSlaveBuffer[2], _modbusSlaveBuffer[3]) ),4))){return 2;} break; case 3 : case 16 : if(!(checkModbusRange((word( _modbusSlaveBuffer[2], _modbusSlaveBuffer[3])), (word( _modbusSlaveBuffer[4], _modbusSlaveBuffer[5])),4))){return 2;} break; } return 0; // OK, no exception code thrown } bool checkModbusAddres(int addr, byte table) { return (!(( modbusSlaveIndexForAddres(addr,table)) == -1)); } int modbusSlaveIndexForAddres(int addr, byte table) { int tableSize = 0; switch (table) { case 4: tableSize = 3; break; } for (byte i = 0; i < tableSize; i++) {if((modbusSlaveAddresFromIndex(i,table)) == addr){return i;}} return -1; } int modbusSlaveAddresFromIndex(byte index, byte table) { switch (table) { case 4: return _modbusSlaveAddresTable_4[index]; break; } return -1; } bool checkModbusRange(int startAddr, int addrNumber, byte table) { for (int i=0; i < addrNumber; i++) {if(!(checkModbusAddres((startAddr+i),table))){return false;}} return true; } void _modbusSlaveBuildException( byte exception ) { byte func = _modbusSlaveBuffer[1]; _modbusSlaveBuffer[0] = 1; _modbusSlaveBuffer[1] = func + 0x80; _modbusSlaveBuffer[ 2 ] = exception; _modbusSlaveBufferSize = 3;} void _modbusSlaveSendTxBuffer() { if(_modbusSlaveBuffer[0] == 0) {_modbusSlaveTCPClient.stop(); return;} String stringBuffer = ""; _modbusSlaveMBAPBuffer[4] = highByte(_modbusSlaveBufferSize); _modbusSlaveMBAPBuffer[5] = lowByte(_modbusSlaveBufferSize); for (int i=0; i <6; i++){stringBuffer.concat(char( _modbusSlaveMBAPBuffer[i] ));} for (int i=0; i <_modbusSlaveBufferSize; i++){stringBuffer.concat(char( _modbusSlaveBuffer[i]));} _modbusSlaveTCPClient.print(stringBuffer); _modbusSlaveBufferSize = 0; } byte _modbusGetSlaveRxBuffer() { byte currentByte = 0; boolean bBuffOverflow = false; byte currentByteIndex = 0; _modbusSlaveBufferSize = 0; while (_modbusSlaveTCPClient.available() ) {currentByte = _modbusSlaveTCPClient.read(); if (currentByteIndex < 6) {_modbusSlaveMBAPBuffer[currentByteIndex] = currentByte; } else { _modbusSlaveBuffer[ _modbusSlaveBufferSize ] = currentByte; _modbusSlaveBufferSize ++; if (_modbusSlaveBufferSize >= 64) bBuffOverflow = true;} currentByteIndex++; } if (bBuffOverflow) {return -3; } return _modbusSlaveBufferSize; } byte process_modbus_FC3(byte table) { int startAddr = word( _modbusSlaveBuffer[2], _modbusSlaveBuffer[3] ); int byteRegsno = word( _modbusSlaveBuffer[4], _modbusSlaveBuffer[5] ); int i; int value; byte index; _modbusSlaveBuffer[ 2 ] = byteRegsno * 2; _modbusSlaveBufferSize = 3; for (i = startAddr; i < startAddr + byteRegsno; i++) { index = modbusSlaveIndexForAddres(i, table); if (table == 4) {value = _modbusSlaveDataTable_4[index]; } _modbusSlaveBuffer[ _modbusSlaveBufferSize ] = highByte(value); _modbusSlaveBufferSize++; _modbusSlaveBuffer[ _modbusSlaveBufferSize ] = lowByte(value); _modbusSlaveBufferSize++; } _modbusSlaveSendTxBuffer(); return _modbusSlaveBufferSize + 2; } byte process_modbus_FC6() { int addres = word( _modbusSlaveBuffer[2], _modbusSlaveBuffer[3] ); int index; index = modbusSlaveIndexForAddres(addres, 4); _modbusSlaveDataTable_4[index] =word( _modbusSlaveBuffer[4], _modbusSlaveBuffer[5] ); _modbusSlaveBufferSize = 6; _modbusSlaveSendTxBuffer(); return _modbusSlaveBufferSize + 2; } byte process_modbus_FC16( ) { byte func = _modbusSlaveBuffer[1]; int startAddr = _modbusSlaveBuffer[2] << 8 | _modbusSlaveBuffer[3]; int byteRegsno = _modbusSlaveBuffer[4] << 8 | _modbusSlaveBuffer[5]; int i; int index; _modbusSlaveBuffer[4] = 0; _modbusSlaveBuffer[5] = byteRegsno; _modbusSlaveBufferSize = 6; for (i = 0; i < byteRegsno; i++) { index = modbusSlaveIndexForAddres((startAddr+i), 4); _modbusSlaveDataTable_4[index] =word( _modbusSlaveBuffer[ 7 + i * 2 ], _modbusSlaveBuffer[8 + i * 2 ]); } _modbusSlaveSendTxBuffer(); return _modbusSlaveBufferSize +2; } 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 = 16; switch (_modbusMasterCurrentVariable) { case 1: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 258; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 0; break; case 2: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 259; _modbusTelegramm.numbeRegs = 1; _modbusTelegramm.valueIndex = 1; break; case 3: _modbusTelegramm.function = 3; _modbusTelegramm.startAddres = 260; _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++; UCSR0A=UCSR0A |(1 << TXC0); digitalWrite(12, 1 ); delay(5); Serial.write( _modbusMasterBuffer, _modbusMasterBufferSize ); while (!(UCSR0A & (1 << TXC0))); digitalWrite(12, 0 ); Serial.flush(); _modbusMasterBufferSize = 0; _modbusMasterSendTime = millis(); } void pollModbusMaster() { if (_modbusTelegramm.slaveId == 0) { _modbusMasterState = 1; return;} if (_isTimer(_modbusMasterSendTime, 1000)) { _modbusMasterState = 1; return; } byte avalibleBytes = Serial.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(12, LOW ); _modbusMasterBufferSize = 0; while (Serial.available() ) { _modbusMasterBuffer[ _modbusMasterBufferSize ] = Serial.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_16[currentIndex + i] =value;} break; } currentByte += 2; } }при минимальной квалификации и грамотности специалиста, слова "компиляция" и "проблема" не могут соять рядом - он не совместимы между собой. Никаких "проблем компиляции" не существует в природе. Ну, это примерно, как если бы военная сводка выглядела так: "Продвижение 123 гв. танковой дивизии в обход фланга противника было остановлено внезапно возникшей проблемой - к поручням моста через ручей в деревне Гадюкино оказалась привязана собака, которая охраняет мост и никого на него не пускает". Понимаете, вот как ручей и собака не могут быть проблемой для танковой дивизии, так и компиляция не может быть проблемой для специалиста с отличной от нуля квалификацией. Первая и вторая части процитированной фразы настолько противоречат друг другу, что здорово улыбнуло.
Ну, вы, батенька, прямо философ-лингвист какой-то (точнее - демагог) !
А так понятнее будет звучать ? :
Далее в ходе реализации проекта на основе аппаратного последовательного порта после компиляции столкнулся с ошибками при проверке
Если нет, предложите другой термин для объяснения сложившейся ситуации :
Пользователь создал проект в FLProg-е 3.1.2 с заявленной полной поддержкой платы NodeMcu V3 Lua WI-FI (микроконтроллер ESP8266), использовав аппаратный последовательный порт (по-вашему, аппаратный сериал), и после нажатия кнопки "Компилировать", был сгенерирован скетч для Arduino, который не прошёл дальнейшую проверку в Arduino IDE : вышло одно сообщение об ошибке, а после задекларирования в скетче соответствующей логической переменной 'UCSR0A', другое сообщение об ошибке, которая была исправлена таким же образом. Однако эти "танцы с бубном" позволили прошить контроллер, но проект так и остался не работоспособен.
Если бы не эти ошибки, то можно было бы изменить в скетче настройки параметров последовательного порта с 9600-SERIAL_8N1 на 9600-SERIAL_8N2, и, вероятно, всё бы заработало так, как надо, хотя бы для одной сети Modbus.
Вся фишка в том, что после замены в FLProg аппаратного последовательного порта на программный, сообщение об ошибке при проверке скетча не появляется ни разу.
В этой поделке FLProg вообще поддерживаются платы NodeMCU (микроконтроллер ESP8266)? Если вы там выбираете NodeMCU (ESP8266), а оно генерит вам скетч для AVR, то передавайте пламенный привет автору FLProg...
Так в том то и дело, что, начиная с версии 3.1.2, в этой поделке FLProg было заявлено о полной поддержке платы NodeMcu V3 Lua WI-FI (микроконтроллер ESP8266), т. е. без "шаманства" и "танцев с бубном" с портами контроллера !
Можете ткнуть носом в строки скетча, доказывающие, что "оно генерит скетч для AVR", а не для платы NodeMcu V3 Lua WI-FI (микроконтроллер ESP8266) ?
Можете ткнуть носом в строки скетча, доказывающие, что "оно генерит скетч для AVR", а не для платы NodeMcu V3 Lua WI-FI (микроконтроллер ESP8266) ?
Т.к. скетча в этой теме ни Вы, ни Andrew54321 до сих пор не привели, могу ткнуть только в сообщение об ошибке. Я уже писал: UCSR0A - имя регистра аппаратного интерфейса USART, а TXC0 - бит в этом регистре. Пруф - даташит на микроконтроллер AVR ATmega328P (стр. 245)
UPD: Не сразу заметил скетч под спойлером в сообщении #6. Тогда тыкаю в строки скетча №334, 338.
UPD2: Бегло просмотрел весь скетч, больше таких ошибок с регистрами для AVR не нашёл.
Я думаю, Вам стоит написать в поддержку/авторам FLProg.
Если нет, предложите другой термин для объяснения сложившейся ситуации :
А что я могу предложить?
Я лишь отметил, что нечасто увидишь грамотную речь и "проблемы компиляции". Обычно "проблемы компиляции" возникают у тех, кто выражается примерно так: "скачал прогу, припаял резюк, запустил, а она никампилица. Это патаму что ардуина китайская? У кого какие идеи?". ВОт у таких ребят бывают "проблемы компиляции", а у Вас вроде не должно быть.
............
Вопрос возник на последнем этапе - когда выяснилось, что один из SlaveModbus работает по протоколу 8N2(с двумя стоповыми битами)), а стандартная библиотека SoftwareSeria не поддерживает такую опцию.
Теперь у нас непонятка как быть - либо попытаться (с чьей-то помощью)))) разобраться что за проблема в FLProg и поднять Harware serial (а потом "руками" включить в коде опцию SERIAL_8N2), либо искать библиотеку Softwareserial c таким расширением.
Есть в комплекте ардуино иде, второй стоповый бит там несложно добавить. Есть на гитхабе для ESP8266, вроде бы тоже несложно допилить.
что такое "стандартная библиотека SoftwareSeria" ?
Та, которая есть в комплекте Arduino IDE.
второй стоповый бит там несложно добавить.
Мы, конечно, понимаем, что на этом форуме сидят, в основном, программисты C++, однако вынужден отметить, что среди нас спецов такого уровня пока нет.
"Не будет ли столь любезен многоуважаемый джин" . . . помочь этим недоумкам и допилить за них эту библиотеку Softwareserial для ESP8266, чтобы можно было бы включить в коде опцию 8N2 (с двумя стоповыми битами).
А если бы "многоуважаемый джин" был бы столь любезен, что объяснил бы ещё, как прикрутить к NodeMcu два последовательных порта для одновременной работы (считывания показаний буржуйских контроллеров в двух сетях Modbus с разными протоколами - 8N1 и 8N2), если проделать это с одной общей сетью невозможно, то у этих недоумков не хватило бы слов благодарности !
стоит написать в поддержку/авторам FLProg.
Уже написали на форум и в поддержку, в том числе и автору FLProg (https://forum.flprog.ru/viewtopic.php?t=4234 и https://forum.flprog.ru/viewtopic.php?t=4045&start=460), но пока никто не ответил по существу.
Уже написали на форум и в поддержку, но пока никто не ответил по существу.
Видимо, не теми словами писали.
что такое "стандартная библиотека SoftwareSeria" ?
Та, которая есть в комплекте Arduino IDE.
второй стоповый бит там несложно добавить.
Мы, конечно, понимаем, что на этом форуме сидят, в основном, программисты C++, однако вынужден отметить, что среди нас спецов такого уровня пока нет.
"Не будет ли столь любезен многоуважаемый джин" . . . помочь этим недоумкам и допилить за них эту библиотеку Softwareserial для ESP8266, чтобы можно было бы включить в коде опцию 8N2 (с двумя стоповыми битами).
А если бы "многоуважаемый джин" был бы столь любезен, что объяснил бы ещё, как прикрутить к NodeMcu два последовательных порта для одновременной работы (считывания показаний буржуйских контроллеров в двух сетях Modbus с разными протоколами - 8N1 и 8N2), если проделать это с одной общей сетью невозможно, то у этих недоумков не хватило бы слов благодарности !
попробую по порядку.
1. у меня ИДЕ 1_8_5, win7-64. В комплекте есть файл SoftwareSerial.cpp длиной 13444. Я понятия не имею, будет ли эта библиотека корректно работать с ESP8266 (а должна ли?). Но если бы мне нужно было перенастроить передачу с формата 8N1 на 8N2, я бы попробовал заменить строку "tunedDelay(_rx_delay_stopbit);" на строку "tunedDelay(_rx_delay_stopbit*2);".
2. Я не программист С++. Более того - я вообще не программист.
3. Поиск по "Softwareserial для ESP826" дает "Результатов: примерно 60 600 (0,49 сек.) ". Если потыкать в результаты - можно попасть, например, в "ESP8266 TWO SERIAL PORTS WITH SOFTWARESERIAL LIBRARY" (что-то напоминает?), а оттуда в "https://github.com/plerup/espsoftwareserial". И если бы мне нужно было перенастроить передачу с формата 8N1 на 8N2, я бы попробовал в файле SoftwareSerial.cpp добавить в двух местах строку "WAIT;".
4. Сомневаюсь, что нужно городить огород с двумя протоколами передачи. Сдается мне, что приемник, настроенный на 8N1, нормально воспримет байты, переданные в форматах 8N1 или 8N2 - на то она и асинхронная передача.
в файле SoftwareSerial.cpp добавить в двух местах строку "WAIT;".
В каких конкретно двух местах ? И почему именно "WAIT;", а не "tunedDelay(_rx_delay_stopbit*2);" ?
приемник, настроенный на 8N1, нормально воспримет байты, переданные в форматах 8N1 или 8N2
но до того, как принять на наш приемник, настроенный на 8N1, байты, переданные в формате 8N2 от буржуйского контроллера, нужно передать запрос на этот буржуйский контроллер обязательно (!) в формате 8N2 (проверено подключением PC через RS485). На запрос в формате 8N1 этот буржуйский контроллер тупо не отвечает !.
в файле SoftwareSerial.cpp добавить в двух местах строку "WAIT;".
В каких конкретно двух местах ? И почему именно "WAIT;", а не "tunedDelay(_rx_delay_stopbit*2);" ?
duser, если бы вы удосужились ткнуть в готовую ссылку в моем п. 3, вы попали бы на страницу с библиотекой EspSoftwareSerial, у вас появилась бы возможность прочитать листинг и узнать, что же написано в той библиотеке. Какого икса вы это не сделали?
приемник, настроенный на 8N1, нормально воспримет байты, переданные в форматах 8N1 или 8N2
Запрещать сейчас некому.
если бы вы удосужились ткнуть в готовую ссылку в моем п. 3, вы попали бы на страницу с библиотекой EspSoftwareSerial, у вас появилась бы возможность прочитать листинг и узнать, что же написано в той библиотеке. Какого икса вы это не сделали?
ну так найдите нормальную библиотеку для ESP8266, допилите для передачи 8N2
Ну, вообще-то я не программист, а простой электронщик, и для меня заглядывать в библиотеку EspSoftwareSerial, всё равно что блондинке заглядывать под капот автомобиля --- всё равно я там почти ничего не пойму. Я ремонтировать/паять умею, в электрических схемах немного разбираюсь. В программном коде я, к сожалению, не разбираюсь.
Ну, вообще-то я не программист, а простой электронщик, и для меня заглядывать в библиотеку EspSoftwareSerial, всё равно что блондинке заглядывать под капот автомобиля --- всё равно я там почти ничего не пойму. Я ремонтировать/паять умею, в электрических схемах немного разбираюсь. В программном коде я, к сожалению, не разбираюсь.
На этом форуме есть несколько знающих людей - но они вряд ли без особой надобности будут разбираться с чужим слепым кодом без комментариев. Автоматические кодогенераторы - вещь интересная до тех пор, пока не появится необходимость найти/исправить ошибку или что-то изменить в тексте программы.
========================
"Ребята, я прошу прощения, но у нас сглючила пожарная сигнализация в компьютере, поэтому заблокированы все лифты и двери, включая дверь на улицу. Это починят и разблокируют через четверть часа, а пока мы можем только пить кофе.
- Интересная пожарная сигнализация, - заметил Хаамеа, - Специально блокирует двери, чтобы в случае распространения огня никто не ушел живым. В этом что-то есть.
- У программиста кривые руки, - предположила Маи Ку, шлепаясь за столик в кресло. Велосипед она уже успела приставить к стойке.
- Тут в редакции весь софтвер с сертификатом и лицензией, - уверенно сказал Макдэйл, наливая кофе из автомата последовательно в три бумажные чашечки.
- Ну и что? – спросила китаянка, - сертификат и лицензия от кривых рук не спасает.
Переместив чашечки на столик и поставив рядом коробку с пакетиками сахара, Макдэйл авторитетно сообщил:
- Кривые руки тут не при чем. Сейчас программы пишет программа, которую написала третья программа, которую черт его знает, кто написал. По крайней мере, так нам это объясняли в колледже на занятиях по computer science.
- У черт знает кого тоже могли быть кривые руки, - резонно ответила Маи Ку.
- Реально, - согласился с ней Хаамеа"