Connecting RS485 / MODBUS anemometer toArduino MEGA

Dear experts,
I have bought an anemometer from China with RS485/MODBUS interface (named 3001-FS). I would like to connct it with my Arduino MEGA.

I have bought additional components to connct it:

  • A step-up converter to operate the device at 24V from my 5V power source (and I have confirmed it is working fine and supplying 24V)
  • A RS485<->TTL232 converter (type R411A01), which seems to have an autp TX read toggle. I have connected the device at A+/B- and the Arduino at RX/TX at Serial1 (and of course, also 5V and ground)

The device comes with a manual (attached), which provides the parameters of the MODBUS (which gives me a lot of trouble as I am not familiar with MODBUS at all.

I have used the simplemodbusmaster library with the following code:

#include <SimpleModbusMaster.h>
#define baud 9600                                                                                  // SENSOR SPEC
#define timeout 1000
#define polling 200 // the scan rate
#define retry_count 10
// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 9                                                                           // INDUSTRUINO RS485
// The total amount of available memory on the master to store data
#define TOTAL_NO_OF_REGISTERS 1                                                // SENSOR SPEC

enum
{
  PACKET1,                                          // only need 1 type of operation: read wind sensor
  TOTAL_NO_OF_PACKETS // leave this last entry
};
// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];
// Masters register array
unsigned int regs[TOTAL_NO_OF_REGISTERS];
void setup()
{
  modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0, 1, 0);
  
  // Initialize the Modbus Finite State Machine
  // default SERIAL_8N2 -- wind sensor brochure mentions n,8,1 = 8N1??
  modbus_configure(&Serial1, baud, SERIAL_8N1, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs);
                                                                                // Serial1 = INDUSTRUINO RS485
  Serial.begin(9600);
}
void loop()
{
  modbus_update();                                                             // send 1 simple Master request to Slave, as defined above
  
  float wind_speed = regs[0] / 10.0;
  
  Serial.print("wind speed (m/s): ");
  Serial.println(wind_speed);
  delay(3000);
  
}

I have found a website with a similar device and used that code (Modbus RTU on Industruino IND.I/O | Industruino).

Can somebody please help me to debug this and provide ideas what I can try to get it to work?

Thanks,
MRoggi

test-compressed.pdf (557 KB)

Your manual says that the windspeed is in register 0x16, so the packet construction should read:

modbus_construct(&packets[PACKET1], 1, READ_HOLDING_REGISTERS, 0x16, 1, 0);

Did your code compile? In that case you're using another version of the library (there are several cloned repos on the internet) than me. Post a link to the version you're using!

@pylon hi, it would be fine if you could give the right place to find the right version of the simplemodbusmaster library !
Thanks

Did I write you’re using a wrong version? I just asked which version you’re using. I have no clue if there is a “right” version of that library, I don’t use it because I don’t like it’s API.

Excuse me to be a beginner. I have the same wind sensor I’m trying to get working on an Arduino Uno. I must use SoftwareSerial.h for RS485.
Despite all the hours spent reading documentation I do not understand what and how to send to get the wind speed :frowning:
According to the wind sensor datasheet, I send the frame “0x01 0x03 0x00 0x16 0x00 0x01 0x65 0xCE” right ?
Then the answer will be the frame “0x01 0x03 0x02 0x00 0x17 0xF8 0x4A” for a 17H wind speed.

According to the precedent code, from what you say, the address is the Register address, not the Address code, so 0x16 instead of 0x01. So, where the transmit frame is declare ?

Thanks

it is working now. Here is the code :

#include <SoftwareSerial.h>  // https://github.com/PaulStoffregen/SoftwareSerial

#define RX        10    //Serial Receive pin
#define TX        11    //Serial Transmit pin
#define RTS_pin    9    //RS485 Direction control
#define RS485Transmit    HIGH
#define RS485Receive     LOW

SoftwareSerial RS485Serial(RX, TX);

void setup() {

  pinMode(RTS_pin, OUTPUT);  
  
  // Start the built-in serial port, for Serial Monitor
  Serial.begin(9600);
  Serial.println("Anemometer"); 

  // Start the Modbus serial Port, for anemometer
  RS485Serial.begin(9600);   
  delay(1000);
}

void loop() {

  digitalWrite(RTS_pin, RS485Transmit);     // init Transmit
  byte Anemometer_request[] = {0x01, 0x03, 0x00, 0x16, 0x00, 0x01, 0x65, 0xCE}; // inquiry frame
  RS485Serial.write(Anemometer_request, sizeof(Anemometer_request));
  RS485Serial.flush();
  
  digitalWrite(RTS_pin, RS485Receive);      // Init Receive
  byte Anemometer_buf[8];
  RS485Serial.readBytes(Anemometer_buf, 8);
 
  Serial.print("wind speed : ");
  for( byte i=0; i<7; i++ ) {
  Serial.print(Anemometer_buf[i], HEX);
  Serial.print(" ");
  }
  Serial.print(" ==> ");
  Serial.print(Anemometer_buf[4]);
  Serial.print(" m/s");
  Serial.println();                  
  delay(500);

}