ArduinoTroubleshooting

Can't read the Wind Speed & Direction (SEN0483 + SEN0482) data using Arduino and MAX485 (RS485).

userHead Nat.Ce 2026-06-19 09:18:59 321 Views4 Replies

Hi there, 

I can't seem to figure out how to read the data from the sensors using standard RS485 protocol with a MAX485 board and the ModbusMaster library. I use an ESP32-S3 Arduino board (using HardwareSerial for UART) and an Arduino UNO R3 (using SoftwareSerial for UART).

This is the MAX485 board I am using: https://www.amazon.ca/dp/B00NIOLNAG?ref=ppx_yo2ov_dt_b_fed_asin_title 

All the wiring is correct, the script is working, but I just don't get any back but some result = 226…

Anyone that could help me out here?

I saw this blog post: https://community.dfrobot.com/makelog-313358.html , but does that mean that it is mandatory to use the Gravity: Active Isolated RS485 to UART Signal Adapter Module (https://www.dfrobot.com/product-2392.html) to make this work?

Thanks!

See code: 
// Include the ModbusMaster library for Modbus RTU communication

#include <ModbusMaster.h>

// Include HardwareSerial library to assign the pins for UART1 and UART2

#include <HardwareSerial.h>


 

// Define the pins for MAX485 module

// UART1 for Sensor 1

HardwareSerial SerialSensor1(1); // UART1

#define MAX485_DE_RE_1 2 // DE and RE pins are connected together

#define MAX485_RO_RX_1 0 // RO (Receiver Output) pin = RX

#define MAX485_DI_TX_1 1 // DI (Driver Input) pin = TX



 

// UART2 for Sensor 2

//HardwareSerial SerialSensor2(2); // UART2

//#define MAX485_DE_RE_2 7 // DE and RE pins are connected together

//#define MAX485_RO_RX_2 6 // RO (Receiver Output) pin = RX

//#define MAX485_DI_TX_2 5 // DI (Driver Input) pin = TX



 

// Create TWO separate ModbusMaster instances

ModbusMaster node1; // For Sensor 1 (UART1/SerialSensor1)

//ModbusMaster node2; // For Sensor 2 (UART2/SerialSensor2)



 

void setup() {

// Initialize Serial for debugging

Serial.begin(115200);

delay(2000);



 

Serial.println("Initializing Modbus communication...");


 

// Initialize Serial1 for RS485 communication

// Initialize UART1 (Sensor 1)

SerialSensor1.begin(9600, SERIAL_8N1, MAX485_DI_TX_1, MAX485_RO_RX_1); // Assign TX and RX pins to UART1

pinMode(MAX485_DE_RE_1, OUTPUT);

digitalWrite(MAX485_DE_RE_1, LOW); // Start in receive mode


 

// Initialize UART2 (Sensor 2)

//SerialSensor2.begin(9600, SERIAL_8N1, MAX485_DI_TX_2, MAX485_RO_RX_2); // Assign TX and RX pins to UART2

//pinMode(MAX485_DE_RE_2, OUTPUT);

//digitalWrite(MAX485_DE_RE_2, LOW); // Start in receive mode

 

// Initialize ModbusMaster with the Serial1 port

node1.begin(2, SerialSensor1); // '2' is the Modbus slave ID (0x02 in hex, but library uses decimal)

// Initialize ModbusMaster with the Serial2 port

//node2.begin(2, SerialSensor2); // '2' is the Modbus slave ID (0x02 in hex, but library uses decimal)


 

Serial.println("Modbus communication initialized. Waiting for data...");

}



 

void loop() {

float sensorValue = readSensor(node1, MAX485_DE_RE_1, "Wind Speed", "m/s"); // Store returned value

//float windDirection = readSensor(node2, MAX485_DE_RE_2, "Wind Direction", "deg");


 

delay(1000);

}


 

float readSensor(ModbusMaster &node, uint8_t de_re_pin, const char* sensorName, const char* sensorUnit) {

 

// Set MAX485 to transmit mode (assuming DE/RE is controlled elsewhere)

Serial.println(" - Setting DE/RE HIGH...");

digitalWrite(de_re_pin, HIGH);

delay(50);


 

// Clear response buffer

node.clearResponseBuffer();


 

// Send Modbus request (Function code 0x03 implied by readHoldRegisters function from ModbusMaster lib, Register adddress 0x0000 = 0x00 0x00, Register length 0x0001 = 0x00 0x01)

Serial.println("Transmitting request...");

uint8_t result = node.readHoldingRegisters(0x0000, 1);

 

// Set MAX485 to receive mode

Serial.println("Setting DE/RE LOW...");

digitalWrite(de_re_pin, LOW);



 

if (result == node.ku8MBSuccess) {

uint16_t rawValue = node.getResponseBuffer(0);

float sensorValue = rawValue / 10.0; // Convert to m/s or deg from North 0deg reference. Divided by 10 as per sensor datasheet to get decimal point.

Serial.print(sensorName);

Serial.print(": ");

Serial.print(sensorValue, 1);

Serial.println(sensorUnit);

return sensorValue; // Return the value

} else {

Serial.print(sensorName);

Serial.print(" Error: ");

Serial.println(result); // Prints the raw error code (e.g., 1, 2, 3...)

return -1.0; // Return an error value (e.g., -1)

}

}

2026-06-22 10:37:14

Hi,

 

The Gravity isolated RS485 adapter is not mandatory. A MAX485 module should also work.

 

result = 226 usually means Modbus response timeout, so the request may not be sent correctly, or the sensor reply is not being received.

 

Please mainly check:

1. ESP32 HardwareSerial.begin() pin order should be RX first, then TX.

2. MAX485 DE/RE should switch back to receive mode immediately after sending. It is better to use preTransmission() / postTransmission() with ModbusMaster.

3. Try swapping RS485 A/B if there is no response.

4. If SEN0482 and SEN0483 are on the same bus, make sure they do not use the same slave address. Their default address may be the same.

 

The DFRobot isolated RS485 module is recommended for reliability, but not required.

userHeadPic Yx
Nat.Ce wrote:

Thank you very much for replying to me on this!


I managed to make it work.

 

The key here was to use the following calls:

void preTransmission(){

digitalWrite(MAX485_DE_RE_1, 1);

}

void postTransmission(){

digitalWrite(MAX485_DE_RE_1, 0);

}
 

AND this in the void setup() portion:

node.preTransmission(preTransmission);

node.postTransmission(postTransmission);


It seems that when using the ModbusMaster library, the pre/postTransmission functions are called within the pre-build function like e.g. readHoldingRegister(). They handle the high and low state of the RE and DE pins. The digitalWrite() function is to be used in these pre/postTransmission functions separately and not inside the void loop(), else it doesn't work. And this is because the script requires to also use the node.pre/postTransmission(pre/postTranmission); callout in the void setup(). Else it won't work. It seems that this function configures the RS485 transceiver correctly. 

 

In terms of example to use from the ModbusMaster library, this is the most applicable (Half Duplex):

https://github.com/4-20ma/ModbusMaster/blob/3a05ff87677a9bdd8e027d6906dc05ca15ca8ade/examples/RS485_HalfDuplex/RS485_HalfDuplex.ino

2026-06-23 22:50:36
Nat.Ce wrote:

Here is the script for anyone that might need the same help in the future (I switched from the ESP32 to an Arduino Uno R3 for this, thus I am using SoftwareSerial instead of HardwareSerial):
 

(PART #1)

 

/*This script is made for an Arduino Uno R3 in combination with a MAX485 to TTL board. It is used to read the SEN0483 Wind Speed sensor.*/


 

// Include the ModbusMaster library for Modbus RTU communication

#include <ModbusMaster.h>

// Include SoftwareSerial library to assign the pins for UART1 and UART2

#include <SoftwareSerial.h>

 

// Define the pins for MAX485 module

// UART1 for Sensor 1

#define MAX485_DE_RE_1 2 // DE and RE pins are connected together

#define MAX485_RO_RX_1 3 // RO (Receiver Output) pin = RX

#define MAX485_DI_TX_1 4 // DI (Driver Input) pin = TX
 

SoftwareSerial mySerial(MAX485_RO_RX_1, MAX485_DI_TX_1); //Define the soft serial port, RX = GPIO 3, TX = GPIO 4

 

// Create TWO separate ModbusMaster instances

ModbusMaster node; // For Sensor 1 (UART1/SerialSensor1)

 

void setup() {

// Initialize Serial for debugging

Serial.begin(115200);

delay(2000);

 

Serial.println("Initializing Modbus communication...");

 

// Initialize Serial1 for RS485 communication

// Initialize UART1 (Sensor 1)

mySerial.begin(9600);

pinMode(MAX485_DE_RE_1, OUTPUT);

digitalWrite(MAX485_DE_RE_1, 0); // Start in receive mode

 

// Initialize ModbusMaster with the Serial1 port

node.begin(2, mySerial); // '2' is the Modbus slave ID (0x02 in hex, but library uses decimal)

 

// Callbacks allow us to configure the RS485 transceiver correctly. This is key, without this call, the data won't come out.

node.preTransmission(preTransmission);

node.postTransmission(postTransmission);

 

Serial.println("Modbus communication initialized. Waiting for data...");

}
 

void preTransmission(){

digitalWrite(MAX485_DE_RE_1, 1);

}

void postTransmission(){

digitalWrite(MAX485_DE_RE_1, 0);

}

2026-06-23 22:55:16
Nat.Ce wrote:

(PART #2)

 

void loop() {

float sensorValue = readSensor(node, "Wind Speed", "knots"); // Store returned value

delay(1000);

}

 

float readSensor(ModbusMaster &node, const char* sensorName, const char* sensorUnit) {

 

// Set MAX485 to transmit mode: preTransmission() is automatically called in the ModbusMaster functions. No need to call it. Manually setting the pins HIGH and LOW with digitalwrtie

 

// Clear response buffer

node.clearResponseBuffer();

 

// Send Modbus request (Function code 0x03 implied by readHoldRegisters function from ModbusMaster lib).

uint8_t result = node.readHoldingRegisters(0x0000,1); // The register address is 0x00 0x00, and there is only 1 data register to read.

 

// Set MAX485 to receive mode: postTransmission() is automatically called in the ModbusMaster functions. No need to call it.

 

if (result == node.ku8MBSuccess) {

uint16_t rawValue = node.getResponseBuffer(0); // Only one register to read for the wind speed. 0 seems to be the position of the first and only register.

float sensorValue = rawValue * 1.94384 / 10.0; // Convert to m/s or deg from North 0deg reference. Divided by 10 as per sensor datasheet to get decimal point.

Serial.print(sensorName);

Serial.print(": ");

Serial.print(sensorValue, 1);

Serial.println(sensorUnit);

return sensorValue; // Return the value

} else {

Serial.print(sensorName);

Serial.print(" Error: ");

Serial.println(result); // Prints the raw error code (e.g., 1, 2, 3...)

return -1.0; // Return an error value (e.g., -1)

}

}

2026-06-23 22:55:39
3 Replies