Modbus Master library issue

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)

I also enable the node.enableDebug() and get this

I know the slave is answering correctly because I see it on the Oscilloscope.

I am using a MAX3485 chip and have connections as follows:

BORON MAX3485
3.3V - VC
TX - DI
RX - RO
D7 - RE & DE

Any ideas? Thanks in advance.

Otto

Hi,
you initialized the slave as:

but after enabling debug looks like the id is different
slave_id

and error E0-224 is about wrong slave address:
E0_error_code

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 :slight_smile:
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!
	}
    }
}

hope that helps :slight_smile:

1 Like

Thanks for your help. Adding a 4.7 K resistor help solved the transmission problem. Appreciate your help.

Otto

2 Likes

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.

could you disable debug in your setup and see if will help ?
from official example:


also could you try your code with SYSTEM_THREAD(ENABLED); ?

Yes I do nave SYSTEM_THREAD(ENABLED).

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.