-
Notifications
You must be signed in to change notification settings - Fork 190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ESP32: Reading float type from Modbus #155
Comments
Hello, Probably that's because of sensor documentation uses 1-based offset for registers numbering as library uses 0-based one. |
Hello. Value32_BIN:11100000100011000100000110011100 Values have 31 bits instead of 32 when I apply swap words order Do you know why this can happen? |
You need also swap bytes in words: union sw {
float f;
uint32_t u32;
struct {
uint16_t u161;
uint16_t u162;
};
};
v32.u32 = 0b11010100110100010100000110011101; // Original
v32.u32=(v32.u32>>16) | (v32.u32<<16);
v32.u161 = (v32.u161>>8) | (v32.u161<<8);
v32.u162 = (v32.u162>>8) | (v32.u162<<8);
Serial.println(v32.f);// swap (8<=>8)<=>(8<=8>) ===> 19.73 |
@emelianov I have checked your proposed code and it is not working properly, in fact, I have tried the following code to see if the swap is doing it correctly for me, the tested code is this: `union sw{
` 2638336468 I hope see in the float values 19.73 ¿Is correct? |
Ops... Probably i've lost in swaps. Choose appropriate one: union sw {
float f;
uint32_t u32;
struct {
uint16_t u161;
uint16_t u162;
};
};
sw v32;
v32.u32 = 0b11010100110100010100000110011101;
Serial.println(v32.f); //orig
v32.u32=(v32.u32>>16) | (v32.u32<<16);
Serial.println(v32.f); // swap 16<=>16
v32.u161 = (v32.u161>>8) | (v32.u161<<8);
v32.u162 = (v32.u162>>8) | (v32.u162<<8);
Serial.println(v32.f);// swap (8<=>8)<=>(8<=8>)
v32.u32 = 0b11010100110100010100000110011101;
v32.u161 = (v32.u161>>8) | (v32.u161<<8);
v32.u162 = (v32.u162>>8) | (v32.u162<<8);
Serial.println(v32.f);// swap (8<=>8)(8<=8>)
} |
I have seen the following, it seems that the problem in those variables had it in the consecutive reading of registers. I mean, in the read loop I was reading several registers without any time control, in these float registers, I think some data was lost in the communication.
Is my reasoning possible? If so, is it solved in the best way? |
It should be more complex code. As a minimum for each read uint16_t tr = mb.readHreg(remote,4,&V2,nullptr,1);
while (mb.isTransaction(tr))
mb.task();
// At this point request is finished and value in V2 is set. If got response from server for sure. |
@emelianov thank you for your support. |
Hi @emelianov, I had a problem using the function. I would like to do a multi-read of a sensor, this means that two or more ESP32s would read data from the same sensor. With what I have programmed, that reading is confusing reading non-logical data or even ovf. You have an example where you can see the code as it is implemented. Now in each ESP32 I have the following programmed:
Thanks in advance. |
|
Hi Emilianov, thank you for your answer and sorry for mi delayed response. Until today I can not read your answer. I have changed my code as I have could see in the examples. I go to test if with this code, 4 differentes ESP32 can read to the same sensor. Another problem which I have found with this code, is with the expresion "mb.isConnected(remote)", I hoped when I swicht off the sensor, this expression send me a "0" if this failure occur 2 times, I must send the ERROR by I2C to another system, but this expression sent to me always "1". Do I checking correctly that the connection is running? If not, How I can check it correctly? Thanks in advance. ` |
In case if Modbus server becomes offline and stops responding connection becomes reported as alive on client side for a TCP timeout time. Moreover if no request to be sent over this connection timeout may starts counting only on first request attempt. That's how TCP is designed. |
Hi Emelianov, I am reviwing the code according to the main issues found on it. Attached you can found the changed code. Is correct in this code the use of the mb.connect()? if not, could you clarify to me the example model in the library? I am trying use a callback for determine if the sensor is connected to the network or not. For it, I using a callback function and use the TIMEOUT event to determine that a problem exits with the sensor. The code:
Thanks in advance |
Take a look comments below. Probably they will help with E4 errors. void setup() {
Serial.begin(9600);
Wire.begin(I2C_SDA, I2C_SCL);
wifiManager.autoConnect();
mb.client(); // Need to init Modbus as a client anyway
if(WiFi.status()!=WL_CONNECTED){
ERROR=101;
} else{
mb.connect(remote,502);
}
}
void loop() {
if (WiFi.status()== WL_CONNECTED){
if(mb.isConnected(remote)){
fcn_ModBusRead();
ContFallosMD = 1;
ERROR = 0;
} else {
mb.connect(remote, 502); // Need to try to restore connection if not connected
if (ContFallosMD<=ContFallosMDLimite){
ContFallosMD++;
} else {
ERROR = 202;
Serial.println("Send ERROR by I2C");
}
}
} else{
ERROR = 102;
Serial.println("Send ERROR by I2C");
}
delay(50); // Need to reduce pooling rate as 'remote' device may fail on high rate
} |
I am testing your changes and don't work properly. If the sensor is connected and then run the application the code works properly I can read the values and send ir by I2C, the problem is when the connexion is running and I switch off the sensor, I would hope that the expresion mb.isConnected(remote) would be false and would start to count and increasing the variable ContFallosMD, but the real situation is that expresion mb.isConnected(remote) is true although the sensor is desconnected. |
With the code above is expected that |
I don't understand the situation, If each cycle time I check the connection and if the .isConnected is false, a new transaction is required by mean the fcn_ModbusRead() and if the sensor is desconnected, the this new transaction get timeout error. |
Have no time to test with hardware but this minimalistic code commented with haw it should work. bool cb(Modbus::ResultCode event, uint16_t transactionId, void* data) { // Modbus Transaction callback
if (event != Modbus::EX_SUCCESS) // If transaction got an error
Serial.printf("Modbus result: %02X\n", event); // Display Modbus error code
if (event == Modbus::EX_TIMEOUT) { // If Transaction timeout took place
mb.disconnect(remote); // Close connection to slave and
mb.dropTransactions(); // Cancel all waiting transactions
}
return true;
}
uint16_t res = 0;
void loop() {
if (!mb.isConnected(remote)) { // Check if connection to Modbus Slave is established
mb.connect(remote); // Try to connect if no connection. If no success 5 seconds timeout there
Serial.print(".");
}
if (mb.isConnected(remote) { // Check if Modbus library thinks that remote is alive
uint16_t tr = mb.readHreg(remote, REG, &res, 1, cb); // Initiate read request
while (mb.isTransaction(tr) { // While transaction is active wait for response data. If remote is dead 1 second timeout there
mb.task(); // this fiction processes response frame, calls callback with EX_SUCCESS and clears transaction
// or in case of timeout calls callback with EX_TIMEOUT
// in case of timeout function above forces remote disconnect and destroys other transactions if any.
yield();
}
delay(50);
} else {
// Not connected state code is there.
}
} |
Good morning everyone,
I am using the library the Emelianov Modbus library in an ESP32 thing module with the Arduino IDE to read the values of a sensor by Modbus.
The sensor sends 5 records with the following configuration:
Register address: 1 data type 32b floating point (big endian)
Register address: 2 data type 32b floating point (big endian)
Register address: 3 data type 16b unsigned
Register address: 4 data type 16b unsigned
Register address: 5 data type 16b unsigned
Reading unsigned 16b type registers, I haven't any problem but, I have problems with the 32b floating point values, which I cannot see reasonable values.
I am testing the following code that I saw in another forum:
uint32_t value32;
mb.readHreg (remote, 1, (uint16_t *) & value32, 2,0,1); // read two sequental registers to 32-bit variable
value33 = (value32 >> 16) | (value32 << 16);
Serial.print ("Value32:"); Serial.println (value32, BIN);
Serial.print ("Value33:"); Serial.println (value33, BIN);
But I do not get a reasonable temperature value than expected (around to 24.1ºC)
These are the values rescued from the serial port:
Value32: 11011001000001100100000110111111
Value33: 1000001101111111101100100000110
Could someone tell me what may be going on?
Thanks and best regards.
The text was updated successfully, but these errors were encountered: