ModbusMaster Read/Write Register Errors with RS485 Click 3.3V and RS485 to USB Cable

I am having issues communicating via Modbus with the hardware listed below. There is an example using the same Click 3v3 board but only reading sensor data. I need to read and write data. I have some simple code written that initialized Modbus, write to a single register (function code 0x06) and then read from that same register, but in my serial console I repeatedly get errors from ModbusMaster library: E2 and E0. (response timed out exception / invalid response slave ID exception). Pictures and code below as well of qModbusMaster configuration + payload frames. The photon is being powered by USB as well.

Let me know if I am missing any information that would be helpful or something that I am missing.

Hardware Used:

Photon connected to Click 3v3 via Serial1 RX/TX (RX to TX, TX to RX), R/T connected to D5, 3v3 to 3v3, GND to GND.

Click 3v3 connected to TTL to USB cable: B to -, A to +, GND to GND.

USB connected to laptop running qModbusMaster.

Code:

#include <ModbusMaster.h>

const int RT = D5; // constant for R/T pin set to D5, PWM1 on MikroBUS1

// Instantiate ModbusMaster object with slave ID 1, Serial1
ModbusMaster node(1, 1);

void setup() {
  // Initialize Modbus communication baud rate and format
  node.begin(9600);	  // set baud rate for modbus
	node.enableTXpin(RT); // TX enable pin of RS485 driver

  // Print initialization message
  Serial.begin(9600);
  Serial.println("Modbus communication setup complete");
}

uint8_t result;
uint16_t value = 0x0001; 

void loop()
{
  result = node.writeSingleRegister(5, value);
  Serial.print("writeSingleRegister => ErrorCode: ");
  Serial.println(result);

  delay(1000);

  result = node.readHoldingRegisters(5, 1);
  Serial.print("readHoldingRegisters => ErrorCode: ");
  Serial.println(result);
}

Bus monitor:

Sys > 14:12:55:293 - Connecting to Serial Port [\\.\COM16]...OK
[RTU]>Tx > 14:13:01:306 - 01  06  00  05  FF  FF  98  7B  
[RTU]>Rx > 14:13:01:323 - 01  03  00  05  00  
Sys > 14:13:01:323 - Error : Invalid CRC
[RTU]>Tx > 14:13:02:307 - 01  06  00  05  FF  FF  98  7B  
[RTU]>Rx > 14:13:02:307 - 01  06  00  05  00  01  58  0B  
Sys > 14:13:02:307 - values written correctly.

Although it says that the values are written correctly, it does not show the value in the register. The response frame from the bus monitor also shows FF FF which isn't the data. Any help would be appreciated.

Hi @mprzez what is your jumper configuration on the Click 3.3V? Do you have the termination resistor enabled (J4)?

I'm also reading the documentation for the Click 3.3V and this line:

Therefore, RS485 Click 3.3V offers UART RX and TX pins routed to the appropriate mikroBUS™ TX and RX UART pins.

kind of makes me think that the TX/RX pins might be already swapped for you. Could you try reversing the TX/RX configuration you have currently and report back?

Hi @ericpietrowicz Thanks for responding.

All three of the yellow jumpers are enabled and on J2, J3, and J4. I have not removed any of them, the board is in its default configuration.

Reversing the RX and TX wires from the Photon to the Click 3v3 caused timeout errors. And in the serial monitor continued E2 errors.

Bus monitor:

[RTU]>Tx > 16:10:40:259 - 01  06  00  05  FF  FF  98  7B  
Sys > 16:10:40:775 - Error : Timeout
[RTU]>Tx > 16:10:41:258 - 01  06  00  05  FF  FF  98  7B  
Sys > 16:10:41:775 - Error : Timeout
[RTU]>Tx > 16:10:42:275 - 01  06  00  05  FF  FF  98  7B  
Sys > 16:10:42:777 - Error : Timeout
[RTU]>Tx > 16:10:42:979 - 01  03  00  05  00  01  94  0B  
Sys > 16:10:43:491 - Error : Timeout

I have also been looking at this forum post with similar issues, but it has yet to be helpful to me.
Modbus Master library issue - Firmware / Libraries - Particle

Hi @mprzez can you try replacing these lines (756-758) in ModbusMaster.cpp:

if (MBSerial.available()) { //Empty the receive buffer before beginning.
	MBSerial.read();
}

with:

while(MBSerial.read() > -1);

and let me know if that has any impact?

@ericpietrowicz Nothing seemed to change after replacing the code. Same errors/packets.

I have also attached an image of my setup with the wiring of the hardware.
(sorry for using the same wire colors for everything, it was convenient for me)

I am unsure if this is a hardware or software issue. I am leaning towards software since the ModbusMaster library is the only library available for particle boards and it is outdated by a few versions from the most recent.

We've run out of things to check, and it is not clear why it's not working for you.

I ran a Photon 2 with this firmware.

#include "Particle.h"

#include <ModbusMaster.h>

SYSTEM_THREAD(ENABLED);
SerialLogHandler logHandler;

const int RT = D5; // constant for R/T pin set to D5, PWM1 on MikroBUS1

// Instantiate ModbusMaster object with slave ID 1, Serial1
ModbusMaster node(1, 1);

void setup()
{
    waitFor(Serial.isConnected, 10000);

    // Initialize Modbus communication baud rate and format
    node.begin(9600);     // set baud rate for modbus
    node.enableTXpin(RT); // TX enable pin of RS485 driver
    node.enableDebug();
}


void loop()
{
    uint8_t result;
    uint16_t registerValue = 0x0001;

    result = node.writeSingleRegister(5, registerValue);
    Log.info("writeSingleRegister result=%d", (int) result);

    delay(1000);

    // result = node.readHoldingRegisters(5, 1);
    // Log.info("readHoldingRegisters result=%d", (int) result);

    delay(5000);
}

I got this output from USB serial debug:

0001091539 [app] INFO: writeSingleRegister result=226
TX: 1 6 0 5 0 1 58 B  
RX:  

I connected a logic analyzer set to 9600 8N1 on the TX pin and got this data:

0x010600050001580b

This matched the USB serial debug log. To make sure the CRC (the last two byte) is correct, I used this online calculator.

The value of 0x0b58 is correct (taking into account byte order).

To be sure the data would update correctly, I also set the data to 0x5a0f and got the correct output in the debug log and the logic analyzer. The CRC calculator also returned a match.

0000014715 [app] INFO: writeSingleRegister result=226
TX: 1 6 0 5 5A F E3 6F  
RX: 
1 Like

Thanks @rickkas7.

Although the payload does seem to be sending, isn't the result an error?

0001091539 [app] INFO: writeSingleRegister result=226

The result number in hex, E2, indicates a timeout error. If successful, the documentation says it would return 0.

Maybe there is a misunderstanding, or I am not understanding how Modbus works, I need bidirectional communication, to be able to write to registers and then also read those values. My tests have been made using qModMaster software, and I just don't see anything being stored in any registers although I see the same payload received that you also are getting.

Are you able to read values as well?

That error is because I didn't have a modbus device, or even a bus. I just connected the logic analyzer to the TX pin (at 3.3V level), so the timeout is expected in my test.

Okay so if I am seeing this in the debug log, then everything on the particle/software is working (I changed what data I am sending in this example).

TX: 1 3 0 5 0 1 94 B  
RX:  
0000174080 [app] INFO: readHoldingRegisters result=226
TX: 1 6 0 5 AF 1 25 FB  
RX:  
0000179306 [app] INFO: writeSingleRegister result=226

I am also occasionally getting this, could there be a timing issue?

TX: 1 3 0 5 0 1 94 B  
RX: 1 3 0 5 0  
0000861398 [app] INFO: readHoldingRegisters result=227

Would this mean that it is a hardware or wiring issue then?
Or could it potentially be Modbus test software issue?

I am trying to pinpoint what I should try to debug further; I have already tried various softwares to interface with the USB on my laptop and I have tried different wiring configurations (as well as trying a different board: https://www.amazon.com/DSD-TECH-SH-U12-MAX13487-Raspberry/dp/B07B667STP)

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