Reading modbus register of a radar level transmitter with MAX RS485 to Serial module using arduino

Hello everyone, a few days ago I acquired a radar level transmitter sensor with a maximum range of 15 meters, I am trying to read the Modbus registers of the RS 485 communication that brings the level transmitter, however, when loading the code shown to my Arduino UNO board, with the connections shown in the schematic, I can not read any data.

Connections made

Code implemented

#include <ModbusMaster.h>
#include <SoftwareSerial.h>


#define RX_PIN 11
#define TX_PIN 10
#define MAX485_REDE_PIN 12
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);

ModbusMaster node; 

void preTransmission() 
{
  digitalWrite(MAX485_REDE_PIN, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_REDE_PIN, 0);
}

void setup()
{
  pinMode(MAX485_REDE_PIN, OUTPUT);

  digitalWrite(MAX485_REDE_PIN, 0);
  
  Serial.begin(9600); 
  Serial.println( MAX485_REDE_PIN );
  
  modbusSerial.begin(9600); 
  node.begin(1, modbusSerial); 

  node.preTransmission(preTransmission); 
  node.postTransmission(postTransmission);
}

void loop()
{
  uint16_t result = node.readHoldingRegisters(0x03,6); 
  
  Serial.println(result,HEX);

  if (result == node.ku8MBSuccess)
  {
    Serial.print("data : ");
    Serial.print(node.getResponseBuffer(1));
    Serial.print(" , ");
    Serial.println(node.getResponseBuffer(2));
  }
  Serial.print("\n");

  delay(100);
}

this is the data to read the Modbus registers that were delivered by the vendor.

When I open the serial monitor I can only read the following data:

3

3

E2

3

3

3

If someone could give me a hand with this implementation would be great for the whole community. greetings to all. I remain attentive to your advice and recommendations.

what does this do??

#include <ModbusMaster.h>
#include <SoftwareSerial.h>


#define RX_PIN 11
#define TX_PIN 10
#define MAX485_REDE_PIN 12
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);

ModbusMaster node; 

void preTransmission() 
{
  digitalWrite(MAX485_REDE_PIN, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_REDE_PIN, 0);
}

void setup()
{
  pinMode(MAX485_REDE_PIN, OUTPUT);

  digitalWrite(MAX485_REDE_PIN, 0);
  
  Serial.begin(9600); 
  Serial.println( MAX485_REDE_PIN );
  
  modbusSerial.begin(9600); 
  node.begin(1, modbusSerial); 

  node.preTransmission(preTransmission); 
  node.postTransmission(postTransmission);
}

void loop()
{
  //read 5 regs starting at address 2..
  uint16_t result = node.readHoldingRegisters(0x02,5); 
  Serial.print("result: ");Serial.println(result,HEX);
  if (result == node.ku8MBSuccess)
  {
    Serial.print("Current Level : ");
    Serial.println(node.getResponseBuffer(0));
    Serial.print("Measure Range: ");
    Serial.println(node.getResponseBuffer(1));
    Serial.print("Base Offset: ");
    Serial.println(node.getResponseBuffer(2));
    Serial.print("Baude Rate: ");
    Serial.println(node.getResponseBuffer(3));
    Serial.print("Device ID: ");
    Serial.println(node.getResponseBuffer(4));
  }
  Serial.print("\n");

  delay(2000);
}

good luck.. ~q

Hi Bro, I run your code, and this is what I found on the Serial monitor:

result: 3

result: 3

result: 3

result: 3

But, I have a really good news. There I can read the buffers that I needed, so this is the code That works for me:

#include <ModbusMaster.h>
#include <SoftwareSerial.h>

#define RX_PIN 11
#define TX_PIN 10
#define MAX485_REDE_PIN 12
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);

ModbusMaster node; //object node for class ModbusMaster

//Variables de medicion de radar
int Rango = 0;
int Nivel = 0; 


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


void postTransmission()
{
  digitalWrite(MAX485_REDE_PIN, 0);
}


void setup()
{
  pinMode(MAX485_REDE_PIN, OUTPUT);
  digitalWrite(MAX485_REDE_PIN, 0);
  Serial.begin(9600); 
  modbusSerial.begin(9600); 
  node.begin(1, modbusSerial); 
  node.preTransmission(preTransmission); 
  node.postTransmission(postTransmission);
}

void loop()
{
  uint16_t result = node.readHoldingRegisters(0x01, 2);
  if (result == node.ku8MBSuccess)
  {
    Nivel = node.getResponseBuffer(0);
    Rango = node.getResponseBuffer(1);
    return Nivel, Rango;
  }

  int Distancia = Rango - Nivel;   //Distancia medida en mm 
  Serial.print(Distancia);
  Serial.println(" mm");

  delay(10);
}

I read the buffer 0 and 1, with the 0x01 address, and when I get the values, I only have to make Distance = Range - Level, and That's all bro, this code works with the same schematic diagram that I show in my first publication. I hope that it could work for you bro, Thank you so much.

Best regards.

that is..

static const uint8_t ku8MBIllegalDataValue           = 0x03;

index was off or too many regs..
Glad you got something going..
um..

take out, makes no sense..

good luck.. ~q

Thanks for your advice, I have corrected your observations. it was so helpful for me. Best regards.

Hello, I need your help, I have an ultrasonic level transmitter, and the manufacturer only shared the following information with me, the data reviewed in the instrument is:
Address: 001, baudrate: 2400, check digit: None, data bits: 8 stop bit: 1

The only response I have received is E2

I was varying uint16_t result = node.readHoldingRegisters(0x01,2);
and I still get the same E2 value

Hi @Hugo_Molina ,

Welcome to the forum..

The dreaded E2..

static const uint8_t ku8MBResponseTimedOut           = 0xE2;

means no response received..
even if it was a bad register address requested the device should respond if addressed properly..
make sure you got your baud at 2400 like the manu says, can't hurt to try other bauds just to see..
check your connections..
still not getting it, then we need more info..
connection diagram and test code please..

good luck.. ~q


I use the same connection from the diagram and share the example that the manufacturer provided me.

#include <ModbusMaster.h>
#include <SoftwareSerial.h>


#define RX_PIN 11
#define TX_PIN 10
#define MAX485_REDE_PIN 12
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);

ModbusMaster node; 

void preTransmission() 
{
  digitalWrite(MAX485_REDE_PIN, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_REDE_PIN, 0);
}

void setup()
{
  pinMode(MAX485_REDE_PIN, OUTPUT);

  digitalWrite(MAX485_REDE_PIN, 0);
  
  Serial.begin(9600); 
  Serial.println( MAX485_REDE_PIN );
  
  modbusSerial.begin(9600); 
  node.begin(1, modbusSerial); 

  node.preTransmission(preTransmission); 
  node.postTransmission(postTransmission);
}

void loop()
{
  //read 5 regs starting at address 2..
  uint16_t result = node.readHoldingRegisters(0x02,5); 
  Serial.print("result: ");Serial.println(result,HEX);
  if (result == node.ku8MBSuccess)
  {
    Serial.print("D1 : ");
    Serial.println(node.getResponseBuffer(0));
    Serial.print("D2: ");
    Serial.println(node.getResponseBuffer(1));
  }

did you also try the default 2400??

per your doc, this should be (1,1)..
only 1 reg, so just one word, ResponseBuffer(0) only..

bad baud would result in no replies "E2"..

good luck.. ~q

I have used the default configuration at 2400 baud and I always get E2, I changed the baudrate on the device and in the code and I still get E2.

Do you think it could be the connections?

how??
This is usually a write register command, so you first needs comms up to do it..

could be, diagram looks ok, can try switching the a and b, won't hurt just won't work..

could also be wrong address, reading the doc, they have an "if" there..
If the meter address is 01..

not sure if the lib allows it, but try changing that 1 to 255..
address 255 is the modbus broadcast address all modules connected should respond and can find out what address it is currently set too..

but obviously the address can be changed..

a usb485 adapter for the PC would be handy, could test comms to the unit..

in the code pic, you are still trying to getResponseBuffer(1) even though you only ask for 1..
the one response will be in Buffer(0) only..

if the address is wrong, you can get "E2"..
if CRC is wrong, usually due to bad baud, you get "E2"..

could be more than 1 thing..

good luck.. ~q

if you can't do the 255 address then maybe give this sketch a try..
Uno 7n1 Modbus
it's for some 7 in 1 sensor, reads registers 0-6..
looks like your command is in temp register 1..
this sketch does not use a lib for the modbus so you get more debug info and you can use the 255 addresses..

maybe it helps..

good luck.. ~q

Thanks, I'll try it and tell you how it went.

The problem was very simple, a cable is making false contact.
The code with which it operates is the following:

#include <ModbusMaster.h>
#include <SoftwareSerial.h>


#define RX_PIN 11
#define TX_PIN 10
#define MAX485_REDE_PIN 12
SoftwareSerial modbusSerial(RX_PIN, TX_PIN);

ModbusMaster node; 

void preTransmission() 
{
  digitalWrite(MAX485_REDE_PIN, 1);
}

void postTransmission()
{
  digitalWrite(MAX485_REDE_PIN, 0);
}

void setup()
{
  pinMode(MAX485_REDE_PIN, OUTPUT);

  digitalWrite(MAX485_REDE_PIN, 0);
  
  Serial.begin(2400); 
  Serial.println( MAX485_REDE_PIN );
  
  modbusSerial.begin(2400); 
  node.begin(1, modbusSerial); 

  node.preTransmission(preTransmission); 
  node.postTransmission(postTransmission);
}

void loop()
{
  //read 5 regs starting at address 2..
  uint16_t result = node.readHoldingRegisters(0x01,1); 
  Serial.print("result: ");Serial.println(result,HEX);
  if (result == node.ku8MBSuccess)
  {
    Serial.print("D1 : ");
    Serial.println(node.getResponseBuffer(0));
  }
  Serial.print("\n");

  delay(2000);
}

@qubits-us thank you so much!!

1 Like

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