Hi , 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

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 as follows:

#include<ModbusMaster.h>
#define MAX485_DE 3
#define MAX485_RE_NEG 2
ModbusMaster node;

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

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

void setup() {
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
// Init in receive mode
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);

Serial.begin(9600);  
//slave ID 1  from datasheet
node.begin(1, Serial);  

Serial.println("Starting Modbus Transaction:");  
node.preTransmission(preTransmission);  
node.postTransmission(postTransmission);  

}

void loop() {
static uint32_t i;
uint8_t j, result;
uint16_t data[10];

i++;

result = node.readHoldingRegisters(10,2); // i want to read 7 registers from start address 10 based on datasheet 

Serial.println("");

if (result == node.ku8MBSuccess) {
  Serial.print("Success, Received data: ");
  for (j = 0; j < 2; j++) {
    data[j] = node.getResponseBuffer(j);
    Serial.print(data[0], HEX);
    Serial.print(" ");
  }
  Serial.println("");
} else {
  Serial.print("Failed, Response Code: ");
  Serial.print(result, HEX);
  Serial.println("");
  delay(5000); 
}
delay(1000);

}

When i run the code get error like as follows:
12:37:05.358 -> Starting Modbus Transaction:
12:37:05.358 -> Failed, Response Code: E2
12:37:07.439 -> Failed, Response Code: E2

Please kindly help me, thank you very much

Which Arduino are you using?
Which RS485 module are you using?
How have you wired your setup together?

Hi I am using Arduino Mega , I am using the RS485 TO TTL Convertor , yes I have wired the setup together , Rx-->0,Tx-->1 , DE-->3 , RE-->2 , is my connection correct , am i using the right code ? thank you very much

I have wired A to A and B to B from sensor to DI,DE,RI,RO as per diagram attached


please kindly help me , thank you

By Mega, do you mean a MEGA2560? If so, use a different hardware serial port than the one used for sketch upload and debugging. Maybe Serial1 instead.

If you mean an UNO, then you need to create a software serial port to handle the Modbus comms.

Hi ,yes Mega 2650 , I tried to change the code as follows for serial1 ,

// FOR MEGA2560 with Modbus device #4 on Serial #1 @ 9600 baud.

#include <ModbusMaster.h> //Library for using ModbusMaster

//#define MAX485_REDE_PIN 5
#define MAX485_DE 2
#define MAX485_RE_NEG 3

ModbusMaster node; //object node for class ModbusMaster
unsigned int DATA[2];
unsigned long lastTime;

float f_2uint_float(unsigned int uint1, unsigned int uint2) { // reconstruct the float from 2 unsigned integers

union f_2uint {
float f;
uint16_t i[2];
};

union f_2uint f_number;
f_number.i[0] = uint1;
f_number.i[1] = uint2;

return f_number.f;

}

void preTransmission() //Function for setting stste of Pins DE & RE of RS-485
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
// digitalWrite(MAX485_REDE_PIN, 1);
}
void postTransmission()
{
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// digitalWrite(MAX485_REDE_PIN, 0);
}

void setup()
{
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
// pinMode(MAX485_REDE_PIN, OUTPUT);

digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// digitalWrite(MAX485_REDE_PIN, 0);

Serial.begin(9600); //Baud Rate as 9600
// Serial.println( MAX485_REDE_PIN );

// Serial1.begin(38400); //Baud Rate as 38400
node.begin(1, Serial); //Slave ID as 1 on Serial #1

node.preTransmission(preTransmission); //Callback for configuring RS-485 Transreceiver correctly
node.postTransmission(postTransmission);
}

void loop()
{
DATA[0] = node.getResponseBuffer(0);
DATA[1] = node.getResponseBuffer(1);
uint8_t result = node.readInputRegisters( 10, 2 ); // Read 2x 16-bit words

Serial.print("result = ");
Serial.println( result );
if (result == node.ku8MBSuccess)
{
Serial.print("data : ");
Serial.print(node.getResponseBuffer(0));
Serial.print(" ");
Serial.println(node.getResponseBuffer(1));
Serial.print("Temperature: ");
Serial.print(f_2uint_float(DATA[0],DATA[1]));
Serial.println(" C");
}
Serial.print("\n");

delay(1000);
}

My registers are 16 bit register(all read registers) , starting address is 10 and slave id is hex 1,baud rate 9600,

The output contains characters and 256 as per attached,

Am I correctly defining the address ? uint8_t result = node.readInputRegisters( 10, 2 ); // Read 2x 16-bit words or should it be (30001+10,2)....both dont seem to work

is code correct ?

please kindly help me , thank you very much

If you want the above settings, the start by changing this line:

to this:

Serial1.begin(9600); 

And change this line:

to this:

node.begin(4, Serial1); //Slave ID as 4 on Serial #1

Note that a result of 226 = 0xE2 which according to the modbusmaster library is a response timeout - i.e. your sensor didn't respond. You need a result = 0 which means that the request for data was successful.

If you are using Serial1, then you need to adjust your wiring to use TX1 and RX1. RO goes to RX1 and DI goes to TX1.

Generally you also need a common GND connection from the sensor to the RS485 module and the MEGA2560.

Hi, I have amended the code as follows :

the console appears to be empty like this ,

// FOR MEGA2560 with Modbus device #4 on Serial #1 @ 9600 baud.

#include <ModbusMaster.h> //Library for using ModbusMaster

#define MAX485_DE 2
#define MAX485_RE_NEG 3

ModbusMaster node; //object node for class ModbusMaster
unsigned int DATA[2];
unsigned long lastTime;

float f_2uint_float(unsigned int uint1, unsigned int uint2) { // reconstruct the float from 2 unsigned integers

union f_2uint {
float f;
uint16_t i[2];
};

union f_2uint f_number;
f_number.i[0] = uint1;
f_number.i[1] = uint2;

return f_number.f;

}

void preTransmission() //Function for setting stste of Pins DE & RE of RS-485
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);

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

}

void setup()
{
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);

digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// digitalWrite(MAX485_REDE_PIN, 0);

Serial1.begin(9600); //Baud Rate as 9600

node.begin(4, Serial); //Slave ID as 4 on Serial #1

node.preTransmission(preTransmission); //Callback for configuring RS-485 Transreceiver correctly
node.postTransmission(postTransmission);
}

void loop()
{
DATA[0] = node.getResponseBuffer(0);
DATA[1] = node.getResponseBuffer(1);
uint8_t result = node.readInputRegisters( 10, 1 ); // Read 2x 16-bit words

Serial.print("result = ");
Serial.println( result );
if (result == node.ku8MBSuccess)
{
Serial.print("data : ");
Serial.print(node.getResponseBuffer(0));
Serial.print(" ");
Serial.println(node.getResponseBuffer(1));
Serial.print("Temperature: ");
Serial.print(f_2uint_float(DATA[0],DATA[1]));
Serial.println(" C");
}
Serial.print("\n");

delay(1000);
}

Please kindly help me,

Thank you very much,

You missed out the "1". It should be Serial1 here.

You still need the Serial.begin(9600) line if you want to use Serial.print to see any output in the IDE serial monitor.

Also, please can you use code tags when posting your code - it's the CODE/ icon in the edit box.

// FOR MEGA2560 with Modbus device #4 on Serial #1 @ 9600 baud.

#include <ModbusMaster.h> //Library for using ModbusMaster


#define MAX485_DE 2
#define MAX485_RE_NEG 3

ModbusMaster node; //object node for class ModbusMaster
unsigned int DATA[2];
unsigned long lastTime;

float f_2uint_float(unsigned int uint1, unsigned int uint2) { // reconstruct the float from 2 unsigned integers

union f_2uint {
float f;
uint16_t i[2];
};

union f_2uint f_number;
f_number.i[0] = uint1;
f_number.i[1] = uint2;

return f_number.f;

}

void preTransmission() //Function for setting stste of Pins DE & RE of RS-485
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);

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

}

void setup()
{
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);


digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// digitalWrite(MAX485_REDE_PIN, 0);

Serial.begin(9600);
Serial1.begin(9600); //Baud Rate as 9600


node.begin(4, Serial1); //Slave ID as 4 on Serial #1

node.preTransmission(preTransmission); //Callback for configuring RS-485 Transreceiver correctly
node.postTransmission(postTransmission);
}

void loop()
{
DATA[0] = node.getResponseBuffer(0);
DATA[1] = node.getResponseBuffer(1);
uint8_t result = node.readInputRegisters( 10, 2 ); // Read 2x 16-bit words

Serial.print("result = ");
Serial.println( result );
if (result == node.ku8MBSuccess)
{
Serial.print("data : ");
Serial.print(node.getResponseBuffer(0));
Serial.print(" ");
Serial.println(node.getResponseBuffer(1));
Serial.print("Temperature: ");
Serial.print(f_2uint_float(DATA[0],DATA[1]));
Serial.println(" C");
}
Serial.print("\n");

delay(1000);
}

Hi modified the code and able to see console , thanks a lot , but then result shows

what could be the issue , please kindly help me , thank you very much

Are you sure that your device is at address 04 and the baud rate should be 9600?

What does your user guide say the defaults are?

Hi yes as per datasheet baud rate is 9600 and default slave ID is 1 for the sensor ,

Is there a way to check if device is at Address 04 ?

please kindly help me , thank you very much ,

Why do you believe that your device is configured for address 04? Have you changed it?

Have you tried address 01 with your latest code?

Hi I have tried both it is showing error ,

please kindly help me , one more question is function reads for register having 32 bits, my register is 16 bits , should I be making any changes to the code ?If my starting address is 10 and i have to read 7 register from starting address each 16 bit register ,how to reflect in code ? please kindly help me ,thank you very much

Can you rephrase this as I'm not sure I understand what you are saying.

If you need to read a 32-bit number, then you usually have to read 2 consecutive 16-bit registers and recombine them together in your own code to get the 32-bit value.

Hi I have to read registers from R10 to R16 , from datasheet it mentions each register is 16-bit , is the above program especially the functions node.readInputRegisters(10,2) and if (result == node.ku8MBSuccess) , is it correct or am i missing something ? please kindly help me , thank you very much

That line of code will return 2 16-bit words starting with the contents of register 10.

That bit of code will print out in decimal the 2 16-bit values returned by the sensor. They should equate to the contents of registers 10 & 11.

That is the correct way of determining if the sensor responded with valid data.

I think you can request the contents of all 7 registers in 1 go like this:

result = node.readInputRegisters( 10, 7 );

Table 1 has the title "Input Register" so I would make the assumption that the call to readInputRegisters() is the correct one to get the sensor to send you the data.

If you don't get a response from your sensor, then I would try the readHoldingRegisters() function as well. I would probably concentrate on reading register R15 as temperature is a parameter that you can fairly easily decide for yourself whether the correct value is being returned.

Hi I modified and tried the following code :

`#include<ModbusMaster.h>


/*  DI =  UNO / NANO TX PIN / arduino mega pin 1 TX pin
    RO =  UNO/ NANO RX PIN / arduino mega pin 0 RX Pin
*/
#define MAX485_DE      3
#define MAX485_RE_NEG  2

ModbusMaster node;

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

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

void setup() {
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);
  // Init in receive mode
  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);



  Serial.begin(9600, SERIAL_8N1);
  Serial.begin(9600);
  //slave ID 1
  node.begin(1, Serial);

  Serial.println("Starting Modbus Transaction:");
  // Callbacks allows us to configure the RS 485 transreceiver correctly
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}


uint16_t newData = 0;
float floatData;
double dataOne;



void loop() {                           // loop starts from here.

  static uint32_t i;
  uint8_t j, result;
  uint16_t data[10];



  i++;
 
  result = node.readInputRegisters(10, 7); // read holding registers

  Serial.println(" ");
 


  if (result == node.ku8MBSuccess) {


   

    Serial.print("\nSuccess, Received data 0: ");

    for (j = 0; j < 7; j++) {
      data[j] = node.getResponseBuffer(j);
    }

    unsigned long temp = (unsigned long)data[6] /10.0;
    floatData = *((float*)&temp);

    Serial.print(floatData);

  }


  

  else {
    Serial.print("Failed, Response Code: ");
    Serial.print(result, HEX);
    Serial.println(" ");
    delay(5000); // 5000
  }
}`

but i get output like this :


what could be the issue ? ,is the code correct ? ,please kindly help me , thank you

That code is not correct. You cannot use the same serial port for both debug printing and Modbus comms.

As I said previously, you need to use a different hardware serial port on your MEGA2560 for the Modbus comms. You did have code that used Serial1.

Hi , I modified and tried the following code :

// FOR MEGA2560 with Modbus device #4 on Serial #1 @ 9600 baud.

#include <ModbusMaster.h> //Library for using ModbusMaster


#define MAX485_DE 2
#define MAX485_RE_NEG 3

ModbusMaster node; //object node for class ModbusMaster
unsigned int DATA[7];
unsigned long lastTime;
/*
float f_2uint_float(unsigned int uint1, unsigned int uint2) { // reconstruct the float from 2 unsigned integers

union f_2uint {
float f;
uint16_t i[2];
};

union f_2uint f_number;
f_number.i[0] = uint1;
f_number.i[1] = uint2;

return f_number.f;

}
*/
void preTransmission() //Function for setting stste of Pins DE & RE of RS-485
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);

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

}

void setup()
{
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);


digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// digitalWrite(MAX485_REDE_PIN, 0);

Serial.begin(9600);
Serial1.begin(9600); //Baud Rate as 9600


node.begin(4, Serial1); //Slave ID as 4 on Serial #1

node.preTransmission(preTransmission); //Callback for configuring RS-485 Transreceiver correctly
node.postTransmission(postTransmission);
}

void loop()
{
DATA[0] = node.getResponseBuffer(0);
DATA[1] = node.getResponseBuffer(1);
DATA[2] = node.getResponseBuffer(2);
DATA[3] = node.getResponseBuffer(3);
DATA[4] = node.getResponseBuffer(4);
DATA[5] = node.getResponseBuffer(5);
DATA[6] = node.getResponseBuffer(6);

uint8_t result = node.readInputRegisters( 10, 7 ); // Read 2x 16-bit words

Serial.print("result = ");
Serial.println( result );
if (result == node.ku8MBSuccess)
{
Serial.print("data1 : ");
Serial.print(node.getResponseBuffer(0));
Serial.print(" ");
Serial.println(node.getResponseBuffer(1));
Serial.print(" ");
Serial.println(node.getResponseBuffer(2));
Serial.print(" ");
Serial.println(node.getResponseBuffer(3));
Serial.print(" ");
Serial.println(node.getResponseBuffer(4));
Serial.print(" ");
Serial.println(node.getResponseBuffer(5));
Serial.print(" ");
Serial.println(node.getResponseBuffer(6));
Serial.print(" ");
Serial.print("Temperature: ");
//Serial.print(f_2uint_float(DATA[0],DATA[1]));
//Serial.println(" C");
}
Serial.print("\n");

delay(1000);
}

what could be the issue ? ,is the code correct ? please kindly help me , thank you very much ,

console shows :

You can't expect the answers before you ask the question.

Let's try something simple:

// FOR MEGA2560 with Modbus device #4 on Serial #1 @ 9600 baud.

#include <ModbusMaster.h> //Library for using ModbusMaster

#define MAX485_DE 2
#define MAX485_RE_NEG 3

ModbusMaster node; //object node for class ModbusMaster

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

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

void setup()
{
  pinMode(MAX485_RE_NEG, OUTPUT);
  pinMode(MAX485_DE, OUTPUT);

  digitalWrite(MAX485_RE_NEG, 0);
  digitalWrite(MAX485_DE, 0);

  Serial.begin(9600);
  Serial1.begin(9600); //Baud Rate as 9600

  node.begin(4, Serial1); //Slave ID as 4 on Serial #1
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

void loop()
{
  uint8_t result = node.readInputRegisters( 10, 1 ); // Read one 16-bit word

  Serial.print("result = ");
  Serial.println( result );
  if (result == node.ku8MBSuccess) {
    Serial.print("data1 : ");
    Serial.println(node.getResponseBuffer(0));
  }
  Serial.print("\n");

  delay(1000);
}

The above code is untested, but should work. You need the Modbus library to return Success from the readInputRegisters call. If it does not, then you likely have a wiring issue or a documentation issue.