Issues with MODBUS RTU communication and Holding Registers

Hey Everyone! I have been trying to communicate a Suto S220 sensor with an Arduino UNO R4 using a MAX485 module. I have attached the program, Sensor Datasheet and the circuit diagram here as well.

No matter what I try, I keep getting the Error : E2

Suto S220 Datahseet

#include <ModbusMaster.h>

#define RE_PIN 7      // Receive Enable
#define DE_PIN 6      // Data Enable
#define TX_PIN 11     // Transmit (DI)
#define RX_PIN 10     // Receive (RO)

ModbusMaster node;

void preTransmission() {
  digitalWrite(DE_PIN, HIGH);
  digitalWrite(RE_PIN, HIGH);
}

void postTransmission() {
  digitalWrite(DE_PIN, LOW);
  digitalWrite(RE_PIN, LOW);
}

void setup() {
  // Initialize Serial for debugging
  Serial.begin(19200); // Match baud rate with sensor

  // Initialize RS485 control pins
  pinMode(DE_PIN, OUTPUT);
  pinMode(RE_PIN, OUTPUT);
  
  // Set RS485 transceiver to receive initially
  digitalWrite(DE_PIN, LOW);
  digitalWrite(RE_PIN, LOW);

  // Modbus configuration
  node.begin(27, Serial); // Replace '1' with the correct Modbus ID if needed
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);

  Serial.println("Starting Modbus communication test...");
}

void loop() {
  uint8_t result;

  // Send a read request to a generic register (e.g., register 2000)
  result = node.readHoldingRegisters(2000, 1);

  if (result == node.ku8MBSuccess) {
    Serial.println("Communication successful: Sensor responded.");
  } else {
    Serial.print("Communication failed. Error code: ");
    Serial.println(result, HEX);
  }

  delay(1000); // Wait 1 second before the next test
}

The screenshot of your serial monitor suggests that you are using the same serial port for diagnostic printing that you are using for your modbus comms. That's usually a bad idea.

I'm not familiar with the UNO R4. I know it's much more advanced than the original UNO. Does it not have any additional hardware serial ports?

Error code E2 = response timeout - i.e. the sensor didn't respond to the request.

Are you sure that your sensor ID is 27? The default is usually 1, unless you've changed it.

Page 24 of your datasheet says that the response time is 1 second. I hope that is the time the sensor takes to calculate a new value rather than the time taken to respond to the modbus message!

Hey, thank you for your reply.

I have also tried using the Sensor ID as 1, with the same results unfortunately.

Would you suggest using software and hardware serial in tandem?

One thing I would suggest is that it would help you a lot if you were able to buy a USB-RS485 dongle. They are pretty cheap and it will allow your PC to talk to the sensor using one of the free modbus programs. It's a lot easier to adjust parameters in a PC program than to keep recompiling Arduino code.

Once you get the sensor working with the PC program, you will know the correct serial comms parameters as well as the sensor ID.

If you do get hold of one of the USB-RS485 dongles, then it ma be worth asking the sensor manufacturer if they have a PC program that will communicate with the sensor. That too will give you confidence that the sensor is working and likely expose the device ID and register addresses too.

I think it is a good suggestion to use software serial to monitor the sensor and hardware serial for debugging. Of course, check your baud rates and everything.

The other thing that stands out to me here is that, according to the schematic, the ground on your sensor isn't connected to the rest of the system. I would recommend ensuring that the ground on your sensor is at the same voltage level as the ground on your arduino and your RS485 converter. Keep your additional power supply isolated, but connect all of the grounds together. A floating ground may be enough to wreck your data.

Hope this helps!

Should be Serial1, Serial is your USB-serial.
So you need to add
Serial1.beging(19200);
and correct
node.begin(27, Serial1);

And correct pins are Rx 0 and Tx 1

Are you sure that slave address is 27?

Yes, slave address is printed on the sensor itself and is 27.

I have tried this as well, unfortunately the same result persists. Thank you!

Did you change the pins?
Serial1 uses RX and TX pins 0 and 1

Maybe you should post your new code so we can see if you missed something.

#include <ModbusMaster.h>

#define MAX485_DE 2
#define MAX485_RE_NEG 2

ModbusMaster node;

void preTransmission() {
  digitalWrite(MAX485_RE_NEG, HIGH);
}

void postTransmission() {
  digitalWrite(MAX485_RE_NEG, LOW);
}

void setup() {
  Serial.begin(19200);  // Arduino Serial Monitor
  Serial1.begin(19200, SERIAL_8N1);  // Modbus baud rate and settings
  
  pinMode(MAX485_RE_NEG, OUTPUT);
  digitalWrite(MAX485_RE_NEG, LOW);

  node.begin(1, Serial1);  // Modbus ID 1 (check your device's settings)
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
}

void loop() {
  uint8_t result;
  uint16_t data[2];

  // Reading Dew Point (example register address - replace as needed)
  result = node.readInputRegisters(0x2301, 2);  // Replace with correct register address for dew point

  if (result == node.ku8MBSuccess) {
    float dewPoint = node.getResponseBuffer(0) / 10.0;  // Scale as required by device specs
    Serial.print("Dew Point: ");
    Serial.print(dewPoint);
    Serial.println(" °C");
  } else {
    Serial.println("Failed to read from transmitter");
  }

  delay(2000);  // Polling interval
}

You set the address back to "1" and not "27"
Should be:
node.begin(27, Serial1); // Modbus ID 1 (check your device's settings)

I have tried doing that as well. Unfortunately the same results.

Well two more issues:
You gave the register value in hex. It should just be 2301
You may need to put a120 ohm resistor across the S220 D+ and D-

Also
You should use Holding Register

Change
result = node.readInputRegisters(0x2301, 2);
To
result = node.readHoldingRegisters(0x2301, 2);

Thank you so much for the feedback Jim. I have been actually using the Holding Registers, just was trying something in the code and forgot to edit it out.

I'm gonna make the changes from your previous suggestion and hopefully it works! Again, thank you.

I did make a mistake with the address 0x2301 is correct.

1 Like

Why you deleted the response line from your code??
You are blind without it, you don't get any feedback from the library indicating what is your problem.
Serial.println(result, HEX);
put it back where it was and post what error you get.
Did you wire your RO to 0 and DI to 1 ?
Did you physically bridge RE and DE to single pin2 ?

1 Like

Yes to both questions and I still get the same error E2.

Did you add the 120 ohm resistor?

Yes.