My 20 year old Davis Vantage Pro2 died a decade ago and I thought I would resurrect it to help automate Home assistant tasks based on the weather. I had to replace the super capacitor (used a 20F) and the Temp/Humidity unit. I plugged the console USB into HA and it sort of worked but the transmitter was very patchy even in close proximity – I assume it had also degraded and was only catching about one packet in five.

The plan
The sensors on a Vantage Pro2 are surprisingly simple. The anemometer is a reed switch that closes once a revolution, plus a 20 kΩ potentiometer for the vane. The rain gauge is another reed switch on the tipping bucket. The solar sensor puts out a voltage proportional to sunlight. Only the temperature/humidity board is clever, and that’s the one you don’t want to touch (more below).
So the new setup is an ESP32 in the ISS box counting the two reed switches, an ADS1115 converter reading the vane and the solar sensor, and an Adafruit SHT45 in the radiation shield in place of the Davis temperature board (Giving higher accuracy as well). It reports to Home Assistant over Wi-Fi and runs off 5 V USB, so no radio, no console, no supercap and no CR123A. Every sensor keeps its own Davis cable and RJ11 plug, and the old SIM board stays in the box in case I ever want to go back. Only downside is the power draw is higher than the original ISS but easily dealt with with a small battery and solar panel.
Breadboard first
Before ordering anything I built the whole circuit on a breadboard and tested each sensor in turn. A few things came out of that.
The anemometer – Davis quote 2.25 mph per pulse per second, which works out at 3.621 km/h per Hz. The vane is linear: four 90° steps read 0.244, 0.260, 0.251 and 0.245 of full scale. Reading it as a ratio of the wiper to its own supply cancels out any supply drift. There’s a dead band of a few degrees at north where the wiper leaves the track and the reading wanders, so the firmware clamps it and takes a median.
The rain gauge was the surprise. The reed switch closes twice every time the bucket tips, about 0.1 to 0.4 seconds apart, so my first 100 ms debounce counted every tip twice. A 750 ms lockout fixed it and still copes with rain far heavier than anything real (around 960 mm/h). A closure now has to last at least 20 ms before it counts.
The board
With the breadboard working I drew a carrier board in KiCad. The ESP32 DevKit and the ADS1115 plug into sockets, three RJ11 jacks take the Davis plugs, and the rest is a handful of resistors, capacitors and diodes. Five boards (min order) from JLCPCB cost a few euros plus shipping – proved incredibly easy to do and arrived as promised within 10 days.

| Qty | Part | Use |
|---|---|---|
| 1 | ESP32 DevKit V1, 30-pin | controller |
| 1 | Adafruit ADS1115, STEMMA QT (1085) | vane and solar, 16-bit |
| 1 | Adafruit SHT45 with PTFE membrane (6174), 400 mm STEMMA QT cable | temperature and humidity |
| 3 | RJ11 6P6C PCB jack, SparkFun PRT-00132 | WIND, RAIN, SUN |
| 5 | 1N5817 Schottky diode | 4 input clamps, 1 solar supply drop |
| 5 + 2 | 1 kΩ + 10 kΩ, ¼ W | series protection, pull-ups |
| 2 + 2 | 10 nF + 100 nF ceramic | input filters, decoupling |
| Female headers: 1×15 ×2, 1×6 ×2 | sockets for the ESP32 and ADS1115 | |
| 1 | Carrier PCB (Gerbers below) | 58.4 × 88.9 mm, 2-layer, through-hole |
The modules and connectors came to a little over €40 from Kiwi Electronics; the resistors, capacitors and headers came out of a cheap assortment kit.
| Sensor | Wire | Function | ESP32 side |
|---|---|---|---|
| Wind (6410) | black | speed reed, 1 pulse per revolution | D27: 10 k pull-up, 1 k series, 10 nF, two 1N5817 clamps |
| red | common | GND | |
| green | vane wiper | ADS1115 A0 via 1 k | |
| yellow | vane supply | ADS1115 A+, sensed on A1 via 1 k | |
| Rain | red, green+yellow | reed switch | D26: same input circuit as wind, red to GND |
| Solar (6450) | yellow | supply, 3 V ±10 % | 3V3 through a 1N5817: 3.14 V at 0.67 mA |
| green | 1.67 mV per W/m² | ADS1115 A2 via 1 k | |
| red, black | ground | GND | |
| SHT45 | STEMMA QT cable into the ADS1115 | I²C 0x44 | D21 SDA, D22 SCL, shared with the ADS1115 at 0x48 |

Gotchas
- Don’t wire the Davis temperature/humidity board (7346.070) up as I²C. It reportedly uses Sensirion’s old SHT1x “Sensibus” protocol, and at least one person has cooked theirs trying. The SHT45 costs about €15 and has a better accuracy spec anyway. I have put mine in the housing underneath the rain gauge and it seems to work fine. The Davis replacement is over 70 Euro.
- The ADS1115’s A+ and A− pins are supply outputs, not inputs. The vane’s supply comes from A+, so the rain gauge in the wind jack would short the supply on every tip. The jacks are labelled, but unplug the power before swapping plugs.
Building it
- Resistors, diodes and capacitors first (diode band to the square pad), then the sockets, using the modules as jigs, then the jacks.
- On the bare board, check 3V3 to GND isn’t shorted.
- Flash ESPHome over USB and add the device in Home Assistant. Temperature and wind direction should show values; if not, check I²C (SHT45 at 0x44, ADS1115 at 0x48).
- Power off, plug in the sensors, power on.
The firmware
The ESPHome config below has the same sensor logic I tested on the bench, plus the Home Assistant connection, a rain total that survives restarts, and a north offset for the vane. It compiles on ESPHome 2026.9.1. Set north_offset to the bearing the anemometer arm points to (0 if it points north, as Davis recommend).
# Davis Vantage Pro2 ISS read directly by an ESP32 (no SIM board, no radio)## Carrier PCB: ESP32 DevKit V1 (30-pin), Adafruit ADS1115 (1085) at 0x48, Adafruit SHT45 at 0x44.# Pins: D27 wind speed, D26 rain, D21 SDA, D22 SCL. ADS1115: A0 vane wiper, A1 vane supply, A2 solar.# Settings proven on the bench (Oct 2026): wind 1 ms pulse filter; rain 20 ms minimum closure plus a# 750 ms lockout (the rain reed closes twice per tip, 0.11-0.36 s apart).substitutions: device_name: davis-iss friendly_name: Davis ISS # Bearing the anemometer arm points to (0 if it points north, as Davis recommends). north_offset: "0" rain_lockout_ms: "750"esphome: name: ${device_name} friendly_name: ${friendly_name} on_boot: priority: -100 then: - lambda: |- id(rain_total).publish_state(id(rain_tip_count) * 0.2f); id(rain_rate).publish_state(0);esp32: board: esp32dev framework: type: esp-idflogger: level: INFOapi: encryption: key: !secret api_encryption_keyota: - platform: esphomewifi: ssid: !secret wifi_ssid password: !secret wifi_password ap: ssid: ${friendly_name} Fallback password: !secret fallback_ap_passwordcaptive_portal:i2c: sda: GPIO21 scl: GPIO22 frequency: 100kHzads1115: - address: 0x48 id: adsglobals: # Rain tips since first flash; survives restarts. - id: rain_tip_count type: uint32_t restore_value: true initial_value: "0" - id: rain_last_tip_ms type: uint32_t initial_value: "0" - id: rain_closures_seen type: float initial_value: "0"sensor: # ---- Wind speed: reed switch, one pulse per revolution ---- - platform: pulse_meter id: wind_speed name: Wind speed pin: number: GPIO27 inverted: true mode: input: true pullup: true # Closed and open for at least 1 ms to count: ignores bounce. ~1.6 ms closure at 200 mph. internal_filter: 1ms internal_filter_mode: PULSE timeout: 10s unit_of_measurement: km/h device_class: wind_speed state_class: measurement accuracy_decimals: 1 # Davis: 2.25 mph per Hz = 3.621 km/h per Hz. pulse_meter reports pulses per minute. filters: - multiply: 0.060352 # ---- Rain: reed switch, 0.2 mm per tip ---- # The pulse meter counts closures of at least 20 ms (timed in the interrupt); the lambda then drops # any closure within the lockout of the last counted tip. - platform: pulse_meter id: rain_closures internal: true pin: number: GPIO26 inverted: true mode: input: true pullup: true internal_filter: 20ms internal_filter_mode: PULSE timeout: 15min total: id: rain_closures_total internal: true on_value: - lambda: |- float seen = id(rain_closures_seen); id(rain_closures_seen) = x; if (x <= seen) return; uint32_t now = millis(); uint32_t since = now - id(rain_last_tip_ms); if (id(rain_last_tip_ms) != 0 && since < ${rain_lockout_ms}) return; if (id(rain_last_tip_ms) != 0) id(rain_rate).publish_state(0.2f * 3600000.0f / since); // Davis-style rate id(rain_tip_count) += 1; id(rain_last_tip_ms) = now; id(rain_total).publish_state(id(rain_tip_count) * 0.2f); - platform: template id: rain_total name: Rain total unit_of_measurement: mm device_class: precipitation state_class: total_increasing accuracy_decimals: 1 update_interval: never - platform: template id: rain_rate name: Rain rate unit_of_measurement: mm/h device_class: precipitation_intensity state_class: measurement accuracy_decimals: 1 update_interval: never # ---- Wind direction: vane pot read as a ratio (A0 wiper / A1 supply), so supply drift cancels ---- - platform: ads1115 ads1115_id: ads id: vane_wiper multiplexer: A0_GND gain: 4.096 update_interval: never internal: true - platform: ads1115 ads1115_id: ads id: vane_supply multiplexer: A1_GND gain: 4.096 update_interval: never internal: true - platform: template id: wind_direction name: Wind direction unit_of_measurement: "°" state_class: measurement accuracy_decimals: 0 update_interval: never lambda: |- float s = id(vane_supply).state, w = id(vane_wiper).state; if (std::isnan(s) || std::isnan(w) || s < 1.0f) return NAN; return std::min(std::max(w / s, 0.0f), 1.0f); # The pot has a few-degree gap at north where the wiper floats and reads noisy: a median of 3 # removes the odd outlier. filters: - median: window_size: 3 send_every: 1 - lambda: return fmodf(x * 360.0f + ${north_offset} + 360.0f, 360.0f); # ---- Solar radiation: Davis 6450, 1.67 mV per W/m², supply 3V3 through a 1N5817 (~3.1 V) ---- - platform: ads1115 ads1115_id: ads id: solar_volts multiplexer: A2_GND gain: 4.096 update_interval: 10s internal: true - platform: copy source_id: solar_volts name: Solar radiation unit_of_measurement: W/m² device_class: irradiance state_class: measurement accuracy_decimals: 0 filters: - lambda: return std::max(x / 0.00167f, 0.0f); - sliding_window_moving_average: window_size: 6 send_every: 6 # ---- Temperature and humidity: SHT45 in the Davis radiation shield ---- - platform: sht4x address: 0x44 precision: High update_interval: 30s temperature: name: Temperature accuracy_decimals: 1 humidity: name: Humidity accuracy_decimals: 1 - platform: wifi_signal name: Wi-Fi signal update_interval: 60s - platform: uptime name: Uptimeinterval: # Read the vane's two channels back to back, then work out the direction. - interval: 2s then: - component.update: vane_wiper - component.update: vane_supply - component.update: wind_direction # Rain rate falls back to 0 after 15 min without a tip. - interval: 60s then: - lambda: |- if (id(rain_last_tip_ms) != 0 && millis() - id(rain_last_tip_ms) > 15UL * 60UL * 1000UL && id(rain_rate).state != 0.0f) id(rain_rate).publish_state(0);
Where it’s at
The board is built and all four sensors have been tested on it on the bench; It’s reporting into Home Assistant consistently via the native ESP32 integration. Much slicker and more controllable than the old USB integration. The Console is in the cupboard.
Gerbers (v0.2) – 2-layer, 1.6 mm FR-4, any fab.
Acknowledgements
This stands on other people’s work. Thanks to:
- rainx, for the Direct Davis Vantage receiver (868 MHz) via ESPHome + CC1101 guide on the Home Assistant forum. It was my starting point, and it’s still the way to go if your ISS transmitter is healthy.
- dekay, for the DavisRFM69 message protocol notes, and Paul Wieland for esphome-davis-vantage-rx. Between them they got my first attempt, an ESP32 radio receiver in place of the console, working.
- previmeteo, whose gprs-davis-datalogger showed that the Davis wind, vane, rain and solar sensors can be read directly.
- awszac, whose weather station blog warns that the Davis temperature/humidity board isn’t I²C. That kept mine in one piece.
- The Home Assistant forum threads on the Davis anemometer and wind direction with ESPHome, plus ON7EQ’s ESP32 Davis wind notes and blog.jingo.uk, for the pulse counting and the advice to use an external ADC for the vane.
- SparkFun and Adafruit, for publishing their board designs. The RJ11 jack and ADS1115 footprints came straight from them.
Header photo: “Davis Instruments weather station” by Cjp24, via Wikimedia Commons, licensed under CC BY-SA 4.0. Unmodified.

Leave a Reply