Hi all, I am having an issue with the ModbusMaster.h library trying to read some Register values from a modbus slave. I am using the example included in the Web IDE environment as follows:
#include "ModbusMaster.h"
//instantiate ModbusMaster object as slave ID 1
ModbusMaster node(2);
void setup() {
// initialize Modbus communication baud rate
node.begin(9600);
node.enableTXpin(D7); //D7 is the pin used to control the TX enable pin of RS485 driver
//node.enableDebug(); //Print TX and RX frames out on Serial. Beware, enabling this messes up the timings for RS485 Transactions, causing them to fail.
Serial.begin(9600);
while(!Serial.available()) Particle.process();
Serial.println("Starting Modbus Transaction:");
}
void loop() {
static uint32_t i;
uint8_t j, result;
uint16_t data[10];
i++;
// result = node.readHoldingRegisters(0x2f,2);
result = node.readHoldingRegisters(9,1);
// do something with data if read is successful
if (result == node.ku8MBSuccess) {
Serial.print("Success, Received data: ");
for (j = 0; j < 2; j++) {
data[j] = node.getResponseBuffer(j);
Serial.print(data[j], HEX);
Serial.print(" ");
}
Serial.println("");
} else {
Serial.print("Failed, Response Code: ");
Serial.print(result);
Serial.print(" - ");
Serial.print(result, HEX);
Serial.println("");
delay(5000); //if failed, wait for bit longer, before retrying!
}
delay(1000);
}
Looking at the Terminal I get from time to time a proper response. I think it might be a timing issue (see attached)
Thanks, I later realized that… but Now I am getting an 0xE2 error code. which points to timeout. But every once in a while I do get a proper response. Do you know if there is provision in the library to introduce a delay between the request/transmission?
you mean time between transmission of data and response from slave ? if yes, yes
namely idle()
Do you have end terminators (120 ohm) on both side of your RS485 network ?
avoid long delays instead use millis()
looks like pinMode is defined just as output (from ModbusMaster.cpp)
/**
Enable and set the GPIO pin that is required by some RS485 Drivers to switch from receiving to transmitting mode
@ingroup setup
*/
void ModbusMaster::enableTXpin(uint8_t pin) {
pinMode(pin, OUTPUT);
MBTXEnablePin = pin;
MBUseEnablePin = 1;
}
IMHO should be pulled down as can be floating and maybe switching between RX/TX not function correctly could you pull down D7 by external resistor e.g 4K7
and finally try this code:
// This #include statement was automatically added by the Particle IDE.
#include <ModbusMaster.h>
#include "Particle.h"
SYSTEM_THREAD(ENABLED);
//instantiate ModbusMaster object as slave ID 1
ModbusMaster node(1);
unsigned long interval = 0;
unsigned long base_T = 1000;
void idle() {
delay(10); // in case slave only replies after 10ms
Particle.process(); // avoids letting the connection close if open
}
void setup() {
// initialize Modbus communication baud rate
node.begin(9600);
node.enableTXpin(D7); //D7 is the pin used to control the TX enable pin of RS485 driver
//node.enableDebug(); //Print TX and RX frames out on Serial. Beware, enabling this messes up the timings for RS485 Transactions, causing them to fail.
node.idle(idle); //function gets called in the idle time between transmission of data and response from slave
Serial.begin(9600);
while(!Serial.available()) Particle.process();
Serial.println("Starting Modbus Transaction:");
}
void loop() {
uint8_t j, result;
uint16_t data[10];
if (millis() - interval > base_T) {
interval = millis();
result = node.readHoldingRegisters(9,1);
// do something with data if read is successful
if (result == node.ku8MBSuccess) {
Serial.print("Success, Received data: ");
for (j = 0; j < 2; j++) {
data[j] = node.getResponseBuffer(j);
Serial.print(data[j], HEX);
Serial.print(" ");
}
Serial.println("");
base_T = 1000;
} else {
Serial.print("Failed, Response Code: ");
Serial.print(result);
Serial.print(" - ");
Serial.print(result, HEX);
Serial.println("");
base_T = 5000; //if failed, wait for bit longer, before retrying!
}
}
}
I seem to have now an intermittent problem. Every couple of hours the BORON seems to lose the ability to read the Modbus Slave… looks like out of sync and it doesn’t recover the only way to get it to work again is to reset the unit.
Here is a screenshot of the Serial port.
Any ideas? I have added node.clearResponseBuffer(); and node.clearTransmitBuffer(); node.clearResponseBuffer(); when the unit fails to read… but it doesn’t do anything, it doesn’t recover.