I recently bought this ultrasonic anemometer off AliExpress, to replace a Davis wind cup/vane setup where I used ESPHome to read the pulses and the potentiometer resistance. It was relatively cheap and looked reasonable quality compared to others available.
It comes with instructions which are quite good, basically you power it with ~9-12V and use read some modbus registers over RS485.
The unit needs to be mounted on a vertical pole, and seems to be based on a 1.5" BSP tube (ie. 48.3mm scaffold tube). Slightly smaller tubing would work (there is some slack internally), but I wanted it to fit securely so I cut a short piece of scaffold tube and welded it to the 1" steel tubing I am using, leaving space for the cable down the middle. The plastic is fairly thin, so I only didn't tighten the nuts as much as I otherwise would have. Given the unit has a threaded cable connector in the base there's no real chance of it being shaken off the top of the pole.
![](https://blog.jingo.uk/content/images/2024/02/PXL_20240217_162434062-2.jpg)
I try and use ESPHome as much as possible, and this device is a perfect use case for it, so I wrote a configuration file and (after some fiddling)... it worked! The wind speed means the speed is displayed in km/h in Home Assistant. The direction is just a number, so you'll need to convert it to a heading separately. There's also a nice HACS compass card.
Here's my ESPHome configuration. I have found this style of RS485 board the most reliable. It handles DE/RE (driver enable/receiver enable) automatically so you just need to feed it the data. Also it has 2x LEDs (TX/RX) so you can very easily see when it's receiving data, which removes an entire layer of problem solving.
uart:
id: anemometer_uart
tx_pin: D2
rx_pin: D1
baud_rate: 9600
stop_bits: 1
modbus:
id: anemometer_modbus
uart_id: anemometer_uart
modbus_controller:
- id: anemometer_controller
address: 0xFF
modbus_id: anemometer_modbus
update_interval: 1s
sensor:
- platform: modbus_controller
modbus_controller_id: anemometer_controller
name: Wind Speed
id: wind_speed_ms
unit_of_measurement: "m/s"
device_class: wind_speed
register_type: holding
address: 0x000C
value_type: U_WORD
accuracy_decimals: 1
filters:
- multiply: 0.01
- sliding_window_moving_average:
window_size: 5
send_every: 5
- platform: modbus_controller
modbus_controller_id: anemometer_controller
name: Wind Direction
id: wind_direction
unit_of_measurement: "°"
register_type: holding
address: 0x000D
value_type: U_WORD
accuracy_decimals: 0
filters:
- multiply: 0.1
- throttle: 5s
This template sensor will record wind gusts based on the instantaneous wind speeds. I used the general meteorology standards for what a "wind gust" is:
template:
- trigger:
- platform: state
entity_id: sensor.wind_speed
sensor:
- name: "Wind Gust"
unique_id: "sensor.wind_gust"
unit_of_measurement: "kph"
state: >
{% set current_speed = states('sensor.wind_speed_2') | float %}
{% set average_speed = states('sensor.wind_speed_avg') | float %}
{% if current_speed > (average_speed + 16) and current_speed > 30 %}
{{ current_speed }}
{% else %}
0
{% endif %}
You'll need this sensor, which is a 2-minute wind speed average:
- platform: filter
name: "Wind Speed 2 Minute Average"
entity_id: sensor.wind_speed_2
filters:
- filter: time_simple_moving_average
window_size: "00:02"
precision: 2
Results
Annoyingly, there hasn't been much wind since I installed it, however it is at least giving a speed/direction output vaguely in the range I'd expect. I will update here. I intended to leave the old ones up as a comparison but in the end couldn't be bothered to sort out the cabling. I wish I had now!
Davis Vantage Pro wind sensors
For reference, here's my old ESPHome configuration with the Davis Vantage Pro equipment:
sensor:
# Davis Vantage Pro wind direction/weather vane sensor
- platform: custom
lambda: |-
auto wind_sensor = new WindDirectionSensor();
App.register_component(wind_sensor);
return {wind_sensor};
sensors:
name: "Wind Direction"
accuracy_decimals: 0
# Davis Vantage Pro tipping-bucket rain sensor
- platform: pulse_counter
pin:
number: GPIO15
mode: INPUT_PULLDOWN
unit_of_measurement: 'mm'
name: 'Rainfall'
id: rainfall
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
internal_filter: 13us
filters:
- multiply: 0.04233 # 0.254ml / 6 (the update interval fraction)
- debounce: 2s
update_interval: 10s
# Davis Vantage Pro wind speed sensor
- platform: pulse_counter
pin:
number: GPIO19
mode: INPUT_PULLUP
unit_of_measurement: 'mph'
name: 'Wind speed'
id: wind_speed
count_mode:
rising_edge: DISABLE
falling_edge: INCREMENT
internal_filter: 13us
filters:
- multiply: 0.07440 # 1 pulse per second = 1m/s / 2.23694 (to get mph) / 6 (the update interval fraction)
- debounce: 100ms
update_interval: 10s
accuracy_decimals: 0
And the referenced "WindDirectionSensor.h" component. Be aware that the analogue inputs of the ESP32 are not terribly linear, it would be much better to use an external I2C ADC, or at least calibrate it by setting the vane to various positions and recording the result. Also I'm sure running the 3.3V over a long cable is not a great way to do it either! It did seem to work "good enough" though.
#include "esphome.h"
#include "math.h"
#define WindVanePin (34) // The pin the Davis Vantage direction/vane sensor is connected to
int VaneValue; // raw analog value from wind vane
int Direction; // translated 0 - 360 direction
int LastValue; // last direction value
class WindDirectionSensor : public PollingComponent, public Sensor {
public:
// constructor
WindDirectionSensor() : PollingComponent(10000) {}
void setup() override {
LastValue = 0;
Direction = 0;
}
void update() override {
//ESP_LOGD("custom", "update");
getWindDirection();
// Only update the display if change greater than 5 degrees.
if(abs(Direction - LastValue) > 5) {
LastValue = Direction;
}
ESP_LOGD("custom", "Direction %d", Direction );
publish_state(Direction);
}
// Get Wind Direction as degrees
void getWindDirection() {
VaneValue = analogRead(WindVanePin);
Direction = map(VaneValue, 0, 4096, 0, 359);
if(Direction > 360)
Direction = Direction - 360;
if(Direction < 0)
Direction = Direction + 360;
ESP_LOGD("custom", "VaneValue %d", VaneValue );
}
};