ArduinoTroubleshooting

DFROBOT_RTU: ReadHoldingRegister for multiple register and conversion

userHead Albertoz 2023-10-11 15:29:13 550 Views2 Replies

I use the DFRobot_RTU library for Modbus Master.

 

I use 

uint8_t readHoldingRegister(uint8_t id, uint16_t reg, uint16_t *data, uint16_t regNum)

to read two holding registers (regNum = 2).

 

Can you give a code sample how uint16_t *data has to be defined and how the result is converted to a float value?

The Modbus data is big endian.

 

Thank you

 

2023-10-11 17:57:39

You could define an array in your code, and then pass the name of the array(which is the pointer) to the readHoldingRegister() function. Like the following:

 

uint16_t array[8];

int result = readHoldingRegister(0x01, 0x08, array, 2);

 

 

Then the data you need would be stored in the array. I don't know the detail for your Modbus protocol. So I assumed that the data you need was stored in the fourth and fifth byte. And the endian byte is the third byte.

 

So you could use the “<<” to move your third byte to get the data you need.

 

uint16_t data = (array[4]<<8) + array[5];

 

For eample, if your array[4] is 0x08, your array[5] is 0xFA.

The above line will make you get 0x08FA

userHeadPic Yeez_B
Albertoz wrote:

Thank you for pointing me to the right direction.

 

It seems that readHoldingRegister() returns the data value in array[0] and array[1].

 

So ended up with the follwing code giving the correct float value from two subsequent registers:

 

  uint16_t array[2];

  float floatValue;

  unsigned long *p;

  p = (unsigned long*)&floatValue;

 

  // read register a118 and a119 from slaveId 3

  uint8_t result = modbus.readHoldingRegister(0x03, 0xa118, array, 2);

  if(!result)

  {

     *p = (unsigned long)array[0]<<16 | array[1];       //considers big-endian

     Serial.print("Value: "); Serial.println(floatValue);

  }

  else

  {

    Serial.print("Error number: "); Serial.println(result);

  }

 

 

2023-10-16 00:47:06
1 Replies