icon

How to use wind speed/direction transmitter on Arduino and micro:bit? ——RS485 to UART

0 21326 Medium

Background

Some time ago, a friend of mine wanted to do a weather station project, but the interfaces of the wind speed transmitter and wind direction transmitter he chose were not compatible with Arduino and micro:bit. So he asked if I had any solution.

 

RS485 Wind Speed Transmitter

 

When I saw the picture he sent, one idea came to my mind. One RS485 to UART Signal Adapter Module(https://www.dfrobot.com/product-2392.html) is a perfect solution to his problem.  

Because the wind direction transmitter and wind speed transmitter are RS485 interfaces, and the protocol is Modbus protocol and the RS485 to UART adapter can just convert the RS485 into UART output.

 

Now I will share how to use wind direction transmitter and wind speed transmitter on Arduino and micro:bit controller.

First, we connect the wind direction transmitter and wind speed transmitter to the Gravity: RS485 to UART active isolated signal conversion module according to the following figure.

Note: The wiring method of the wind direction transmitter and the wind speed transmitter is the same.

 

How to use it on Arduino uno

 

Measure wind direction

Software and hardware preparation

Hardware:

HARDWARE LIST
1 DFRduino UNO R3 with IO Expansion Shield and USB Cable A-B
1 RS485 Wind Direction Transmitter
1 Gravity: Active Isolated RS485 to UART Signal Adapter Module

Software:

 

· Arduino IDE Click to download Arduino IDE: (https://www.arduino.cc/en/software)

· MIND+ Click to download mindplus(http://mindplus.cc/download-en.html)

 

 

Hardware connection

Arduino IDE - Sample Code

1. Connect the wind direction transmitter, RS485 to UART module, and uno R3 together according to the diagram above.

2. Open the Arduino IDE and upload the code below to the DFRduino uno R3.

3. Open the serial port, adjust the baud rate to 115200, and observe the result through the serial port.

4. The direction corresponding to the number.

CODE
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //Define the soft serial port, port 3 is TX, port 2 is RX,

uint8_t Address = 0x03;

void setup()
{
   Serial.begin(115200);
   mySerial.begin(9600);
   // ModifyAddress(0x00, Address); //Modify device address, please comment out this sentence after modifying the address and power on again.
}

void loop()
{
   Serial.println(readWindDirection(Address)); //Read the wind direction
   delay(1000);
}


size_t readN(uint8_t *buf, size_t len)
{
   size_t offset = 0, left = len;
   int16_t Tineout = 1500;
   uint8_t *buffer = buf;
   long curr = millis();
   while (left) {
     if (mySerial.available()) {
       buffer[offset] = mySerial.read();
       offset++;
       left--;
     }
     if (millis() - curr > Tineout) {
       break;
     }
   }
   return offset;
}


/**
   @brief      Calculate CRC16_2 check value
   @param buf      Packet for calculating the check value
   @param len      Check the date length
   @return      Return a 16-bit check result
*/
uint16_t CRC16_2(uint8_t *buf, int16_t len)
{
   uint16_t crc = 0xFFFF;
   for (int pos = 0; pos < len; pos++)
   {
     crc ^= (uint16_t)buf[pos];
     for (int i = 8; i != 0; i--)
     {
       if ((crc & 0x0001) != 0)
       {
         crc >>= 1;
         crc^= 0xA001;
       }
       else
       {
         crc >>= 1;
       }
     }
   }

   crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
   return crc;
}


/**
   @brief	 Add a CRC_16 check to the end of the packet
   @param buf 		Packet that needs to add the check value
   @param len 		Length of data that needs to add the check 
   @return 		None
*/
void addedCRC(uint8_t *buf, int len)
{
   uint16_t crc = 0xFFFF;
   for (int pos = 0; pos < len; pos++)
   {
     crc ^= (uint16_t)buf[pos];
     for (int i = 8; i != 0; i--)
     {
       if ((crc & 0x0001) != 0)
       {
         crc >>= 1;
         crc^= 0xA001;
       }
       else
       {
         crc >>= 1;
       }
     }
   }
   buf[len] = crc % 0x100;
   buf[len + 1] = crc / 0x100;
}


/**
   @brief 		Read wind direction
   @param Address 	The read device address.
   @return 		Wind direction unit m/s, return -1 for read timeout.
*/

int readWindDirection(uint8_t Address)
{
   uint8_t Data[7] = {0}; //Store the original data packet returned by the sensor
   uint8_t COM[8] = {0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; // Command of reading wind direction
   boolean ret = false; //Wind direction acquisition success flag
   int WindDirection = 0;
   long curr = millis();
   long curr1 = curr;
   uint8_t ch = 0;
   COM[0] = Address; //Add the complete command package with reference to the communication protocol.
   addedCRC(COM , 6); //Add CRC_16 check for reading wind direction command packet
   mySerial.write(COM, 8); //Send the command of reading the wind direction

   while (!ret) {
     if (millis() - curr > 1000) {
       WindDirection = -1; //If the wind direction has not been read for more than 1000 milliseconds, it will be regarded as a timeout and return -1.
       break;
     }

if (millis() - curr1 > 100) {
       mySerial.write(COM, 8); //If the last command to read the wind direction is sent for more than 100 milliseconds and the return command has not been received, the command to read the wind direction will be re-sent
       curr1 = millis();
     }

     if (readN(&ch, 1) == 1) {
       if (ch == Address) { //Read and judge the packet header.
         Data[0] = ch;
         if (readN(&ch, 1) == 1) {
           if (ch == 0x03) { //Read and judge the packet header.
             Data[1] = ch;
             if (readN(&ch, 1) == 1) {
               if (ch == 0x02) { //Read and judge the packet header.
                 Data[2] = ch;
                 if (readN(&Data[3], 4) == 4) {
                   if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) { //Check data packet
                     ret = true;
                     WindDirection = Data[3] * 256 + Data[4]; //Calculate the wind direction
                   }
                 }
               }
             }
           }
         }
       }
     }
   }
   return WindDirection;
}


/**
  @brief 	Modify the sensor device address
  @param Address1 	The address of the device before modification. Use the 0x00 address to set any address, after setting, you need to re-power on and restart the module.
  @param Address2 	The modified address of the device, the range is 0x00~0xFF,
  @return 		Returns true to indicate that the modification was successful, and returns false to indicate that the modification failed.
*/

boolean ModifyAddress(uint8_t Address1, uint8_t Address2)
{
  uint8_t ModifyAddressCOM[11] = {0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00};
  boolean ret = false;
  long curr = millis();
  long curr1 = curr;
  uint8_t ch = 0;
  ModifyAddressCOM[0] = Address1;
  ModifyAddressCOM[8] = Address2;
  addedCRC(ModifyAddressCOM , 9);
  mySerial.write(ModifyAddressCOM, 11);
  while (!ret) {
    if (millis() - curr > 1000) {
      break;
    }

    if (millis() - curr1 > 100) {
      mySerial.write(ModifyAddressCOM, 11);
      curr1 = millis();
    }

    if (readN(&ch, 1) == 1) {
      if (ch == Address1) {
        if (readN(&ch, 1) == 1) {
          if (ch == 0x10 ) {
            if (readN(&ch, 1) == 1) {
              if (ch == 0x10) {
                if (readN(&ch, 1) == 1) {
                  if (ch == 0x00) {
                    if (readN(&ch, 1) == 1) {
                      if (ch == 0x00) {
                        if (readN(&ch, 1) == 1) {
                          if (ch == 0x01) {
                            while (1) {
                              Serial.println("Please power on the sensor again.");
                              delay(1000);
                            }
                            ret = true ;
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  return ret;
}

Effect Display:

Notice: The white dot on the sensor must face due north during installation. As shown below:

 

The result printed by the serial port is 13 (west-northwest)

The corresponding direction of the mobile phone is west-northwest, which is almost the same.

Mind+ —— Sample Code

1. Open mind+, add the main control board - Arduino Uno, and then go to the user library to add - wind direction transmitter library.

 

 

2. Upload the code below to the DFRduino uno R3.

3. Open the serial port, adjust the baud rate to 9600, and observe the results through the serial port.

 

Effect Display:

The result printed by the serial port shows North.

 

The corresponding direction of the mobile phone is north, which is consistent.

 

Measure wind speed

 

Software and hardware preparation

Hardware:

HARDWARE LIST
1 Measure wind speed Software and hardware preparation Hardware:
1 RS485 Wind Speed Transmitter
1 Gravity: Active Isolated RS485 to UART Signal Adapter Module

Software:

 

· Arduino IDE Click to download Arduino IDE: (https://www.arduino.cc/en/software)

· MIND+ Click to download mindplus(http://mindplus.cc/download-en.html)

 

Hardware Connection

 

Arduino IDE - Sample Code

1. Connect the wind speed transmitter, RS485 to UART module, and Uno R3 together according to the diagram above.

2. Open the Arduino IDE and upload the code below to the DFRduino uno R3.

3. Open the serial port, adjust the baud rate to 115200, and observe the result through the serial port.

 

 

CODE
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //Define the soft serial port, port 3 is TX, port 2 is RX,

uint8_t Address = 0x10;


void setup()
{
   Serial.begin(115200);
   mySerial.begin(9600);
  ModifyAddress(0x00, Address); //Modify device address, please comment out this sentence after modifying the address and power on again.
}

void loop()
{
   Serial.print(readWindSpeed(Address)); //Read wind speed
   Serial.println("m/s");
   delay(1000);
}


size_t readN(uint8_t *buf, size_t len)
{
   size_t offset = 0, left = len;
   int16_t Tineout = 1500;
   uint8_t *buffer = buf;
   long curr = millis();
   while (left) {
     if (mySerial.available()) {
       buffer[offset] = mySerial.read();
       offset++;
       left--;
     }
     if (millis() - curr > Tineout) {
       break;
     }
   }
   return offset;
}


/**
   @brief 	Calculate CRC16_2 check value
   @param buf 		Packet for calculating the check value
   @param len 		Length of data that needs to check
   @return 		Return a 16-bit check result.
*/
uint16_t CRC16_2(uint8_t *buf, int16_t len)
{
   uint16_t crc = 0xFFFF;
   for (int pos = 0; pos < len; pos++)
   {
     crc ^= (uint16_t)buf[pos];
     for (int i = 8; i != 0; i--)
     {
       if ((crc & 0x0001) != 0)
       {
         crc >>= 1;
         crc^= 0xA001;
       }
       else
       {
         crc >>= 1;
       }
     }
   }

   crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
   return crc;
}


/**
   @brief  Adds a CRC_16 check to the end of the packet
   @param buf 		Data packet that needs to add the check value
   @param len 		Length of data that needs to add check
   @return 		None
*/
void addedCRC(uint8_t *buf, int len)
{
   uint16_t crc = 0xFFFF;
   for (int pos = 0; pos < len; pos++)
   {
     crc ^= (uint16_t)buf[pos];
     for (int i = 8; i != 0; i--)
     {
       if ((crc & 0x0001) != 0)
       {
         crc >>= 1;
         crc^= 0xA001;
       }
       else
       {
         crc >>= 1;
       }
     }
   }
   buf[len] = crc % 0x100;
   buf[len + 1] = crc / 0x100;
}


/**
   @brief 	Read the wind speed
   @param Address 	The read device address
   @return 		Wind speed unit m/s, return -1 for read timeout
*/

float readWindSpeed(uint8_t Address)
{
   uint8_t Data[7] = {0}; //Store the original data packet returned by the sensor
   uint8_t COM[8] = {0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; //Command for reading wind speed
   boolean ret = false; //Wind speed acquisition success flag
   float WindSpeed = 0;
   long curr = millis();
   long curr1 = curr;
   uint8_t ch = 0;
   COM[0] = Address; //Add the complete command package with reference to the communication protocol.
   addedCRC(COM , 6); //Add CRC_16 check for reading wind speed command packet
   mySerial.write(COM, 8); //Send the command of reading the wind speed

   while (!ret) {
     if (millis() - curr > 1000) {
       WindSpeed = -1; //If the wind speed has not been read for more than 1000 milliseconds, it will be regarded as a timeout and return -1.
       break;
     }

if (millis() - curr1 > 100) {
       mySerial.write(COM, 8); //If the last command to read the wind speed is sent for more than 100 milliseconds and the return command has not been received, the command to read the wind speed will be re-sent
       curr1 = millis();
     }

     if (readN(&ch, 1) == 1) {
       if (ch == Address) { //Read and judge the packet header.
         Data[0] = ch;
         if (readN(&ch, 1) == 1) {
           if (ch == 0x03) { //Read and judge the packet header.
             Data[1] = ch;
             if (readN(&ch, 1) == 1) {
               if (ch == 0x02) { //Read and judge the packet header.
                 Data[2] = ch;
                 if (readN(&Data[3], 4) == 4) {
                   if (CRC16_2(Data, 5) == (Data[5] * 256 + Data[6])) { //Check data packet
                     ret = true;
                     WindSpeed = (Data[3] * 256 + Data[4]) / 10.00; //Calculate the wind speed
                   }
                 }
               }
             }
           }
         }
       }
     }
   }
   return WindSpeed;
}


/**
   @brief 	Modify the sensor device address
   @param Address1 	The address of the device before modification. Use the 0x00 address to set any address, after setting, you need to re-power on and restart the module.
   @param Address2 	The modified address of the device, the range is 0x00~0xFF,
   @return 		Returns true to indicate that the modification was successful, and returns false to indicate that the modification failed.
*/

boolean ModifyAddress(uint8_t Address1, uint8_t Address2)
{
   uint8_t ModifyAddressCOM[11] = {0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00};
   boolean ret = false;
   long curr = millis();
   long curr1 = curr;
   uint8_t ch = 0;
   ModifyAddressCOM[0] = Address1;
   ModifyAddressCOM[8] = Address2;
   addedCRC(ModifyAddressCOM , 9);
   mySerial.write(ModifyAddressCOM, 11);
   while (!ret) {
     if (millis() - curr > 1000) {
       break;
     }

if (millis() - curr1 > 100) {
      mySerial.write(ModifyAddressCOM, 11);
      curr1 = millis();
    }

    if (readN(&ch, 1) == 1) {
      if (ch == Address1) {
        if (readN(&ch, 1) == 1) {
          if (ch == 0x10 ) {
            if (readN(&ch, 1) == 1) {
              if (ch == 0x10) {
                if (readN(&ch, 1) == 1) {
                  if (ch == 0x00) {
                    if (readN(&ch, 1) == 1) {
                      if (ch == 0x00) {
                        if (readN(&ch, 1) == 1) {
                          if (ch == 0x01) {
                            // while (1) {
                            Serial.println("Please power on the sensor again.");
                            // delay(1000);
                            // }
                            ret = true ;
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  return ret;
}

Effect Display:

Push the wind speed transmitter slightly by hand and observe the data.

 

Mind+ —— Sample Code

1. Open mind+, add the controller - Arduino Uno, and then go to the user library to add the wind speed transmitter library.

2. Upload the code below to the DFRduino Uno R3.

3. Open the serial port, adjust the baud rate to 9600, and observe the results through the serial port.

 

Effect Display:

Push the wind speed transmitter slightly by hand and observe the data.

 

 

How to use it on micro:bit

 

Measure wind direction

 

Software and hardware preparation

Hardware:

HARDWARE LIST
1 micro:bit V2- an Educational & Creative Tool for Kids
1 IO Extender for micro:bit / UNIHIKER
1 RS485 Wind Direction Transmitter
1 Gravity: Active Isolated RS485 to UART Signal Adapter Module

Software:

MIND+ Click to download mindplus(http://mindplus.cc/download-en.html)

 

Hardware connection

 

Mind+ —— Sample Code

1. Open mind+, add the main controller - micro:bit, and then go to the user library to add the wind direction transmitter library.

 

2. Upload the code below to the micro:bit.

3. Open the serial port, adjust the baud rate to 9600, and observe the result through the serial port.

 

Effect Display:

Push the wind direction transmitter slightly by hand and observe the data.

 

Measure wind speed

 

Software and hardware preparation

Hardware:

 

HARDWARE LIST
1 micro:bit V2- an Educational & Creative Tool for Kids
1 IO Extender for micro:bit / UNIHIKER
1 RS485 Wind Speed Transmitter
1 Gravity: Active Isolated RS485 to UART Signal Adapter Module

Software:

MIND+ Click to download mindplus(http://mindplus.cc/download-en.html)

 

Hardware connection

Mind+ —— sample code

1. Open mind+, add the main controller - micro:bit, and then go to the user library to add the wind speed transmitter library.

 

2. Upload the code below to the micro:bit.

3. Open the serial port, adjust the baud rate to 9600, and observe the result through the serial port.

 

Effect display:

Push the wind speed transmitter slightly by hand and observe the data.

License
All Rights
Reserved
licensBg
0