Modbus problem between sensor and Arduino

Hello everyone. I would really appreciate your help with this problem i am facing. I'm newbie in Arduino.

I am trying to read sensor parameter via RS485 using modbus RTU but unable to do. I have seen tutorial & read in many forum but didn't success.

Modbus mapping for the sensor: https://www.emerson.com/documents/automation/modbus-mapping-assignments-for-transmitters-en-65522.pdf

I am using MAX485 - TTL UART to RS485 Converter Module: https://core-electronics.com.au/ttl-uart-to-rs485-converter-module.html

I have been checking parameter of the sensor using manufactures software. Here is the the parameter:

  • Baudrate: 38400
  • ID Slave: 4
  • Parity: None
  • Stop bits: 1

Then I want to monitor sensor temperature. The address of holding register is: 0251. When I check from serial monitor, modbus communication is failed and the address is change to 169. I think, I can not write the register with prefix "0".

Here is my code:

#include <ModbusMaster.h>
#define baudrate 38400
#define timeout 100
#define polling 100
#define retry_count 10
ModbusMaster node;

#define MAX485_DE      2
#define MAX485_RE_NEG  3

#define ID_meter  4
#define Total_of_Reg  1

#define Reg_E       0251 // Sensor temperature register
uint16_t Reg_addr[1] = {
  Reg_E
  };

float DATA_METER [Total_of_Reg] ;

void preTransmission()
{
  digitalWrite(MAX485_RE_NEG, 1);
  digitalWrite(MAX485_DE, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}

//------------------------------------------------
// Convent 32bit to float
//------------------------------------------------
float HexTofloat(uint32_t x) 
{
  return (*(float*)&x);
}

uint32_t FloatTohex(float x) 
{
  return (*(uint32_t*)&x);
}
//------------------------------------------------

float Read_Meter_float(char addr , uint16_t  REG) 
{
  float i = 0;
  uint8_t result,j;

  uint16_t data[5];
  uint32_t value = 0;
  node.begin(ID_meter,Serial);
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
  
  result = node.readHoldingRegisters(REG,4); ///< Modbus function 0x03 Read Holding Registers
  delay(500);
  if (result == node.ku8MBSuccess) 
  {
    for (j = 0; j < 5; j++)
    {
      data[j] = (node.getResponseBuffer(j));
    }
    value = data[1];
    value = value << 16;
    value = value + data[1];
    i = HexTofloat(value);
    Serial.println("Connect modbus Ok.");
    return i;
  } else 
  {
    Serial.print("Connect modbus fail. REG >>> "); Serial.println(REG); // Debug
    delay(1000); 
    return 0;
  }
}

void GET_METER() 
{     // Update read all data
  delay(1000);                            
    for (char i = 0; i < Total_of_Reg ; i++)
    {
      DATA_METER [i] = Read_Meter_float(ID_meter, Reg_addr[i]);
    } 
}

void setup() 
{
  Serial.begin(baudrate, SERIAL_8N1);

  Serial.println(F("Test"));
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}

void loop() 
{
  //float x = Read_Meter_float(ID_meter,Reg_Volt);
  GET_METER();
  Serial.println();
  Serial.print("Data = "); Serial.println(DATA_METER[0]);

}

Please help me out and thanks in advance.

And please let me know if any other information I need to provide. Thank you

When you prefix a number with "0", it will be interpreted as octal. Octal value 0251 = decimal value 169. Just remove the preceding 0 from this line:

#define Reg_E       0251 // Sensor temperature register

Thank you for your response. I have removed 0 from that line. But it still failed. Please let me know what is the mistake I am doing. Thank you.

Here is my updated code:

#include <ModbusMaster.h>
#define baudrate 38400
#define timeout 100
#define polling 100
#define retry_count 10
ModbusMaster node;

#define MAX485_DE      2
#define MAX485_RE_NEG  3

#define ID_meter  4
#define Total_of_Reg  1

#define Reg_E       251 // Sensor temperature register
uint16_t Reg_addr[1] = {
  Reg_E
  };

float DATA_METER [Total_of_Reg] ;

void preTransmission()
{
  digitalWrite(MAX485_RE_NEG, 1);
  digitalWrite(MAX485_DE, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}

//------------------------------------------------
// Convent 32bit to float
//------------------------------------------------
float HexTofloat(uint32_t x) 
{
  return (*(float*)&x);
}

uint32_t FloatTohex(float x) 
{
  return (*(uint32_t*)&x);
}
//------------------------------------------------

float Read_Meter_float(char addr , uint16_t  REG) 
{
  float i = 0;
  uint8_t result,j;

  uint16_t data[5];
  uint32_t value = 0;
  node.begin(ID_meter,Serial);
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
  
  result = node.readHoldingRegisters(REG,4); ///< Modbus function 0x03 Read Holding Registers
  delay(500);
  if (result == node.ku8MBSuccess) 
  {
    for (j = 0; j < 5; j++)
    {
      data[j] = (node.getResponseBuffer(j));
    }
    value = data[1];
    value = value << 16;
    value = value + data[1];
    i = HexTofloat(value);
    Serial.println("Connect modbus Ok.");
    return i;
  } else 
  {
    Serial.print("Connect modbus fail. REG >>> "); Serial.println(REG); // Debug
    delay(1000); 
    return 0;
  }
}

void GET_METER() 
{     // Update read all data
  delay(1000);                            
    for (char i = 0; i < Total_of_Reg ; i++)
    {
      DATA_METER [i] = Read_Meter_float(ID_meter, Reg_addr[i]);
    } 
}

void setup() 
{
  Serial.begin(baudrate, SERIAL_8N1);

  Serial.println(F("Test"));
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);
}

void loop() 
{
  //float x = Read_Meter_float(ID_meter,Reg_Volt);
  GET_METER();
  Serial.println();
  Serial.print("Data = "); Serial.println(DATA_METER[0]);

}

Dunno the modbus library, but the line node.begin(ID_meter,Serial); should be in void setup() and it does not look right that you have:

node.preTransmission(preTransmission);
//Perform transmission here?
node.postTransmission(postTransmission);

Right after each other, transmission should probably be tucked in between of those instructions where I put a comment.

Okay thank you for your help. It's solved. I didn't connect GND sensor with Arduino, so I couldn't communicate between sensor and Arduino using modbus RS485

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