Before order, please ensure you know how to develop the software to collect the data. What we can support only is to provide the communication protocol to you.
First of all, the forum is not a design shop or a coding shop. You are expected to make a swerious effort and when yiou get stuck a helper will give you a hint.
the WH65L appears to have a RS485 interface therefore you require a TTL-RS485 converter as in the link - it can be powered from 3.3V therefore should interface to the ESP32 3.3V logic OK
if working with RS485 I find it useful to have a USB-RS485 module so a PC can be used to test the RS485 bus and monitor data flow
simple ESP32 test program to communicate with TTL-RS485 module
// ESP32 Serial1 to RS485 bus
//
// see https://microcontrollerslab.com/rs485-serial-communication-arduino-tutorial/
#define RS485Serial Serial1 // hardware serial port on ESP32
// RS485 VCC ESP32 to to 3.3V
#define RXD2 16 // ESP32 Serial1 Receive pin 16 to RS485 RO (Receiver Output) /RXD
#define TXD2 17 // ESP32 Serial1 Transmit pin 17 to RS485 DI (Driver Input) /TXD
// some RS485 modules automatically switch between transmit and receive DE/RE not defined
// RS485 DE (Driver Enable set HIGH to enable) and RE (Receiver Enable set LOW to enable) to ESP32 pins 18 and 19
//#define DE //RS485 Direction control pin
//#define RE //RS485 Direction control pin
#define RS485Transmit HIGH
#define RS485Receive LOW
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n\nESP32 connect to RS485 bus - enter/receive text");
#ifdef DE // if DE and RE are defined
pinMode(DE, OUTPUT);
pinMode(RE, OUTPUT);
digitalWrite(DE, RS485Receive); // Disable RS485 Transmit
digitalWrite(RE, RS485Receive); // Disable RS485 Transmit
#endif
RS485Serial.begin(9600, SERIAL_8N1, RXD2, TXD2); // set the RS485 data rate
}
// loop sending data to RS485 and receiving data
void loop() {
if (Serial.available()) { // Arduino Serial data avaliable?
#ifdef DE // if DE and RE are defined
digitalWrite(DE, RS485Transmit); // Enable RS485 Transmit
digitalWrite(RE, RS485Transmit); // Enable RS485 Transmit
#endif
RS485Serial.write(Serial.read()); // Send byte to Remote RS485
RS485Serial.flush(); // wait for byte to be transmitted
#ifdef DE // if DE and RE are defined
digitalWrite(DE, RS485Receive); // Disable RS485 Transmit
digitalWrite(RE, RS485Receive); // Disable RS485 Transmit
#endif
}
if (RS485Serial.available()) // RS485 serial data available?
Serial.write(RS485Serial.read()); // read character and display it
}
some TTL-RS485 modules have RE and DE pins to enable/disable the transmit and receive circuits when switching the bus between transmit and receive (RS485 is simplex)
the TTL-485 module in your link switches automatically and does not have RE/DE pins therefore you can ignore them
Yes, I used this converter to read water levels; it used the Modbus protocol.
If I want to read data from the weather station, do I need to use it again?
Could you take a look at the schematic?
I'll try your code when I receive the station.
looping reading single bytes until you get 25 fails if you start reading in the middle of a frame
probably simpler to attempt to read a frame of 25 bytes using Serial.readBytes(buffer, length) which returns the number of bytes read (or 0 if timeout)
if you start the program reading in the middle of a frame it will return the wrong count which you can ignore
e.g. this reads a frame of 10 bytes
// ESP32 Serial1 test - read array of 10 bytes
#define RXD1 16 // can map Serial1 and Serial2 to many ESP32 GPIO pins
#define TXD1 17 // check pin usage https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
void setup() {
// initialize both serial ports:
Serial.begin(115200);
Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1);
Serial.printf("\n\nESP32 serial1 test RXD1 pin %d TXD1 pin %d\n", RXD1, TXD1);
Serial.printf(" loopback test connect pin %d to pin %d\n", RXD1, TXD1);
}
void loop() {
// read from Serial1, send to Serial
if (Serial1.available()) {
byte data[50] = { 0 }, count = 0;
// attempt to read 10 bytes - will timeout after 1 second returning 0
// Serial.readBytes(buffer, length)
if ((count = Serial.readBytes(data, 10)) == 10) {
// 10 bytes read display
Serial.printf("Read text %s\n", data);
for (int i = 0; i < 10; i++)
Serial.printf(" 0x%02x", data[i]);
Serial.println();
} else // if not 10 bytes read error
if (count > 0) // ignor timeout
Serial.printf("ERROR readBytes read %d bytes\n", count);
}
// read from Serial, send to Serial1
while (Serial.available()) {
int inByte = Serial.read();
//Serial.write(inByte); // local echo if required
Serial1.write(inByte);
}
}
entering frames of various length serial monitor displays
horace I've connected the station and received a byte frame. I don't know how to decode the byte frame. I'd like to start by reading the first value.
Do I understand correctly that the first value is the wind direction, and the third byte?
wind direction - value in hex range 0° - 359°
#include <SoftwareSerial.h>
const byte rxPin = 5;
const byte txPin = 4;
SoftwareSerial mySerial(rxPin, txPin);
const byte bufferSize = 25;
byte data[50] = {0};
byte count = 0;
void setup()
{
Serial.begin(115200);
mySerial.begin(9600);
}
void loop()
{
if (mySerial.available())
{
// attempt to read 25 bytes - will timeout after 1 second returning 0
// Serial.readBytes(buffer, length)
if ((count = mySerial.readBytes(data, bufferSize)) == bufferSize)
{
// 25 bytes read display
Serial.printf("Read bytes \n");
for (int i = 0; i < bufferSize; i++)
{
Serial.printf(" 0x%02x", data[i]);
}
Serial.println("\n");
Serial.printf("Received %d bytes", count);
}
else // if not 25 bytes read error
{
if (count > 0)
{
Serial.printf("ERROR readBytes read %d bytes\n", count);
}
}
}
}
Yes, the example Horace gave was very helpful. You need to calculate the remaining values based on this, summing the remaining bytes according to the documentation.