Estação Meteorológica - WIP

Olá, recentemente decidi-me a montar uma estação meteorológica. Já tinha tido uma do Lidl, mas durou pouco. Há muitos modelos já prontos a usar, fiáveis e até integráveis no Home Assistant, mas são demasiado caras para o pretendido e não tem a mesma piada, que sermos nós a desenvolver!

Parte 1.

Material usado:

  • Anemómetro e o anemoscópio RS485 - 35.87€
  • TTL to RS485 - 1.23€
  • Wemos D1 Mini - 2.28€ (tinha em stock)
  • Pluviómetro - 16.40€ (usei o do Lidl que tinha)
  • Sensor Temperatura/Humidade ATH15 - 2.53€ (tinha em stock)
  • Resisência 10Kohm - 3.92€ (kit em stock)
  • Hi-Link PM01 222v to 5v dc - 3.84€ (tinha em stock)
  • Prefboard - 2.10€ (tinha em stock)
  • Fonte de alimentação 12v dc (tinha em stock)

As opções de material usado, foi principalmente por poder aproveitar ao máximo o que tenho disponível.
O firmware escolhido foi o EspHome.

Anemómetro e anemoscópio decidi-me pela versão RS485, pois considero que sejam mais simples as leituras dos dados, sem necessidade de fazer divisores de tensão (versão de 5v) ou contar pulsos ou medir resistência. Basta adicionar o conversor TTL para RS485, ligar ao ESP e já está! O EspHome já tem o resto.

O sensor de temperatura AHT15, não é o melhor, mas é pequeno, com uma margem de erro reduzida e barato (comprei há uns anos um conjunto de 5 por poucos euros). Tenho um no exterior há 2 anos sem dar problemas. Um SHT30 é melhor opção para quem tiver que adquirir, por ter leituras mais fiáveis, por quase o mesmo preço. (https://wiki.liutyi.info/display/ARDUINO/Sensors)

Para complementar uma estação meteorológica, seria bom adicionar um sensor de pressão atmosférica. Não o incluí aqui porque já tenho um BME280 noutro dispositivo diy. Este sensor é um tudo em 1 (temp, humi e pressão) mas sofre de “self heating” e acaba por dar uma temperatura superior e humidade menor. Pode-se adicionar só pela pressão, visto que é barato e usamos o mesmo I2c Bus.

O pluviómetro que tinha da estação antiga, funcionava a pilhas e transmitia por RF 433Mhz. Estava tudo funcional e cheguei a receber esses dados no HA, mas como queria tirar a parte da alimentação a pilhas e simplificar, acabei por desmontar tudo e só deixar o sensor Reed, que dá um impulso por cada vez que o báscula enche de água. O pluviómetro que sugiro, pelo que li, tem o mesmo funcionamento.

2 Curtiram

Parte 2.

Ligações:

Assim à primeira vista, até pode parecer complicado, mas com paciência faz-se bem… Nestes casos, eu prefiro ir primeiro ao Fritzing (é o melhor que conheço gratuito) e desenhar o que quero. Vou pondo componentes e andando com eles de um lado para o outro até me parecer bem.

Depois, é soldar os componentes principais na Placa perfurada e com fios de um cabo de rede UTP Cat6 ir soldando as ligações entre os pontos. Por detrás fica uma salganhada, mas bonito pela frente!!!

Podia tentar algo mais “profissional”, como uma placa PCB feita na JLCpcb, mas nunca fiz isso, não sei se os meus rabiscos estão suficientemente bons para isso ou se ainda tenho que estudar mais!

Nesta configuração, fico com:

  • Conector J3 para a entrada dos 220v
  • Jack J16 para ligar a fonte de alimentação de 12v para os medidores do vento
  • Conetor J11 e J17 para o A, B, +12v e Gnd dos medidores de vento
  • Conetor J14 para o Reed Switch do pluviómetro
  • Conetores J12 e J13 para o I2C usado pelo sensor de temperatura Aht15 (ou outros que lá se queiram ligar)

Se fosse para adquirir o material todo, iria para uma fonte de alimentação externa Dual, com saída de 12v e 5v e conetor Mini Din Male 4-pin. O placa ficaria mais pequena e era só uma coisa a alimentar nos 220v.

A utilização dos Pins TX e RX do Wemos D1 Mini para a UART é discutível. Estes pins são partilhados com a porta USB, que poderia causar interferências na comunicação, no entanto como eu não a vou usar, não há problema. Em casos de falhas, pode-se dessoldar as resistências que estão verso da placa, nestes pins e problema resolvido. Podia usar outros pins, mas esta board só tem uma Serial UART. Um D1 Mini ESP32 seria perfeito, pois tem duas Serial UART e pins de sobra!
imagem

Infelizmente ainda estou na fase em que terminei o teste na Breadboard e ainda não terminei a placa perfurada, pelo que não tenho fotos da montagem final. Mas seguem fotos dos esquemas finais e umas fotos dos testes. Tudo funcionou!

Parte 3.
Firmware:

Aqui, optei pelo EspHome, que já uso em vários dispositivos. É de fácil aprendizagem, há muita literatura online e grupos de ajuda. Já tem suporte para os dois medidores do vento adquiridos:

A primeira coisa a fazer alterar o endereço dos dois equipamentos. Vêm os dois de origem com o endereço 1, o que impede de usar ao mesmo tempo. Podia só alterar um deles, mas optei por alterar os dois para se um dia quiser adicionar outro que tenha o endereço 1.

As instruções estão nos links em cima, mas aqui vai o que usei, que serve para os dois equipamentos.
Carregar no ESP, abrir a webpage http://weatherstation.local e introduzir o novo endereço. Eu coloquei 2 para a velocidade e 3 para a direção do vento.

substitutions:
  name: "weatherstation"
  friendly_name: "Estação Meteorológica"
  
esphome:
  name: ${name}
  friendly_name: ${friendly_name}

esp8266:
  board: d1_mini


# Enable logging
logger:
  level: DEBUG
  baud_rate: 0  // disable UART debug

# Enable Home Assistant API
api:
  encryption:
    key: !secret secretkey

ota:
  - platform: esphome
    password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${name} Fallback Hotspot"
    password: !secret fallback_password

captive_portal:

web_server:
  port: 80

uart:
  tx_pin: GPIO01 # TX PIN
  rx_pin: GPIO03 # RX PIN
  baud_rate: 4800
  stop_bits: 1

modbus:
  id: modbus1

modbus_controller:
  - id: wind_speed_meter
    address: 1
    modbus_id: modbus1
    setup_priority: -10
    command_throttle: 200ms
    update_interval: 1s
    
sensor:
  - platform: modbus_controller
    modbus_controller_id: wind_speed_meter
    name: "Device current address"
    register_type: read
    address: 2000
    value_type: U_WORD

number:
  - platform: modbus_controller
    modbus_controller_id: wind_speed_meter
    name: "Device new address"
    address: 2000
    register_type: holding
    value_type: U_WORD
    mode: box

Código completo que tenho até ao momento. Ainda não está finalizado, pois ainda me faltam testes aos dois dados da pluviosidade, pois queria ter acesso ao valor no momento e o acumulado ao dia, sendo que a momentânea não está muito correta.
Também o parametro da rajáda de vento máxima não está perfeito. Na leitura da velocidade do vento ao ter a filtragem de valores, o resultado é mais consistente, mas pode não ser a velocidade máxima.

## PINS
#  GPIO13  D7  - Reed switch Pluviometro
#  GPIO04  D2  - I2C sda  Ath15
#  GPIO05  D1  - I2C scl  Ath15
#  GPIO01  TX  - UART RS485 Vento
#  GPIO03  RX  - UART RS485 Vento


substitutions:
  name: "weatherstation"
  friendly_name: "Estação Meteorológica"
  
esphome:
  name: ${name}
  friendly_name: ${friendly_name}

esp8266:
  board: d1_mini

# Enable logging
logger:
  level: DEBUG
  baud_rate: 0  # Disable UART debug

# Enable Home Assistant API
api:
  encryption:
    key: !secret secretkey

ota:
  - platform: esphome
    password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${name} Fallback Hotspot"
    password: !secret fallback_password

captive_portal:

web_server:
  port: 80

globals:
  - id: wind_gust_daily
    type: float
    restore_value: yes
    
time:
  - platform: homeassistant
    id: homeassistant_time  
    
    on_time:
      - seconds: 59
        minutes: 59
        hours: 23     
        then:  
        - globals.set:
            id: wind_gust_daily
            value: '0' 

#########################################################################
# https://devices.esphome.io/devices/Renke-RS-FXJT-N01-Wind-Direction
# https://devices.esphome.io/devices/Renke-RS-FSJT-N01-Wind-Speed

i2c:
  sda: GPIO04
  scl: GPIO05
  id: bus_a  

uart:
  tx_pin: GPIO01 # TX PIN
  rx_pin: GPIO03 # RX PIN
  baud_rate: 4800
  stop_bits: 1

modbus:
  id: modbus1

modbus_controller:
  - id: wind_speed_meter
    address: 2
    modbus_id: modbus1
    setup_priority: -10
    command_throttle: 200ms
    update_interval: 1s
    
  - id: wind_direction_meter
    address: 3
    modbus_id: modbus1
    setup_priority: -10
    command_throttle: 200ms
    update_interval: 60s


sensor:
  - platform: modbus_controller
    modbus_controller_id: wind_speed_meter
    name: "Velocidade do Vento"
    device_class: wind_speed
    register_type: read
    address: 0
    unit_of_measurement: "m/s"
    value_type: U_WORD
    accuracy_decimals: 1
    filters:
      - multiply: 0.1
      - max:
          window_size: 5
          send_every: 5
      - exponential_moving_average:
          alpha: 0.1
          send_every: 12  
    on_value:
      lambda: |-
        float speed = float(x);

        if (speed <= 0.2) {               // Beaufort 0: Calmo (0.0 - 0.2 m/s)
          id(wind_scale).publish_state("0: Calmo - Fumo sobe na vertical");
        } else if (speed <= 1.5)  {       // Beaufort 1: Bafagem (0.3 - 1.5 m/s)
          id(wind_scale).publish_state("1: Bafagem - Sentido pelo fumo");
        } else if (speed <= 3.3)  {       // Beaufort 2: Brisa Leve (1.6 - 3.3 m/s)
          id(wind_scale).publish_state("2: Brisa Leve - Sentida na face, folhas agitam-se");
        } else if (speed <= 5.4)  {       // Beaufort 3: Brisa Fraca (3.4 - 5.4 m/s)
          id(wind_scale).publish_state("3: Brisa Fraca - Bandeiras leves esticam, folhas em movimento contínuo");
        } else if (speed <= 7.9)  {       // Beaufort 4: Brisa Moderada (5.5 - 7.9 m/s)
          id(wind_scale).publish_state("4: Brisa Moderada - Levanta poeira e papel solto, pequenos ramos em movimento");
        } else if (speed <= 10.7) {       // Beaufort 5: Brisa Forte (8.0 - 10.7 m/s)
          id(wind_scale).publish_state("5: Brisa Forte - Pequenas árvores começam a balançar, ondulação em águas interiores");
        } else if (speed <= 13.8) {       // Beaufort 6: Vento Forte (10.8 - 13.8 m/s
          id(wind_scale).publish_state("6: Vento Forte - Dificuldade em usar guarda-chuva, fios de eletricidade assobiam");
        } else if (speed <= 17.1) {       // Beaufort 7: Vento Duro (13.9 - 17.1 m/s)
          id(wind_scale).publish_state("7: Vento Duro - Árvores grandes balançam, dificuldade em andar contra o vento");
        } else if (speed <= 20.7) {       // Beaufort 8: Temporal (17.2 - 20.7 m/s)
          id(wind_scale).publish_state("8: Temporal - Ramos partidos, andar na rua torna-se muito difícil");
        } else if (speed <= 24.4) {       // Beaufort 9: Temporal Forte (20.8 - 24.4 m/s)
          id(wind_scale).publish_state("9: Temporal Forte - Pequenos danos estruturais (chaminés e telhas removidas)");
        } else if (speed <= 28.4) {       // Beaufort 10: Vendaval (24.5 - 28.4 m/s)
          id(wind_scale).publish_state("10: Vendaval - Danos estruturais significativos (arrancamento de árvores)");
        } else if (speed <= 32.6) {       // Beaufort 11: Vendaval Forte (28.5 - 32.6 m/s)
          id(wind_scale).publish_state("11: Vendaval Forte - Danos generalizados e graves");
        } else if (speed <= 60)   {       // Beaufort 12: Furacão (> 32.7 m/s)
          id(wind_scale).publish_state("12: Furacão - Destruição em larga escala e devastadora");
        } else {
          id(wind_scale).publish_state("");
        }

        if (speed >= id(wind_gust_daily)) {
          id(wind_gust_daily) = speed;
        }    

  
  - platform: modbus_controller
    modbus_controller_id: wind_direction_meter
    name: "Wind direction gear"
    internal: true
    register_type: read
    address: 0
    value_type: U_WORD
    accuracy_decimals: 0
    on_value:
      - lambda: |-
          switch (int(x)) {
            case 0:
              id(wind_direction_cardinal).publish_state("N");  //North
              break;
            case 1:
              id(wind_direction_cardinal).publish_state("NE"); //North-East
              break;
            case 2:
              id(wind_direction_cardinal).publish_state("E");  //East
              break;
            case 3:
              id(wind_direction_cardinal).publish_state("SE"); //South-East
              break;
            case 4:
              id(wind_direction_cardinal).publish_state("S");  //South
              break;
            case 5:
              id(wind_direction_cardinal).publish_state("SO"); //South-West
              break;
            case 6:
              id(wind_direction_cardinal).publish_state("O");  //West
              break;
            case 7:
              id(wind_direction_cardinal).publish_state("NO"); //North-West
              break;
            default:
              id(wind_direction_cardinal).publish_state("");   //invalid
          }

  - platform: modbus_controller
    modbus_controller_id: wind_direction_meter
    name: "Direção do Vento"
    icon: mdi:compass-outline
    register_type: read
    address: 1
    value_type: U_WORD
    accuracy_decimals: 0
    state_class: measurement
    unit_of_measurement: "°"

# Wind Gust
  - platform: template
    name: "Rajada máxima"
    id: template_wind_gust_daily
    device_class: wind_speed
    unit_of_measurement: "m/s"
    accuracy_decimals: 2
    icon: mdi:wind-turbine-alert
    update_interval: 60s
    lambda: |-
      return (id(template_wind_gust_daily).state = id(wind_gust_daily));


############ pluviometro ###############
  - platform: pulse_counter
    pin:
      # Don't forget to add a pulling up resistor 10K Ohm (D7 e 3.3v), see README
      number: GPIO13  # D7 PIN
      mode: INPUT
    unit_of_measurement: 'mm'
    name: "Precipitação"
    icon: 'mdi:weather-rainy'
    id: rain_gauge
    internal: true
    count_mode:
      rising_edge: DISABLE
      falling_edge: INCREMENT
    internal_filter: 13us
    update_interval: 60s
    filters:
      # Area do Funil: 8992 mm2  |  0.008992 m2 ~= 0.009 m2
      # Volume Bascula: 300ml/81 interações:  3.70373 ml  |  0.0037037 l / interação
      # Chuva em mm por iteração: 0.0037037 l / 0.009 m2 = 0.4115226 mm
      - multiply: 0.4115226
    accuracy_decimals: 4
    
  - platform: integration
    name: "Precipitação"
    id: rain_per_min
    time_unit: min
    unit_of_measurement: 'mm'
    icon: 'mdi:weather-rainy'
    sensor: rain_gauge

  - platform: total_daily_energy
    name: "Precipitação diária"
    power_id: rain_gauge
    unit_of_measurement: 'mm'
    icon: 'mdi:weather-rainy'
    # x60 To convert to aggregated rain amount
    filters:
      - multiply: 60

  - platform: aht10
    i2c_id: bus_a
    temperature:
      name: "Temperatura"
      unit_of_measurement: "°C"
      icon: "mdi:thermometer"
      device_class: "temperature"
      state_class: "measurement"
      accuracy_decimals: 1
    humidity:
      name: "Humidade"
      unit_of_measurement: "%"
      icon: "mdi:water-percent"
      device_class: "humidity"
      state_class: "measurement"
      accuracy_decimals: 1
    update_interval: 60s


text_sensor:
  - platform: template
    name: 'Escala de Vento Beaufort'
    icon: 'mdi:tailwind'
    id: wind_scale
    update_interval: never
    
  - platform: template
    name: "Direção do Vento Cardeal"
    id: wind_direction_cardinal
    icon: mdi:compass-rose

Dados obtidos, neste momento tudo indisponível pois estou a montar a placa…

Com uns calculos, ainda podemos adicionar o Ponto de Orvalho e a Humidade Absoluta. Com o BME280, obtemos a pressão atmosférica:

  - platform: template
    name: "Humidade Absoluta Exterior"
    lambda: |-
      const float mw = 18.01534;    // molar mass of water g/mol
      const float r = 8.31447215;   // Universal gas constant J/mol/K
      return (6.112 * powf(2.718281828, (17.67 * id(temperatura).state) /
        (id(temperatura).state + 243.5)) * id(humidade).state * mw) /
        ((273.15 + id(temperatura).state) * r); // in grams/m^3
    accuracy_decimals: 1
    update_interval: 15s
    icon: 'mdi:water'
    unit_of_measurement: 'g/m³'
    
  - platform: template
    name: "Ponto de Orvalho Exterior"
    lambda: |-
      return (243.5*(log(id(humidade).state/100)+((17.67*id(temperatura).state)/
      (243.5+id(temperatura).state)))/(17.67-log(id(humidade).state/100)-
      ((17.67*id(temperatura).state)/(243.5+id(temperatura).state))));
    unit_of_measurement: °C
    icon: 'mdi:thermometer-alert'

imagem

Offtopic:

Porquê gastar dinheiro para obter valores que o IPMA e vários “meteorologistas caseiros” publicam na internet?
Mera curiosidade e querer saber os valores mais reais para o local onde moro.
Também tenho interesse em ver a velocidade e direção do vento para estudar a possibilidade de instalar um gerador eólico para complementar os painéis fotovoltaicos.

Exemplo de uma curiosidade observada, quando ainda só tinha o BME280 e o AHT15:
A 15 de Janeiro de 2022, pouco depois da meia noite, houve uma erupção do vulcão submarino de Tonga, no outro lado do mundo no Pacífico Sul, no entanto a sua violência foi sentida por este simples sensor de pressão de 2 euros.
Também é possível antever algumas tempestades com a queda mais rápida de pressão.

Bom trabalho :slight_smile: sem dúvida que é engraçado fazer uma coisa destas e ainda para mais aproveitar coisas que já temos :slight_smile: falta umas fotos para ver isso no sítio!:slight_smile:


Copyright © 2017-. Todos os direitos reservados
CPHA.pt - info@cpha.pt


FAQ | Termos de Serviço/Regras | Política de Privacidade