Davis Wind direction Equipment and ESP Home

Hi
I have a 6410 davis equipement with DIY ESP Home weather station.
My question is about the compute of wind direction with the internal 20k pots.
Is my formula is correct and linear value too ? I read the ADC is bad at the bottom and up the 0 and 3.3V.

# Girouette - Direction du vent - Wind Direction

  - platform: adc
    id: source_sensor
    pin: GPIO34
    attenuation: 11db # to mesure 3.3V
    #internal: true
    unit_of_measurement: '°'
    name: 'Vent Direction'
    update_interval: 1s # avant 5 secondes... On passe à 1 pour test
    accuracy_decimals: 0
    filters:
      - multiply: 0.846153 # 3.9 -> 3.3V
      - calibrate_linear:
          # Map 0.0 (from sensor) to 0.0 (true value)
          - 0.1 -> 0
          - 3.2 -> 360
      - offset: 90 # set offset for physical calibration of the arm of anemometer. Si arm on North (0°) offset should be 0.
      - lambda: |-
          // Modify offset to not going up than 360°
          if (x >= 360) {
                return (x - 360.0);  
          }
          else
            return x;
    on_value:
      - if:
          condition:
            sensor.in_range:
              id: source_sensor
              above: 348.75
              below: 11.25
          then:
            - text_sensor.template.publish:
                id: wind_dir_card
                state: "N"

The pot is linear according to the data sheet so should be fine.

Thanks. Yes I know
But my interogation is about the ADC input of the ESP32 which is so quiet bad between 0 and 0.1V and 3.2 and 3.3V.
So the pots souhld change tension between 0 and 3.3V…

Hello I have been using the Davis 6410 for about 12 months with ESP32 (originally ESP8266)

It has been calibrated against two marine shipping weather stations which are within 1 km of my coastal house.

The ESP32 is indeed not linear (and if you google you will find specific data on this); however for a wind vane which swings by around 10 - 20 degrees, you will never notice it. What is more important is the location of the vane/ wind cups. I urge you to read the Davis manual on placement. My direction matches both of the professional stations.

The ESP32 breaks down ADC into 4095 increments; I use the raw data and convert that into direction. I then created a template which gives a cardinal. This all works perfectly for me.

  - platform: adc
    pin: GPIO33
    name: "Wind Direction"
    id: winddirection1
    icon: mdi:compass-rose
    unit_of_measurement: "º"
    update_interval: 10s
    accuracy_decimals: 0
    attenuation: 11db
    raw: True
    filters:
      - calibrate_linear:
          - 0.0 -> 0.0
          - 4095-> 360
      - offset: 5
      - sliding_window_moving_average:
          window_size: 20
          send_every: 6

# Cardinal Wind direction
text_sensor:
  - platform: template
    name: Cardinal Wind Direction
    lambda: |-
      if (id(winddirection1).state < 11.25 || id(winddirection1).state >= 348.75) {
        return {"N"};
      } else if (id(winddirection1).state >= 11.25 && id(winddirection1).state < 33.75) {
        return {"NNE"};
      } else if (id(winddirection1).state >= 33.75 && id(winddirection1).state < 56.25) {
        return {"NE"};
      } else if (id(winddirection1).state >= 56.25 && id(winddirection1).state < 78.75) {
        return {"ENE"};
      } else if (id(winddirection1).state >= 78.75 && id(winddirection1).state < 101.25) {
        return {"E"};
      } else if (id(winddirection1).state >= 101.25 && id(winddirection1).state < 123.75) {
        return {"ESE"};
      } else if (id(winddirection1).state >= 123.75 && id(winddirection1).state < 146.25) {
        return {"SE"};
      } else if (id(winddirection1).state >= 146.25 && id(winddirection1).state < 168.75) {
        return {"SSE"};
      } else if (id(winddirection1).state >= 168.75 && id(winddirection1).state < 191.25) {
        return {"S"};
      } else if (id(winddirection1).state >= 191.25 && id(winddirection1).state < 213.75) {
        return {"SSW"};
      } else if (id(winddirection1).state >= 213.75 && id(winddirection1).state < 236.25) {
        return {"SW"};
      } else if (id(winddirection1).state >= 236.25 && id(winddirection1).state < 258.75) {
        return {"WSW"};
      } else if (id(winddirection1).state >= 258.75 && id(winddirection1).state < 281.25) {
        return {"W"};
      } else if (id(winddirection1).state >= 281.25 && id(winddirection1).state < 303.75) {
        return {"WNW"};
      } else if (id(winddirection1).state >= 303.75 && id(winddirection1).state < 326.25) {
        return {"NW"};
      } else if (id(winddirection1).state >= 326.25 && id(winddirection1).state < 348.75) {
        return {"NNW"};
      } else return {"Something is not Right..."};
    update_interval: 10s
3 Likes

I do not have many North winds; so I will have to monitor accuracy around 0 and 360 degrees when it next comes up.

1 Like

Hi again
Thanks to your response
I think it’s a great idea to mask voltage and then use raw data. This is quite good now.
Yes and ok for the non linear and ends limit (for north direction only).

So just for information in my case, I use offset because the arm can’t be installed to north.
I’m using a lambda to correct the exceeding of 360°.
Here’s my code inspired of yours.
Too my sensor is a bit much reactive as yours but I have an other template with 10 min throttle average
Thanks a lot for your help

# Girouette - Direction du vent - Wind direction
  - platform: adc
    id: weatherstation_source_sensor
    pin: GPIO34
    attenuation: 11db  # to mesure up to VCC
    #internal: true
    unit_of_measurement: '°'
    name: 'Vent Direction'
    update_interval: 1s 
    icon: mdi:compass-rose
    accuracy_decimals: 0
    raw: true
    filters:
      #- multiply: 0.846153 # 3.9 -> 3.3V => pots between 0 and 3.3V with the 20k
      - calibrate_linear:
          # Map 0.0 (from sensor) to 0.0 (true value)
          - 0.0 -> 0.0
          - 4095 -> 360
      - offset: 90 # set offset for physical calibration of the arm of anemometer. Si arm on North (0°) offset should be 0. 
      - lambda: |-
          // Modify offset to not going up than 360°
          if (x > 360) {
              return (x - 360.0);  
          }
          else if (x < 0) {
              return (x + 360);
          }
          else
            return x;
      - sliding_window_moving_average:
          window_size: 20 #6
          send_every: 6 #3
    on_value:
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 348.75
              below: 11.25
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "N"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 11.25
              below: 33.75
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "NNE"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 33.75
              below: 56.25
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "NE"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 56.25
              below: 78.75
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "ENE"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 78.75
              below: 101.25
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "E"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 101.25
              below: 123.75
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "ESE"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 123.75
              below: 146.25
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "SE"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 146.25
              below: 168.75
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "SSE"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 168.75
              below: 191.25
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "S"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 191.25
              below: 213.75
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "SSO"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 213.75
              below: 236.25
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "SO"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 236.25
              below: 258.75
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "OSO"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 258.75
              below: 281.25
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "O"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 281.25
              below: 303.75
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "ONO"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 303.75
              below: 326.25
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "NO"
      - if:
          condition:
            sensor.in_range:
              id: weatherstation_source_sensor
              above: 326.25
              below: 348.75
          then:
            - text_sensor.template.publish:
                id: weatherstation_wind_dir_card
                state: "NNO"

    # Moyenne direction vent
  - platform: copy
    name: 'Vent Direction moyenne'#'${friendly_name} wind speed average'
    id: wind_direction_avg
    source_id: weatherstation_source_sensor
    unit_of_measurement: '°'
    icon: mdi:compass-rose
    filters:
      - throttle_average: 10min  # 10 min average as meteo france quality
      - filter_out: nan

Yes your wind is basically South :wink: Where do you live ?

Mine in alps valley
image

Hello yes … that is a very unusual wind direction for me! I am on the South Coast England with Atlantic depressions bringing in regular SW winds. (what3words: prosper.sued.snowballs) We have no mountains around!

My vane was installed with a compass but 8m high it was quite tricky. Even if it is correct, I have set an offset to keep my wind direction in line with the harbour weather station. We are all windsurfers …

I am not sure you need the lambda because the reading will never be above 4095, which maps to 360 anyway. HOWEVER, I am aware that 4095 will correspond to the 3.3v; it might be that the vane never receives 3.3v and so therefore the sensor never gets to 4095/360 degrees. I had this on my to do list; i will short the pins and see what voltage/ increment I get. This number then becomes the linear mapping number for 360. Also I have a suspicion that somewhere it is possible to recalibrate the linear mapping for ESP32. If you want to get super accurate

Yes but if you look about my last code, after the reading of the adc esp (between 0 to 4095), whichvis convert with filter linear value, i add an offset. So in this case my direction can be over 360.
My offset is my position of the arm of anemometer wich is Est and not north

1 Like

Thank you. I had not focussed on that and missed it. I will add the code in case I get any North winds!

1 Like

Hi Julian
Your Text Sensor and Cardinal Wind Direction Lambda solution are fantastic!
Exactly what I needed to make a little more sense of the readings from my Ultrasonic Wind Direction Sensor which outputs 0-360°.
Thanks very much for posting this and I would highly recommend it to others here as well.

PS: using Renke Weather Station and ESPHome and Sonoff Basic Hardware with RS485 Modbus Controller (details here)