Arduino UNO + Modbus RTU RS485 + wind sensor

I did some other tests by changing the baudrate, but nothing changed, I still get garbage.
I did also these other tests:

  • if I disconnect both data+ and data-, then I get nothing
  • if I swap the wire data+ with data-, then I get garbage, but the output is different

At the moment, this is my current wiring:

The sensor works at 24VDC, so the power supply is +24VDC and GND
Then, I connected data+ to the A+ pin on my usb to rs485 converter and data- from the sensor to the B- pin on the converter.
I also connected gnd from the power supply to GND on the converter.

So, in total, there are three wires from the sensor to the converter: data+, data- and GND.

Should I use a resistor?
The wire from the sensor to the converter are about 1.5 meters long.

The sensor is the Lambrecht u[sonic]WS6 sensor, it is a very expensive sensor (2000EUR) and from the manual it says that the standard connection is 19200, 8E1, address 5

I post here the rs485 description coming from the manual.

If you are using an UNO, then I believe that in order to satisfy the requirement for 8E1 (8-bits, even parity & 1 stop bit), you will need to use the modified AltSoftSerial library that was mentioned in post #10.

I think those RS485 modules have the pull up, pull down and terminating resistors fitted. That should be enough for basic bench testing.

That's strange. I wonder where the garbage is coming from.

Are RE and DE wired up correctly? It could be that RE is not changing and your UNO is hearing its own transmission.

At the moment, I'm not using the UNO since the sensor seems to be a little bit complex.
So, now, I'm still using the modbus software on Windows with the USB adapter.

I think that using Arduino at this moment would complicate the things.

I agree. It's a lot easier to figure out the comms parameters via a PC app.

Is the sensor new? If it's new, then it's reasonable to assume that it is configured for the default comms parameters of 19200,8,E,1 and address 5.

Does the manufacturer have a PC app that connects to the sensor?

Yes the sensor is new, so the paramters should be that ones.

I think there is a software but it is under license and the price is abour 1500 eur.
Moreover, they also have a datalogger and the price is 1200 eur.

It is too much so i would like to use arduino.
At the moment i'm still struggling with the pc software.. can't understand why im not able to read anything.

Does the company have a tech support department. With a sensor that expensive, they should have somebody who can clarify a few things for you. If you tell them what PC software you are using, then they should be able/willing to assist you.

EDIT: I wonder if the following modbus scanner software would help:

1 Like

I tried it and it scans the port to find devices testing all the address IDs however it wasn't able to find any correct answer. So, I had no success with it.

However, by using another software, I noticed that the sensor continuously send some output as soon as it is powered on. The problem is that I'm not able to correctly read the output with any software.

I finally got it working (I think) by changing the parameters with another software.
At the end, if I set:

setting

Then I get this output continuously since the sensor output it automatically:

I think it is correct since WIMWV should be some kind of notation for wind sensors even if i do not know what does it means :slight_smile:

Do you think now it is possible to switch to Arduino?
What kind of library should I use? I only need to read at this point, I think.. I do not need to send any request to the sensor..

This is another screenshots where it is possible to see both the HEX and the packets on the right:

it seems to be always the same: WIMTA, WIMHU, WIMMB, WIMWV
but I can't figure out how to use this in Arduino.. hope you can help me

That would suggest that the sensor doesn't use the Modbus message protocol. When using Modbus, the sensor should only transmit when it is asked for data.

The serial parameters you discovered - i.e. 4800,8,E,1 are clearly correct as the output you posted shows pure ASCII text. You should be able to view it with any terminal emulator software.

Each line starts with a $ symbol and terminates with CR & LF - carriage return & line feed - the 0D and 0A characters.

I did a quick search via google for "$wimta message" and got a hit to a PDF for a slightly different sensor from the same company:

That gave me the name EOLOS and another google search gave me a different manual:

Section 6 details the message contents I think.

WIMWV = wind speed
WIMTA = air temperature
WIMMB = barometric pressure

Etc.

1 Like

Thank you a lot and yes, I can read the output with putty or any other similar software.

At this point, I could just write a arduino code where:
I start reading the string when I receive a $ and stop reading it when I found \r\n, is it correct?

I'm not very skilled, so it won't be immediate for me to write this code, but I'll try!

Yes, that's the way to do it. Your end marker can be either \r or \n.

Have a read of this discussion:

By reading through the above, you should have an idea of how to do this. Example 5 in post #3 looks to be a good match for your messages.

You will need to modify the recvWithEndMarker() function to use a software serial port created using the modified AltSoftSerial library that @DaveEvans linked to back in post #10.

Have a look at the original page for AltSoftSerial here to see a simple example of how to use it:
https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html

The format of the messages you've shown bear a striking resemblance to the NMEA 0183 messages that i've seen with off the shelf GPS modules. Wikipedia has a page here:

I wonder if one of the tinyGPS libraries could be tweaked to pick up your specific messages and decode them.

This page on tinyGPS++ looks interesting: TinyGPS++ | Arduiniana
Especially the section called Custom NMEA Sentence Extraction. It sounds like it could do all the hard work of parsing those messages for you.

Thanks to your support, I was able to going on with this project. Now, I'm able to acquire the measurements from the wind sensor and feed them on the network by using a RS232-to-Ethernet converter.
I configured my Arduino MEGA + an Ethernet shield to work as a TCP Client and I can read the data stream continuously without problems.

#include <Ethernet.h>
#include <SPI.h>

byte mac[] = { 0xBE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 100 };
byte server[] = { 192, 168, 1, 200 }; // Touchberry Pi Server
int tcp_port = 4196;

EthernetClient client;

void setup()
{
  Ethernet.begin(mac, ip);
  Serial.begin(9600);

  delay(1000);

  Serial.println("Connecting...");

  if (client.connect(server, tcp_port)) { // Connection to server.js
    Serial.println("Connected to server.js");
    client.println();
  } else {
    Serial.println("connection failed");
  }
}

void loop()
{
  if (client.available()) {
      char c = client.read();
      Serial.print(c); /
      }

  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    for(;;)
      ;
  }
}

Unfortunately, with this code I can only read the stream on the Serial Monitor but I'm not able to correctly catch the full message and store it into a string.
There isn't any special character used to communicate the end of the message.

The full repeating message is:

$WIMWV,000.0,R,00.0,M,A*10
$WIMTA,020.0,C*29
$WIMHU,080.6,,016.6,C*02
$WIMMB,,,1001.1,B*01

They are four lines that end with and even the fourth line ends with .
I was thinking to start reading when I find the first $WIMWV and then stop when I encounter the next $WIMWV, but I do not know how to do that with code.

If you simply want to catch those 4 $WIMxx messages, then have a read of the tutorial I linked to back in post #31. Example 2 shows how to read a message with start and end markers - your start marker would be the $ and your end marker could be either the CR or LF character (10 or 13).

That code should capture the whole message into a null terminated c string. You can then do what you like with it.

1 Like

At the moment, I came up with this solution.
I'm perfectly aware that this is a very "stupid" and not smart solution because of the string memory management since I used multiple times strcpy and strcat, but it seems that it works.


#include <Ethernet.h>
#include <SPI.h>

byte mac[] = { 0xBE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 100 };
byte server[] = { 192, 168, 1, 200 }; // Touchberry Pi Server
int tcp_port = 4196;
int counter = 0;

EthernetClient client;

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

      // variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;
char WIMMB[32]; 
char WIMWV[32]; 
char WIMTA[32];
char WIMHU[32];

boolean newData = false;

//============

void setup() {
    Serial.begin(9600);
    Ethernet.begin(mac, ip);
    delay(1000);

  Serial.println("Connecting...");
  if (client.connect(server, tcp_port)) { // Connection to server.js
    Serial.println("Connected!");
    client.println();
  } else {
    Serial.println("Connection failed");
  }
}

//============

void loop() {
       
       recvWithStartEndMarkers();
       if (newData == true && counter < 4) {
       strcpy(tempChars, receivedChars);
               
         if (strcasestr(tempChars, "WIMWV")) { 
         strcpy(WIMWV, tempChars);
         strcat(WIMWV,";");
         counter++;
         Serial.println(WIMWV); 
         }
         if (strcasestr(tempChars, "WIMTA")) { 
         strcpy(WIMTA, tempChars);
         strcat(WIMTA,";"); 
         counter++;
         Serial.println(WIMTA);
         }
         if (strcasestr(tempChars, "WIMHU")) { 
         strcpy(WIMHU, tempChars); 
         strcat(WIMHU,";");
         counter++; 
         Serial.println(WIMHU); 
         }
         if (strcasestr(tempChars, "WIMMB")) { 
         strcpy(WIMMB, tempChars); 
         strcat(WIMMB,";"); 
         Serial.println(WIMMB); 
         counter++;
         }
                  
       // parseData();
       // showParsedData();
        newData = false;
    }
       else{
         String wind_sensor;
         wind_sensor.concat(WIMWV);
         wind_sensor.concat(WIMTA);
         wind_sensor.concat(WIMHU);
         wind_sensor.concat(WIMMB);
         Serial.println(wind_sensor);
         }
    delay(1000);
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '$';
    char endMarker = '\n';
    char rc;

    if (client.available()){
    while (newData == false) {
        rc = client.read();
        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
    }
}

//============

void parseData() {      // split the data into its parts

    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
 
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

    strtokIndx = strtok(NULL, ",");
    floatFromPC = atof(strtokIndx);     // convert this part to a float

}

//============

//void showParsedData() {
//    Serial.print("Message ");
//    Serial.println(messageFromPC);
//    Serial.print("Integer ");
//    Serial.println(integerFromPC);
//    Serial.print("Float ");
//    Serial.println(floatFromPC);
//}

I believe that those string handling functions using ordinary null terminated c strings are perfectly fine to use as many times as you like.

From what I've read, the memory issues that you hint at more commonly associated with the String datatype, which is a different datatype to the ordinary null terminated c strings.

1 Like

Thank you for your help, @markd833! Since I'm having problems that seem to be different from the initial topic, I'm going to open a new discussion.

I can't simply do as you suggested because the whole message is made in this way:

$WIMWV,000.0,R,00.0,M,A*10\r\n
$WIMTA,020.0,C*29\r\n
$WIMHU,080.6,,016.6,C*02\r\n
$WIMMB,,,1001.1,B*01\r\n

So, if I look for $ and \n I will only catch the first line or a random line and not all the four lines.

For this reason, after having read the topic you suggested, I tried to modify it to read each line and then merge them into a String, but even if it works, then, it gives problems with the web server code because of the multiple readings.

I think that would be wise. A new topic in the networking section should hopefully attract the attention of the forum members with that field of interest.

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