Данные, получаемые от слейва, хаотично меняются местами
Проблема есть.
Код: Выделить всё
#include <ESP8266WiFi.h>
int _modbusMasterDataTable_3_reg_1_server1[5];
byte _modbusMasterBufferSize = 0;
byte _modbusMasterState = 1;
long _modbusMasterSendTime;
byte _modbusMasterBuffer[64];
struct _modbusMasterTelegramm {
byte slaveId;
byte function;
int startAddres;
int numbeRegs;
int valueIndex;
IPAddress ip;
int port;
int serverId;
int answerId;
};
_modbusMasterTelegramm _modbusTelegramm;
long _startTimeMasterRegs[1];
long _updateTimeMasterRegsArray[] = {1000};
const unsigned char _modbusMaster_fctsupported[] = {4};
IPAddress SlaveInMasterTCPServer_1(192, 168, 3, 33);
WiFiClient _ModbsTCPMasterClient;
char ESPControllerWifiClient_SSID[40] = "Avtomatik";
char ESPControllerWifiClient_password[40] = "1029384756";
String _gtv1;
int _gtv2;
int _gtv3;
int _gtv4;
int _gtv5;
int _gtv6;
String _stou1;
bool abc;
bool connnect;
long time_recon;
void setup()
{
WiFi.mode(WIFI_STA);
WiFi.begin(ESPControllerWifiClient_SSID, ESPControllerWifiClient_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Serial.begin(115200, SERIAL_8N1);
pinMode(LED_BUILTIN, OUTPUT);
time_recon = millis();
}
void loop()
{
/* if (!connnect){
if ((millis() - time_recon)> 10000){time_recon = millis();ESPControllerWifiClient_IsNeedReconect = 1;}
else{time_recon = millis();}
} */
digitalWrite(LED_BUILTIN, abc); // turn the LED on (HIGH is the voltage level)
//Плата:1
_gtv2 = (_modbusMasterDataTable_3_reg_1_server1[0]);
_gtv3 = (_modbusMasterDataTable_3_reg_1_server1[1]);
_gtv4 = (_modbusMasterDataTable_3_reg_1_server1[2]);
_gtv5 = (_modbusMasterDataTable_3_reg_1_server1[3]);
_gtv6 = (_modbusMasterDataTable_3_reg_1_server1[4]);
//Плата:2
_gtv1 = (((String(_gtv2, DEC))) + (String(" ")) + ((String(_gtv3, DEC))) + (String(" ")) + ((String(_gtv4, DEC))) + (String(" ")) + ((String(_gtv5, DEC))) + (String(" ")) + ((String(_gtv6, DEC))) + (String(".")));
if (1){if(!(( _gtv1)==(_stou1))){Serial.println(_gtv1);}} _stou1 = _gtv1; //
switch ( _modbusMasterState ) {
case 1:
_nextModbusMasterQuery();// передача
break;
case 2:
pollModbusMaster(); // приём
break;
}
}
bool _isTimer(unsigned long startTime, unsigned long period )
{
unsigned long currentTime = millis();
return (period <=(currentTime - startTime));
}
void _nextModbusMasterQuery()
{
if (!(_isTimer(_modbusMasterSendTime, 2000))) return; // новое
//abc = !abc;
_modbusTelegramm.ip = SlaveInMasterTCPServer_1;
_modbusTelegramm.port = 11502;
_modbusTelegramm.slaveId = 1;
_modbusTelegramm.function = 4;
_modbusTelegramm.startAddres = 0; // с какого адреса
_modbusTelegramm.numbeRegs = 5; // сколько штук читать
_modbusTelegramm.serverId = 1;
//_modbusTelegramm.answerId = _modbusTelegramm.answerId + 1;
_modbusMasterSendQuery();
}
void _modbusMasterSendQuery()
{
if ( ! _ModbsTCPMasterClient.connected()) {abc = !abc;_esp8266WifiModuleClientReconnect();/*_ModbsTCPMasterClient.connect(_modbusTelegramm.ip,_modbusTelegramm.port);Serial.print("");Serial.print("Reconect"); */}
else{
_modbusMasterBufferSize = 6;
_modbusMasterBuffer[0]=highByte(_modbusTelegramm.answerId);
_modbusMasterBuffer[1]=lowByte(_modbusTelegramm.answerId);
_modbusMasterBuffer[2]=0;
_modbusMasterBuffer[3]=0;
_modbusMasterBuffer[4]=highByte(_modbusMasterBufferSize);
_modbusMasterBuffer[5]=lowByte(_modbusMasterBufferSize);
_modbusMasterBuffer[6] = _modbusTelegramm.slaveId;
_modbusMasterBuffer[7] = _modbusTelegramm.function;
_modbusMasterBuffer[8] = highByte(_modbusTelegramm.startAddres);
_modbusMasterBuffer[9] = lowByte( _modbusTelegramm.startAddres );
_modbusMasterBuffer[10] = highByte(_modbusTelegramm.numbeRegs );
_modbusMasterBuffer[11] = lowByte( _modbusTelegramm.numbeRegs );
_ModbsTCPMasterClient.write(_modbusMasterBuffer, 12);
//_modbusTelegramm.answerId = _modbusTelegramm.answerId + 1; // новое
_modbusMasterSendTime = millis();
_modbusMasterState = 2;}
}
void pollModbusMaster()
{
if (_isTimer(_modbusMasterSendTime, 900)) { _modbusMasterState = 1; return;}
_modbusMasterGetRxBuffer();
if(_modbusMasterBufferSize == 0) {return;}
Serial.println("Send= " + String(_modbusMasterBufferSize, DEC));
byte exeption = validateAnswer();
_modbusMasterSendTime = millis();
if (exeption != 0) {
_modbusMasterState = 1;_ModbsTCPMasterClient.stop(); return; }
switch ( _modbusMasterBuffer[1] ) {
case 4:
get_FC3(3);
break;
}
_modbusMasterState = 1;
_modbusTelegramm.answerId = _modbusTelegramm.answerId + 1;
return;
}
byte _modbusMasterGetRxBuffer()
{
int qwe;
_modbusMasterBufferSize = 0;
byte currentByte = 0;
byte currentByteIndex = 0;
while (_ModbsTCPMasterClient.available() ) {currentByte = _ModbsTCPMasterClient.read();
if (currentByteIndex ==0)qwe = currentByte;
if (currentByteIndex ==1)qwe = (qwe<<8) | currentByte;
if (currentByteIndex ==3)Serial.println("ID= "+String(qwe, HEX));
if (currentByteIndex > 5) {
_modbusMasterBuffer[ _modbusMasterBufferSize ] = currentByte; _modbusMasterBufferSize ++;
}
currentByteIndex++;
}
return _modbusMasterBufferSize;
}
byte validateAnswer()
{
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.startAddres;
byte currentByte = 3;
int value;
byte mmm = _modbusMasterBuffer[2] / 2; // получено байт, делим на 2 - получено регистров.
for (int i = 0; i < mmm; i++) {
value = word( _modbusMasterBuffer[ currentByte], _modbusMasterBuffer[ currentByte + 1 ]);
if(table == 3) {_modbusMasterDataTable_3_reg_1_server1[currentIndex + i] =value;}
currentByte += 2;
}
}
void _esp8266WifiModuleClientReconnect()
{
WiFi.begin(ESPControllerWifiClient_SSID, ESPControllerWifiClient_password);
while (WiFi.status() != WL_CONNECTED) {
//Serial.print(".");
delay(500);
}
//Serial.println();
_ModbsTCPMasterClient.connect(_modbusTelegramm.ip,_modbusTelegramm.port);
_modbusMasterSendTime = millis();
}
Я так понимаю такое же может происходит при использовании шлюза в каскаде, сталкивался с таким...Sancho писал(а): ↑18.09.2020{, 17:10}Тест переделанного опроса, пакетного, на новой плате с модулем ESP-12E показал свою полную работоспособность.
Указанные в ссылке поста 7 платы годятся разве-что как отдельный контролер с много памяти, а лучше мимо них.
Смещение данных возможно при по-регисторном считывании( даже адресов подряд) и отсутствии проверки номера полученного пакета, что пока присутствует в проге, функция validateAnswer(), и отсутствия какой либо обработки/анализа заголовка, первых 6-ти байт.
При корректировке функций всё будет Ок. Проверенно считывание пяти регистров подряд пакетом за час 1 раз/сек - потерь нет. Слэйв - инсатовский орс на 32т.
Отправлено спустя 13 минут 4 секунды:
Скрин орсСпойлерПоказать2020-09-18_17-09-07.png
В каскаде, при использовании облака, номер пакета в заголовке вообще не инкриминируется. Поэтому в то, что Вы получили ответ на тот пакет запроса, на который ждёте, уверенности 100% нет совсем.
На сколько я понял вопрос про функции модбас и работе в локальной сети ,а не то как сделана работа через облако ..Тут только программист каскады может пояснить.Sancho писал(а): ↑19.09.2020{, 08:33}В каскаде, при использовании облака, номер пакета в заголовке вообще не инкриминируется. Поэтому в то, что Вы получили ответ на тот пакет запроса, на который ждёте, уверенности 100% нет совсем.
Для максимальной уверенности при опросе:
номер принятого пакета соответствует номеру отправленного;
Количество байт в заголовке, 6-й байт( редко 5 и 6), равен количеству байт после него( сейчас _modbusMasterBufferSize, не сложно, для макс уверенности);
проверка на отсутствии в ответе данных об ошибке или её интерпретации.
Как я думаю, облако у Вас - это просто надстройка над той реализацией ТСР, которая была изначально. Соответственно, номер пакета не увеличивается и не проверяется.