angeloc/simplemodbusng

updating register in slave with external master

Closed this issue · 8 comments

Hi,

I have been trying to set up a Modbus RTU communication between a C# program (with another Modbus library) as a master and an arduino as as slave. I do so through a USB to RS485 cable. The arduino is connected to a MAX485 IC.

The goal of the project is for the slave to receive a few registers from the master, do some calculations with it and make the outcome available in another register for the master to read again.

The master can flawlessly read data from registers on the slave, I'm however not really grasping how my slave can receive and store bytes from the master.

#include <SimpleModbusSlave.h>

const int serialNumber = 7999;
const int securityCode = 999;

const int HOLDING_REGS_SIZE= 10 ;
unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

void setup()
{
  modbus_configure(&Serial, 115200, SERIAL_8N1, 3, 2, HOLDING_REGS_SIZE, holdingRegs);
  holdingRegs[0] = serialNumber; 
  holdingRegs[2] = securityCode; 
  holdingRegs[4] = 0; //I'd like this to become a value sent by the master
}

void loop()
{
modbus_update();

}

As I said, I have no issue reading serialNumber and securityCode when I request this data using function code 3 with this code.

Let's say now I want to send an integer from the master to the slave, let's say decimal 32000 (0x7D 0x00). I'd like this number to be available in holdingRegs[4] and holdingRegs[5]. My masters' library is limited to function code 16 and will always write a minimum of 32 bits (4 bytes).

This is what my masters' library outputs:
0x03: (slave ID)

0x10: (function code 16 - write multiple registers)
0x00:

0x04: (2 bytes to specify I want to start writing at register 4)
0x00:

0x02: (2 bytes to specify there will be data for 2 registers (or more specifically 1 32-bit register)

0x04: 4 bytes to come

0x00:
0x00: first register (16 bits) is 0

0x7D:
0x00: value 32000

0xD8
0xB4: CRC

Hopefully, My understanding is not too wrong yet with this logic.

Here is where it probably goes wrong: I was under the impression that modbus_update(); would update holdingRegs[4] and holdingRegs[5] as soon as the function 16 from the master was received. However, when I read those registers later, they still have the original value 0.

I think I'm missing something very obvious. Any help would be greatly appreciated!
Thanks,
Jens

@jensvanhoof86 have you tried with this?

modbus_update(holdingRegs);

@jensvanhoof86 have you tried with this?

modbus_update(holdingRegs);

I just did, but it doesn't seem to accept any arguments.
I also just started to run some tests with QModbus rather than my own C# project, and it does seem to work without any issue for function code 6! For function code 16 it doesn't work in Qmodbus either. I will check if I have the latest library.

Actually even your modbus_configure() doesn't look right. Check the header: https://github.com/angeloc/simplemodbusng/blob/master/SimpleModbusSlave/SimpleModbusSlave.h#L85

EDIT your code looks like you're using the original SimpleModbus library.

Actually even your modbus_configure() doesn't look right. Check the header: https://github.com/angeloc/simplemodbusng/blob/master/SimpleModbusSlave/SimpleModbusSlave.h#L85

EDIT your code looks like you're using the original SimpleModbus library.

Ah yes, exactly. It is a bit confusing. I'm trying now with the other library, but it's exactly the same behaviour. Writing and reading single registers (function 3 and function 6) is fine, but I don't even get a reply from the slave when I'm trying to send a function 16 message..

edit: I changed the slaveID to 3 to match the original example

Yes, skazi1 pointed out that I did not have the correct library, sorry about that.
Anyway, the behaviour remains the same unfortunately:

using QModbus I can perfectly read one or multiple registers from the Arduino (function 3), as well as update single registers using function 6. However, when I try to write multiple registers at once using function 16, the arduino doesn't even reply. This is the updated code:

#include <SimpleModbusSlave.h>

const int serialNumber = 31000;
const int securityCode = 999;

const int HOLDING_REGS_SIZE= 10 ;
unsigned int holdingRegs[HOLDING_REGS_SIZE]; // function 3 and 16 register array

void setup()
{
  //modbus_configure(&Serial, 115200, SERIAL_8N1, 3, 2, HOLDING_REGS_SIZE, holdingRegs);
  modbus_configure(115200, 3, 2, HOLDING_REGS_SIZE, 0);
  
  holdingRegs[0] = serialNumber; 
  holdingRegs[2] = securityCode; 
  holdingRegs[4] = 0;
}

void loop()
{
modbus_update(holdingRegs);
}

Besides the SlaveID change (3 -> 1) I don't see anything wrong with this code.

Have you resolved?

the problem here in my opinion is that you cannot say if it writes or not because holdingregs is not used in the loop function.