NodeMcu V3 Lua + две платы MAX485: 2 сети Modbus с двумя вариантами настройки параметров порта (8N1 и 8N2)

duser
Offline
Зарегистрирован: 27.08.2018

Уважаемые знатоки !

Помогите советами по правильному построению сети 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). 
 
Ну или подскажите, как решить проблему компиляции и как добавить ещё один порт, который умеет работать с двумя стоповыми битами. :)
Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Цитата:

Далее в ходе реализации проекта на основе аппаратного последовательного порта столкнулся с проблемой компиляции 

Скетч не подходит для платы NodeMcu, потому что она на микроконтроллере ESP8266. А в скетче используются регистры конфигурации интерфейса UART для платы Ардуино с микроконтроллером AVR.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

duser пишет:

Далее в ходе реализации проекта на основе аппаратного последовательного порта столкнулся с проблемой компиляции

Вы даже не представляете себе, как смешно это звучит.

Andrew54321
Offline
Зарегистрирован: 28.08.2018

Евгений, согласен с вами - сформулирована проблема коряво.
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

 UCSR0A=UCSR0A |(1 << TXC0);
 

Затем попробовали перейти на SoftwareSerial port и скетч заработал (данные забегали по Modbus на тестовом датчике, работающему по протоколу 8N1). 

Вопрос возник на последнем этапе - когда выяснилось, что один из SlaveModbus работает по протоколу 8N2(с двумя стоповыми битами)), а стандартная библиотека SoftwareSeria не поддерживает такую опцию.

Теперь у нас непонятка как быть - либо попытаться (с чьей-то помощью))))  разобраться что за проблема в FLProg и поднять Harware serial (а потом "руками" включить в коде опцию SERIAL_8N2),  либо искать библиотеку Softwareserial c таким расширением.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Я не знаю, что Вам лучше делать, я бы, конечно, поднимал аппаратный сериал. UART на ноде имеется, значит поднять его как-то можно. Но я бы и flprog'ом не пользовался.

А смешно звучит это потому что, ну вот перечитайте

duser пишет:

Далее в ходе реализации проекта на основе аппаратного последовательного порта столкнулся с проблемой компиляции

Первая часть фразы (зелёная) звучит как хорошо поставленная, грамотная речь и оставляет впечатление нормального, грамотного  специалиста, а красная - как будто из другого текста, другого автора. Понимаете, при минимальной квалификации и грамотности специалиста, слова "компиляция" и "проблема" не могут соять рядом - он не совместимы между собой. Никаких "проблем компиляции" не существует в природе. Ну, это примерно, как если бы военная сводка выглядела так: "Продвижение 123 гв. танковой дивизии в обход фланга противника было остановлено внезапно возникшей проблемой - к поручням моста через ручей в деревне Гадюкино оказалась привязана собака, которая охраняет мост и никого на него не пускает". Понимаете, вот как ручей и собака не могут быть проблемой для танковой дивизии, так и компиляция не может быть проблемой для специалиста с отличной от нуля квалификацией. Первая и вторая части процитированной фразы настолько противоречат друг другу, что здорово улыбнуло.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Andrew54321 пишет:

Мы в FLProg 3.1.2  создали проект под NodeMCU

В этой поделке FLProg вообще поддерживаются платы NodeMCU (микроконтроллер ESP8266)? Если вы там выбираете NodeMCU (ESP8266), а оно генерит вам скетч для AVR, то передавайте пламенный привет автору FLProg...

duser
Offline
Зарегистрирован: 27.08.2018
#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 аппаратного последовательного порта на программный, сообщение об ошибке при проверке скетча не появляется ни разу.

duser
Offline
Зарегистрирован: 27.08.2018

Jeka_M пишет:

В этой поделке FLProg вообще поддерживаются платы NodeMCU (микроконтроллер ESP8266)? Если вы там выбираете NodeMCU (ESP8266), а оно генерит вам скетч для AVR, то передавайте пламенный привет автору FLProg...

Так в том то и дело, что, начиная с версии 3.1.2, в этой поделке FLProg было заявлено о полной поддержке платы NodeMcu V3 Lua WI-FI (микроконтроллер ESP8266), т. е. без "шаманства" и "танцев с бубном" с портами контроллера !

Можете ткнуть носом в строки скетча, доказывающие, что "оно генерит скетч для AVR", а не для платы NodeMcu V3 Lua WI-FI (микроконтроллер ESP8266) ?

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

duser пишет:

Можете ткнуть носом в строки скетча, доказывающие, что "оно генерит скетч для AVR", а не для платы NodeMcu V3 Lua WI-FI (микроконтроллер ESP8266) ?

Т.к. скетча в этой теме ни Вы, ни Andrew54321 до сих пор не привели, могу ткнуть только в сообщение об ошибке. Я уже писал: UCSR0A - имя регистра аппаратного интерфейса USART, а TXC0 - бит в этом регистре. Пруф - даташит на микроконтроллер AVR ATmega328P (стр. 245)

UPD: Не сразу заметил скетч под спойлером в сообщении #6. Тогда тыкаю в строки скетча №334, 338.

UPD2: Бегло просмотрел весь скетч, больше таких ошибок с регистрами для AVR не нашёл.

Я думаю, Вам стоит написать в поддержку/авторам FLProg.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

duser пишет:

Если нет, предложите другой термин для объяснения сложившейся ситуации :

А что я могу предложить?

Я лишь отметил, что нечасто увидишь грамотную речь и "проблемы компиляции". Обычно "проблемы компиляции" возникают у тех, кто выражается примерно так: "скачал прогу, припаял резюк, запустил, а она никампилица. Это патаму что ардуина китайская? У кого какие идеи?". ВОт у таких ребят бывают "проблемы компиляции", а у Вас вроде не должно быть.

SLKH
Offline
Зарегистрирован: 17.08.2015

Andrew54321 пишет:

............
Вопрос возник на последнем этапе - когда выяснилось, что один из SlaveModbus работает по протоколу 8N2(с двумя стоповыми битами)), а стандартная библиотека SoftwareSeria не поддерживает такую опцию.

Теперь у нас непонятка как быть - либо попытаться (с чьей-то помощью))))  разобраться что за проблема в FLProg и поднять Harware serial (а потом "руками" включить в коде опцию SERIAL_8N2),  либо искать библиотеку Softwareserial c таким расширением.

что такое "стандартная библиотека SoftwareSeria" ? 

Есть в комплекте ардуино иде, второй стоповый бит там несложно добавить. Есть на гитхабе для ESP8266, вроде бы тоже несложно допилить.

 

duser
Offline
Зарегистрирован: 27.08.2018

SLKH пишет:

что такое "стандартная библиотека SoftwareSeria" ? 

Та, которая есть в комплекте Arduino IDE.

SLKH пишет:

второй стоповый бит там несложно добавить.

Мы, конечно, понимаем, что на этом форуме сидят, в основном, программисты C++, однако вынужден отметить, что среди нас спецов такого уровня пока нет.  

"Не будет ли столь любезен многоуважаемый джин" . . .  помочь этим недоумкам и допилить за них эту библиотеку Softwareserial для ESP8266, чтобы можно было бы  включить в коде опцию 8N2 (с двумя стоповыми битами).

А если бы "многоуважаемый джин" был бы столь любезен, что объяснил бы ещё, как прикрутить к NodeMcu два последовательных порта для одновременной работы (считывания показаний буржуйских контроллеров в двух сетях Modbus с разными протоколами -  8N1 и 8N2), если проделать это с одной общей сетью невозможно, то  у этих недоумков не хватило бы слов благодарности !

 

duser
Offline
Зарегистрирован: 27.08.2018

Jeka_M пишет:

стоит написать в поддержку/авторам FLProg.

Уже написали на форум и в поддержку, в том числе и автору FLProg (https://forum.flprog.ru/viewtopic.php?t=4234  и  https://forum.flprog.ru/viewtopic.php?t=4045&start=460), но пока никто не ответил по существу.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

duser пишет:

Уже написали на форум и в поддержку, но пока никто не ответил по существу.

Видимо, не теми словами писали. 

SLKH
Offline
Зарегистрирован: 17.08.2015

duser пишет:

SLKH пишет:

что такое "стандартная библиотека SoftwareSeria" ? 

Та, которая есть в комплекте Arduino IDE.

SLKH пишет:

второй стоповый бит там несложно добавить.

Мы, конечно, понимаем, что на этом форуме сидят, в основном, программисты 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 - на то она и асинхронная передача.

 

 

 

duser
Offline
Зарегистрирован: 27.08.2018

SLKH пишет:

в файле SoftwareSerial.cpp добавить в двух местах строку "WAIT;". 

В каких конкретно двух местах ?  И почему именно "WAIT;",  а не "tunedDelay(_rx_delay_stopbit*2);" ?

SLKH пишет:

приемник, настроенный на 8N1, нормально воспримет байты, переданные в форматах 8N1 или 8N2

но до того, как принять на наш приемник, настроенный на 8N1,  байты, переданные в формате 8N2 от буржуйского контроллера, нужно передать запрос на этот буржуйский контроллер обязательно (!) в формате 8N2 (проверено подключением PC через RS485).  На запрос в формате 8N1 этот буржуйский контроллер тупо не отвечает !.

SLKH
Offline
Зарегистрирован: 17.08.2015

duser пишет:

SLKH пишет:

в файле SoftwareSerial.cpp добавить в двух местах строку "WAIT;". 

В каких конкретно двух местах ?  И почему именно "WAIT;",  а не "tunedDelay(_rx_delay_stopbit*2);" ?

duser, если бы вы удосужились ткнуть в готовую ссылку в моем п. 3, вы попали бы на страницу с библиотекой EspSoftwareSerial, у вас появилась бы возможность прочитать листинг и узнать, что же написано в той библиотеке. Какого икса вы это не сделали?

SLKH пишет:

приемник, настроенный на 8N1, нормально воспримет байты, переданные в форматах 8N1 или 8N2

duser пишет:
но до того, как принять на наш приемник, настроенный на 8N1,  байты, переданные в формате 8N2 от буржуйского контроллера, нужно передать запрос на этот буржуйский контроллер обязательно (!) в формате 8N2 (проверено подключением PC через RS485).  На запрос в формате 8N1 этот буржуйский контроллер тупо не отвечает !.

ну так найдите нормальную библиотеку для ESP8266, допилите для передачи 8N2, подключите к своей программе и посылайте свой запрос.

Запрещать сейчас некому.

duser
Offline
Зарегистрирован: 27.08.2018

SLKH пишет:

если бы вы удосужились ткнуть в готовую ссылку в моем п. 3, вы попали бы на страницу с библиотекой EspSoftwareSerial, у вас появилась бы возможность прочитать листинг и узнать, что же написано в той библиотеке. Какого икса вы это не сделали?

SLKH пишет:

ну так найдите нормальную библиотеку для ESP8266, допилите для передачи 8N2

Ну, вообще-то я не программист, а простой электронщик, и для меня заглядывать в библиотеку EspSoftwareSerial, всё равно что блондинке заглядывать под капот автомобиля --- всё равно я там почти ничего не пойму. Я ремонтировать/паять умею, в электрических схемах немного разбираюсь. В программном коде я, к сожалению, не разбираюсь.

SLKH
Offline
Зарегистрирован: 17.08.2015

duser пишет:

Ну, вообще-то я не программист, а простой электронщик, и для меня заглядывать в библиотеку EspSoftwareSerial, всё равно что блондинке заглядывать под капот автомобиля --- всё равно я там почти ничего не пойму. Я ремонтировать/паять умею, в электрических схемах немного разбираюсь. В программном коде я, к сожалению, не разбираюсь.

Я тоже не программист. Моих познаний хватает только для понимания, что для правильного построения сети Modbus на основе NodeMcu V3 Lua WI-FI некоторые знания о программировании всё же необходимы.

На этом форуме есть несколько знающих людей - но они вряд ли без особой надобности будут разбираться с чужим слепым кодом без комментариев. Автоматические кодогенераторы - вещь интересная до тех пор, пока не появится необходимость найти/исправить ошибку или что-то изменить в тексте программы.

========================

"Ребята, я прошу прощения, но у нас сглючила пожарная сигнализация в компьютере, поэтому заблокированы все лифты и двери, включая дверь на улицу. Это починят и разблокируют через четверть часа, а пока мы можем только пить кофе.

- Интересная пожарная сигнализация, - заметил Хаамеа, - Специально блокирует двери, чтобы в случае распространения огня никто не ушел живым. В этом что-то есть.  

- У программиста кривые руки, - предположила Маи Ку, шлепаясь за столик в кресло. Велосипед она уже успела приставить к стойке.

- Тут в редакции весь софтвер с сертификатом и лицензией, - уверенно сказал Макдэйл, наливая кофе из автомата последовательно в три бумажные чашечки.

- Ну и что? – спросила китаянка, - сертификат и лицензия от кривых рук не спасает.

Переместив чашечки на столик и поставив рядом коробку с пакетиками сахара, Макдэйл авторитетно сообщил:

- Кривые руки тут не при чем. Сейчас программы пишет программа, которую написала третья программа, которую черт его знает, кто написал. По крайней мере, так нам это объясняли в колледже на занятиях по computer science. 

- У черт знает кого тоже могли быть кривые руки, - резонно ответила Маи Ку.

- Реально, - согласился с ней Хаамеа"