Sensor de Chuva + ESPHome: Seco, Chovendo ou Secando

Este post traz uma opção de instalação de sensor de chuva sem usar o comparador que vem no sensor. É uma variação desta implementação.

Essa implementação foi adaptada do repositório GitHub - hugokernel/esphome-rain-detector: ESPHome Rain Detector, o qual é o autor original do código. Realizei algumas alterações e traduções para facilitar a implementação.

Algumas vantagens dessa implemetação:

  • Conseguir diferenciar quando está chovendo (o sensor está molhado) de quando a chuva já cessou e o sensor está secando. Isso é possível através da análise da resistência da placa medida pelo NodeMCU.

image

  • Diminuição da oxidação das trilhas da placa devido a aplicação de tensão na placa ocorrer por pequenos intervalos de tempo a cada período de tempo (configurável, no código está aplicação de tensão por 2 segundos a cada 5 segundos se estiver seco ou a cada 30 segundos se estiver molhado).

Materiais utilizados:

Ligação do sensor no ESP:

Código para o ESPHome:

Os comentários do código ajuda a entender a lógica de funcionamento.

substitutions:
  #Configurações da placa:
  Plataforma: ESP32 #Altere para o modelo da sua placa
  TipoPlaca: esp32dev #Altere para o tipo da sua placa
  
  #Configurações do dispositivo:
  hostname: 'casa3740espclima' #Hostname do dispositivo na rede
  PrefixoNomeDevice: "Clima - "
  PrefixoNomeChuvaPlaca: "Clima - Chuva Inst. - "
  
  #Configurações da Rede:
  RedeWifi: !secret RedeWifi_IoT #Nome da rede wifi que o dispositivo irá se conectar
  SenhaWifi: !secret SenhaWifi_IoT #Senha da rede wifi que o dispositivo irá se conectar
  SenhaWifiReconfig: !secret SenhaWifiReconfig #Senha do AP Wifi para reconfiguração do wifi do dispositivo (padrão: o nome do hostame)
  EndConfig: ${hostname}.local #10.10.103.104 #${hostname}.local #Endereço para configuração (IP que o esp está acessível atualmente na rede)
  WifiOculto: 'False'
  WifiFastConnect: 'False'
  
  #Senhas
  SenhaAPI: !secret SenhaAPI
  SenhaOTA: !secret SenhaOTA
  
  #Pinos
  PinoSensorChuvaTensaoPlaca: GPIO19
  PinoSensorChuvaMedidaPlaca: GPIO33

  #Logger
  LoggerLevel: DEBUG
  
  resistor_value: "9.82kOhm" #Usar um resistor de 10kOhm e medir o valor real dele
  
  # Intervalo de resistência mínima (imerso em água) e máxima (seco)
  # Igonora valores fora do intervalo
  min_resistance: "2700"
  max_resistance: "39154"

  # Valor da resistência em que uma mudança significativa é considerada como chovendo
  rain_detection_threshold: "2000"
 
  # Se a média da resistência estiver este valor acima da última média, o sensor é considerado secando
  dry_detection_threshold: "1000"

  # Ao inicializar, se a resistência for inferior a este valor, suponha que o sensor esteja molhado (resistência molhada)
  wet_resistance_when_booting: "35000"

  # +------------------------------+
  # | Delay entre 2 medida de chuva |
  # +------------------------------+
  # Tempo de delay se estiver no modo seco
  measure_interval_dry: "5000"

  # Tempo de delay se estiver no modo molhado
  # Deve ser grande o suficiente para não danificar as trilhas prematuramente, mas pequeno o suficiente para ser reativo o suficiente.
  measure_interval_wet: "30000"

  # Estabilização antes de ler a resistência
  # Um atraso muito curto não permitirá a leitura das resistências baixas
  stabilization_delay: 2sec

esphome:
  name: $hostname
  platform: ${Plataforma}
  board: ${TipoPlaca}
  on_boot:
    then:
      - script.execute: test_resistance
      - script.execute: measure_loop
      - text_sensor.template.publish:
          id: text_status
          state: "Verificando"
wifi:
  networks:
  - ssid: ${RedeWifi}
    password: ${SenhaWifi}
    hidden: ${WifiOculto}
  fast_connect: ${WifiFastConnect}
    
  use_address: ${EndConfig}
  
  # Ative o hotspot de fallback (captive portal) caso a conexão wifi falhe
  ap:
    ssid: WIFI
    password: ${SenhaWifiReconfig}

#Habilita um AP Wifi para reconfigurar em caso de perda de conexão com a rede configurada
captive_portal:

#Habilita a atualização de firmware por OTA
ota:
  password: ${SenhaOTA}
  
#Habilita as mensagens de logs pela porta serial e via MQTT
logger:
  level: ${LoggerLevel}

#Habilita a api para comunicar com o Home Assistant
api:
  password: ${SenhaAPI}

globals:
  - id: measure_delay
    type: int
    restore_value: yes
    initial_value: $measure_interval_dry

################################################################################
#                                      BUTTON                                  #
################################################################################
button:
  #----------------------------------------------------------------------------#
  #                                BUTTON -  DEVICE                            #
  #----------------------------------------------------------------------------#
  #Comando reinicilizar esp remotamente
  - platform: restart
    id: restart_button
    name: ${PrefixoNomeDevice} Reiniciar
    icon: mdi:restart

  #----------------------------------------------------------------------------#
  #                    BUTTON - SENSOR DE CHUVA INSTANTÂNEO (PLACA)            #
  #----------------------------------------------------------------------------#
  #Executar a medição
  - platform: template
    id: run_measure
    name: "${PrefixoNomeChuvaPlaca} Executa Medição"
    on_press:
    - script.execute: measure

################################################################################
#                                  BINARY SENSOR                              #
################################################################################
binary_sensor:
  #----------------------------------------------------------------------------#
  #                            BINARY SENSOR - DEVICE                          #
  #----------------------------------------------------------------------------#
  #Status (conectado ou desconectado)
  - platform: status
    id: device_status
    name: ${PrefixoNomeDevice} Status
    device_class: connectivity

  #----------------------------------------------------------------------------#
  #              BINARY SENSOR - SENSOR DE CHUVA INSTANTÂNEO (PLACA)           #
  #----------------------------------------------------------------------------#
  # Sensor binário do status chovendo
  - platform: template
    id: raining
    name: "${PrefixoNomeChuvaPlaca} Chovendo"
    device_class: moisture
  # Sensor binário do status secando
  - platform: template
    id: drying
    name: "${PrefixoNomeChuvaPlaca} Secando"
    device_class: moisture
  # Sensor binário do status secando
  - platform: template
    id: power
    name: "${PrefixoNomeChuvaPlaca} Tensão Aplicada"
    device_class: power

################################################################################
#                                    TEXT SENSOR                               #
################################################################################
text_sensor:
  #----------------------------------------------------------------------------#
  #                              TEXT SENSOR - DEVICE                          #
  #----------------------------------------------------------------------------#
  #Sensor de tempo ligado formatado
  - platform: template
    name: ${PrefixoNomeDevice} Uptime
    id: uptime_human
    icon: mdi:clock-start
    update_interval: 1s
    entity_category: diagnostic
  #Informações da conexão wifi
  - platform: wifi_info
    #Endereço IP
    ip_address:
      id: IP
      name: ${PrefixoNomeDevice} Endereço IP
      icon: mdi:ip-network
    #Nome da Rede
    ssid:
      id: SSID
      name: ${PrefixoNomeDevice} Rede Wifi
      icon: mdi:wifi
  #Informação da versão da compilação
  - platform: version
    id: versao
    name: ${PrefixoNomeDevice} Versão
    icon: mdi:information

  #----------------------------------------------------------------------------#
  #                TEXT SENSOR - SENSOR DE CHUVA INSTANTÂNEO (PLACA)           #
  #----------------------------------------------------------------------------#
  #Status do sensor de chuva instantaneo
  - platform: template
    id: text_status
    name: "${PrefixoNomeChuvaPlaca} Status"
    icon: mdi:information-outline
    #lambda: |-
    #  return {"Verificando"};


################################################################################
#                                       SWITCH                                 #
################################################################################
switch:
  #----------------------------------------------------------------------------#
  #                  SWITCH - SENSOR DE CHUVA INSTANTÂNEO (PLACA)              #
  #----------------------------------------------------------------------------#
  #Switch GPIO para controlar a aplicação de tensão  na placa
  #(com o objetivo de reduzir a oxidação)
  - platform: gpio
    id: resistance_bias
    name: "${PrefixoNomeChuvaPlaca} Liga Energia Placa"
    icon: "mdi:power"
    internal: true
    pin:
      number: ${PinoSensorChuvaTensaoPlaca}
      mode: OUTPUT
    on_turn_on:
      - binary_sensor.template.publish:
          id: power
          state: on
    on_turn_off:
      - binary_sensor.template.publish:
          id: power
          state: off
     

################################################################################
#                                       SENSOR                                 #
################################################################################
sensor:
  #----------------------------------------------------------------------------#
  #                                 SENSOR - DEVICE                            #
  #----------------------------------------------------------------------------#
  #Sensor de tempo ligado
  - platform: uptime
    id: device_uptime
    internal: true
    update_interval: 1s
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: uptime_human
            state: !lambda |-
              int seconds = round(id(device_uptime).raw_state);
              int days = seconds / (24 * 3600);
              seconds = seconds % (24 * 3600);
              int hours = seconds / 3600;
              seconds = seconds % 3600;
              int minutes = seconds /  60;
              seconds = seconds % 60;
              return (
                (days ? to_string(days) + "d " : "") +
                (hours ? to_string(hours) + "h " : "") +
                (minutes ? to_string(minutes) + "m " : "") +
                (to_string(seconds) + "s")
              ).c_str();

  #Sensor Intensidade Sinal Wifi
  - platform: wifi_signal
    id: wifi_sinal
    name: ${PrefixoNomeDevice} Intensidade Wifi
    icon: mdi:signal
    update_interval: 10s

  #----------------------------------------------------------------------------#
  #                   SENSOR - SENSOR DE CHUVA INSTANTÂNEO (PLACA)             #
  #----------------------------------------------------------------------------#
  #Leitura da resistência da placa
  - platform: adc
    id: source_sensor
    pin: ${PinoSensorChuvaMedidaPlaca}
    name: ADC
    attenuation: 11db
    internal: true

    # É importante ter um intervalo de atualização baixo para que
    # a medição tem tempo para ser feita corretamente durante
    # a ativação da tensão e levando em consideração o filtro mediano
    update_interval: 250ms

    filters:
      - multiply: 0.846153 # 3.9 (11db tensão de atenuação em escala real) -> 3.3V
      - median:
          window_size: 7
          send_every: 4
          send_first_at: 3

  #Calculo da resistência real da placa
  - platform: resistance
    sensor: source_sensor
    id: real_resistance_sensor
    name: "${PrefixoNomeChuvaPlaca} Resistência"
    configuration: DOWNSTREAM
    resistor: $resistor_value
    reference_voltage: 3.3V
    internal: true
    icon: "mdi:omega"
    filters:
      # Nenhum valor menor que 0
      - lambda: 'return max((float)$min_resistance, x);'
      # Nenhum valor maior que $max_resistance
      - lambda: 'return min((float)$max_resistance, x);'
    on_value:
      then:
        - if:
            condition:
              lambda: |-
                  return (
                      id(real_resistance_sensor).state > $min_resistance
                      &&
                      // <= é importante para forçar a resistência ao máximo
                      // para ter um valor para comparar se o
                      // queda de resistência
                      id(real_resistance_sensor).state <= $max_resistance
                  );
            then:
              - sensor.template.publish:
                  id: resistance_sensor
                  state: !lambda "return id(real_resistance_sensor).state;"

  # Sensor da última resistência medida
  - platform: template
    id: latest_resistance_sensor
    name: "${PrefixoNomeChuvaPlaca} Resistência - Última Medição"
    icon: "mdi:omega"
    unit_of_measurement: 'Ω'
    disabled_by_default: true

  # Sensor da última média de resistência medida
  - platform: template
    id: latest_average_resistance_sensor
    name: "${PrefixoNomeChuvaPlaca} Resistência - Última Média"
    icon: "mdi:omega"
    unit_of_measurement: 'Ω'
    disabled_by_default: true

  # Sensor da resistência medida
  - platform: template
    id: resistance_sensor
    name: "${PrefixoNomeChuvaPlaca} Resistência"
    icon: "mdi:omega"
    unit_of_measurement: 'Ω'

  # Sensor da média da resistência medida
  - platform: template
    id: average_resistance_sensor
    name: "${PrefixoNomeChuvaPlaca} Resistência - Média"
    icon: "mdi:omega"
    unit_of_measurement: 'Ω'
    disabled_by_default: true
    filters:
      - sliding_window_moving_average:
          window_size: 15
          send_every: 15
      #- heartbeat: 2min


################################################################################
#                                      SCRIPTS                                 #
################################################################################
script:
  #----------------------------------------------------------------------------#
  #                    SCRIPTS - SENSOR DE CHUVA INSTANTÂNEO (PLACA)           #
  #----------------------------------------------------------------------------#
  #Script para iniciar a medição (aplica a tensão na placa e aguarda estabilizar)
  - id: begin_measure
    mode: single
    then:
      - switch.turn_on: resistance_bias
      - delay: $stabilization_delay
  #Script para finalizar a medição (retira a tensão da placa)
  - id: end_measure
    mode: single
    then:
      - switch.turn_off: resistance_bias
  #Script que testa se a resistência é menor que quando iniciou (para detectar se está secando)
  - id: test_resistance
    mode: single
    then:
      - script.execute: begin_measure
      - script.wait: begin_measure
      - if:
          condition:
            lambda: "return id(resistance_sensor).state < $wet_resistance_when_booting;"
          then:
            - script.execute: its_raining
      - script.execute: end_measure
      - script.wait: end_measure
  #Script que salva os últimos valores de resistência e média
  - id: save_current_resistance
    then:
      - sensor.template.publish:
          id: latest_resistance_sensor
          state: !lambda "return id(resistance_sensor).state;"
      - sensor.template.publish:
          id: latest_average_resistance_sensor
          state: !lambda "return id(average_resistance_sensor).state;"
  # Atualmente:
  # * A chuva é detectada com o valor mais recente comparado a um limite
  # * Para detectar quando está secando, usamos a média
  #   Para ser testado:
  #     - A resistência mais baixa que corresponde a uma saturação completa do sensor é gravado permanentemente:
  #        Se este valor não for alcançado mas a resistência não diminui durante um período de tempo, sabemos que não está mais chovendo.
  #Script para atualizar a média de resistência
  - id: update_average_values
    mode: single
    then:
      # Defina a resistência média
      - if:
          condition:
            lambda: "return (id(resistance_sensor).state >= 0 && id(resistance_sensor).state <= $max_resistance);"
          then:
            - sensor.template.publish:
                id: average_resistance_sensor
                state: !lambda "return id(resistance_sensor).state;"
  #Script de medição da resistência da placa
  - id: measure
    mode: single
    then:
      - script.execute: begin_measure
      - script.wait: begin_measure
      # Inicia o último valor de resistência se não for um número
      - if:
          condition:
            lambda: "return isnan(id(latest_resistance_sensor).state);"
          then:
            - script.execute: save_current_resistance
            - script.wait: save_current_resistance
      - if:
          condition:
            lambda: "return isnan(id(latest_average_resistance_sensor).state);"
          then:
            - script.execute: save_current_resistance
            - script.wait: save_current_resistance
      # Apenas para fins de depuração
      - logger.log:
          level: INFO
          format: "> Resistance: %.1f vs latest resistance: %.1f"
          args: ['id(resistance_sensor).state', 'id(latest_resistance_sensor).state']
      - script.execute: update_average_values
      # Teste para chover
      - if:
          condition:
            lambda: "return id(resistance_sensor).state + $rain_detection_threshold < id(latest_resistance_sensor).state;"
          then:
            - script.execute: its_raining
      # Teste para secagem
      - if:
          condition:
            lambda: "return id(average_resistance_sensor).state - $dry_detection_threshold > id(latest_average_resistance_sensor).state;"
          then:
            - script.execute: its_drying
      # Teste para seco
      # Assumimos que o sensor está seco quando a resistência atual == resistência máxima
      - if:
          condition:
            lambda: "return id(resistance_sensor).state == $max_resistance;"
          then:
            - script.execute: its_dry
      - script.execute: end_measure
      - script.wait: end_measure
  #Script para executar o loop de medição da resistência da placa
  - id: measure_loop
    mode: single
    then:
      - while:
          condition:
            lambda: "return true;"
          then:
            - logger.log:
                format: "[Start measure]"
                level: INFO
            - script.execute: measure
            - script.wait: measure
            - delay: !lambda "return id(measure_delay);"
  #Script para quando detectar que está chovendo
  - id: its_raining
    mode: single
    then:
      - logger.log: "It's raining !"
      - script.execute: save_current_resistance
      - script.wait: save_current_resistance
      - homeassistant.event:
          event: esphome.its_raining
      - text_sensor.template.publish:
          id: text_status
          state: "Chovendo"
      - binary_sensor.template.publish:
          id: raining
          state: on
      - binary_sensor.template.publish:
          id: drying
          state: off
      - globals.set:
          id: measure_delay
          value: $measure_interval_wet
  #Script para quando detectar que a placa está secando
  - id: its_drying
    mode: single
    then:
      - logger.log: "It's drying !"
      - script.execute: save_current_resistance
      - script.wait: save_current_resistance
      - text_sensor.template.publish:
          id: text_status
          state: "Secando"
      - binary_sensor.template.publish:
          id: raining
          state: off
      - binary_sensor.template.publish:
          id: drying
          state: on
      - globals.set:
          id: measure_delay
          value: $measure_interval_wet
  #Script para quando detectar que a placa está seca
  - id: its_dry
    mode: single
    then:
      - logger.log: "It's dry !"
      - script.execute: save_current_resistance
      - script.wait: save_current_resistance
      - text_sensor.template.publish:
          id: text_status
          state: "Seco"
      - binary_sensor.template.publish:
          id: raining
          state: off
      - binary_sensor.template.publish:
          id: drying
          state: off
      - globals.set:
          id: measure_delay
          value: $measure_interval_dry

Todas essas informações importantes (senhas OTA e API, configuração da rede wifi, etc) estão armazenadas no arquivo secrets.yaml (ver aqui e aqui para mais detalhes de configuração e uso).

Exemplos de estatísticas com a informação do sensor:

image

sensor:
  - platform: history_stats
    name: Sensor de Chuva - Chovendo - N° Ativações - Hoje
    entity_id: binary_sensor.clima_chuva_inst_chovendo
    state: "on"
    type: count
    start: "{{ now().replace(hour=0, minute=0, second=0) }}"
    end: "{{ now() }}"

  - platform: history_stats
    name: Sensor de Chuva - Chovendo - N° Ativações - Últimas 24h
    entity_id: binary_sensor.clima_chuva_inst_chovendo
    state: "on"
    type: count
    duration: 24:00:00
    end: "{{ now() }}"

  - platform: statistics
    entity_id: binary_sensor.clima_chuva_inst_chovendo
    name: Sensor de Chuva - Tempo Chovendo - Últimas 24h
    state_characteristic: average_step
    max_age:
      hours: 24
      
  - platform: history_stats
    name: Sensor de Chuva - Secando - N° Ativações - Hoje
    entity_id: binary_sensor.clima_chuva_inst_secando
    state: "on"
    type: count
    start: "{{ now().replace(hour=0, minute=0, second=0) }}"
    end: "{{ now() }}"

  - platform: history_stats
    name: Sensor de Chuva - Secando - N° Ativações - Últimas 24h
    entity_id: binary_sensor.clima_chuva_inst_secando
    state: "on"
    type: count
    duration: 24:00:00
    end: "{{ now() }}"

  - platform: statistics
    entity_id: binary_sensor.clima_chuva_inst_secando
    name: Sensor de Chuva - Tempo Secando - Últimas 24h
    state_characteristic: average_step
    max_age:
      hours: 24

Ideias de uso no Lovelace:

  • Além de incluir a informação em cards, fica lega incluir em alguma parte do seu dashboard a lista de eventos do status do sensor para verificar diretamente quando iniciou e parou a chuva.

Lista de eventos

Código do card:

type: logbook
entities:
  - sensor.clima_chuva_inst_status
hours_to_show: 48
title: Sensor de Chuva
8 curtidas

Excelente tutorial, funcionou tudo perfeitamente. A unica coisa que não entendi muito bem foi com fazer esse teste.

1 curtida

O ideal seria medir a resistência real do resistor com um multímetro. Mas caso não tiver pode usar esse valor sem interferir tanto no resultado final.

1 curtida

Agora tudo fez sentido hahahahaha.
Eu tava tentando medir com o próprio ESP32 tava dando tudo errado, agora deu certo.
Perfeito

1 curtida

Dá para fazer com o mesmo código no esp8266 ?

Amigão! Parabéns! Otimo tutorial! Mas é normal a tensão aplicada ficar ligando e desligando a cada segundo?

1 curtida

Ela vai ligar a cada tempo definido no código no ESPHome, quanto está no seu?

Por exemplo, o padrão do código é efetuar a medição (ligando a saída de tensão) a cada 5 segundos se estiver seco ou a cada 30 segundos se estiver molhado. Esses tempos são configurados no código pelas variáveis abaixo:

1 curtida

Apesar de eu não ter testado, acredito que sim.

O meu a entidade tensão aplicada fica piscando em desligado e ligado! E nos teste ela nao fica como secando? Nao mudei nada do código original! Somente tirei iot do secret do wifi


Fica mesmo em seco fica piscando! Ela n teria q ficar desligado para nao danificar a placa?

1 curtida


Douglas! Esses sensores eu coloco onde? Em sensores no configurations ou no código do esphome? Obrigado

Projeto ficou bem bacana, hoje tenho um com nodemcu e o sensor de chuva, mas usei tasmota, porém o sensor de chuva não funciona muito bem, o que fiz usei o módulo do sensor de chuva, não liguei a placa diretamente no nodemcu como nesse projeto. Mas para implementar esse projeto ao meu, eu precisaria que uma das portas do node acionasse um relé que é o acionamento da janela automática que fiz, teria como me passar o que devo acresentar ao código para habilitar esse switch da janela?

Como vc fez?
Já pensei em fazer isso, mas não achei uma solução que fosse esteticamente boa.

Vc vai ter que adicionar um GPIO Switch ou GPIO Output para controlar o relé.

E executar uma automação no próprio esphome ou no HA para controlar o relé de acordo com sua necessidade.

Uma opção mais complicada é usar Cover Component, com ele da para adicionar algumas opções de segurança para o sistema como fim de curso, tempo que o relé/motor vai ficar acionado, etc

1 curtida

A janela que motorizei é uma jenela suspensa, isso ajudou na estética. Comecei usar o forum agora, vou fazer um topico com o projeto, mas foi o funcionamento mais simples possível, ela completa 3 anos agora em maio/23, única manutenção foi trocar a fonte que queimou com uma descarga elétrica.
Segue um vídeo que fiz na época que finalizei a instalação: Janela automática DIY - YouTube

Ficou muito bom. Qual motor usou?

Da uma olhada no meu código abaixo, talvez te ajude em alguma coisa.
Esse foi o primeiro código que fiz para o esphome.
Como já tem quase um ano que mudei, não uso mais esse projeto, então pode ser que precise de alguns ajustes para compilar devido a alguma atualização do esphome.
Basicamente ele controlava uma cobertura de acordo com a temperatura, horário do dia e se estava chovendo ou não.


substitutions:
  #Configurações do dispositivo:
  friendly_name: Cobertura
  name: cobertura
  NAME: COBERTURA
  versao: '0.03'
  platform: ESP32
  board: esp32dev
  groupid: light
  Groupname: Light


esp32:
  board: ${board}
  framework:
    type: arduino


packages:
  device_base: !include device_basic.yaml

globals:
  - id: previousMillis
    type: unsigned long
    restore_value: no
    initial_value: '0'

  - id: dry_delay
    type: unsigned long
    restore_value: no
    initial_value: '900000'

  - id: rainning
    type: int
    restore_value: no
    initial_value: '1'

  - id: horizon
    type: int
    restore_value: no
    initial_value: '0'

  - id: chuva_limit
    type: int
    restore_value: no
    initial_value: '4090'

  - id: noite_frio
    type: float
    restore_value: no
    initial_value: '23.0'

  - id: noite_quente
    type: float
    restore_value: no
    initial_value: '24.0'

  - id: dia_frio
    type: float
    restore_value: no
    initial_value: '20.0'

  - id: dia_quente
    type: float
    restore_value: no
    initial_value: '22.0'




sensor:
  - platform: dht
#    pin: 35 #new pin
    pin: 25 #old pin
    temperature:
      name: "Varanda Temp"
      id: cover_varanda_temp
    humidity:
      name: "Varanda Umidade"
      id: cover_varanda_umidade
    update_interval: 60s

  - platform: adc
#    pin: 39 #new pin
    pin: 34 #old pin
    name: "Sensor de Chuva"
    icon: "mdi:weather-pouring"
    id: cover_sensor_chuva
    update_interval: never
    attenuation: 11db
    raw: true
#    filters:
#      - multiply: 0.00095238 # 3.9/4095, for attenuation 11db

  - platform: template
    name: IF Status
    id: cover_if_status

  - platform: sun
    name: Sun Elevation
    type: elevation
  - platform: sun
    name: Sun Azimuth
    type: azimuth



text_sensor:
  - platform: sun
    name: Sun Next Sunrise
    type: sunrise
    update_interval: 60s

  - platform: sun
    name: Sun Next Sunset
    type: sunset
    update_interval: 60s

  - platform: template
    name: Clima
    id: cover_clima
    #icon: mdi:clock-start


output:
  - platform: gpio
#    pin: 32 #new pin
    pin: 26 #old pin
    id: power_chuva

interval:
  - interval: 5s
    then:
      - output.turn_on: power_chuva
      - delay: 50ms
      - component.update: cover_sensor_chuva
      - delay: 5ms
      - output.turn_off: power_chuva
      - delay: 5ms
      - script.execute: check_sensors



binary_sensor:
  - platform: gpio
    name: "Sensor Aberto"
#    pin: 27 #new pin
    pin: 36 #old pin
    id: cover_sensor_aberto
    on_press:
      - delay: 150ms
      - switch.turn_off: cover_rele_abrir
      - switch.turn_off: cover_rele_fonte

  - platform: gpio
    name: "Sensor Fechado"
#    pin: 23 #new pin
    pin: 39 #old pin
    id: cover_sensor_fechado
    on_press:
      - delay: 150ms
      - switch.turn_off: cover_rele_fechar
      - switch.turn_off: cover_rele_fonte

  - platform: gpio
    id: cover_open_button
#    pin: 26 #new pin
    pin: 32 #old pin
    on_press:
      if:
        condition:
          switch.is_on: cover_modo_manual
        then:
          - cover.open: cover_controller
    on_release:
      - cover.stop: cover_controller

  - platform: gpio
    id: cover_close_button
#    pin: 13 #new pin
    pin: 33 #old pin
    on_press:
      if:
        condition:
          switch.is_on: cover_modo_manual
        then:
        - cover.close: cover_controller
    on_release:
      - cover.stop: cover_controller

  - platform: gpio
    id: cover_manual_button
#    pin: 22 #new pin
    pin: 35 #old pin
    on_press:
      - switch.turn_on: cover_modo_manual
    on_release:
      - switch.turn_off: cover_modo_manual

  - platform: template
    id: cover_rain_binary_sensor
    name: "Rainning?"
    lambda: |-
      if (id(rainning) == 0) {
        return true;
      } else {
        return false;
      }

  - platform: template
    id: cover_horizon_binary_sensor
    name: "Below horizon?"
    lambda: |-
      if (id(horizon) == 0) {
        return true;
      } else {
        return false;
      }

  - platform: template
    id: cover_moving
    name: "moving?"
    lambda: |-
      if ((id(cover_sensor_aberto).state == 0) && (id(cover_sensor_fechado).state == 0))  {
        return true;
      } else {
        return false;
      }

switch:
  - platform: gpio
    name: "Rele Fechar"
#    pin: 18 #new pin
    pin: 13 #old pin
    id: cover_rele_fechar

  - platform: gpio
    name: "Rele Abrir"
#    pin: 19 #new pin
    pin: 14 #old pin
    id: cover_rele_abrir

  - platform: gpio
    name: "Rele Fonte"
#    pin: 21 #new pin
    pin: 27 #old pin
    inverted: true
    id: cover_rele_fonte

  - platform: template
    name: "Modo Manual"
    id: cover_modo_manual
    turn_on_action:
        - cover.stop: cover_controller
    optimistic: true

cover:
  - platform: endstop
    name: "Cobertura"
    id: cover_controller
    open_action:
      - switch.turn_off: cover_rele_fechar
      - switch.turn_on: cover_rele_fonte
      - delay: 150ms
      - switch.turn_on: cover_rele_abrir
    open_duration: 63s
    open_endstop: cover_sensor_aberto
    close_action:
      - switch.turn_off: cover_rele_abrir
      - switch.turn_on: cover_rele_fonte
      - delay: 150ms
      - switch.turn_on: cover_rele_fechar
    close_duration: 72s
    close_endstop: cover_sensor_fechado
    stop_action:
      - switch.turn_off: cover_rele_fechar
      - switch.turn_off: cover_rele_abrir
      - switch.turn_off: cover_rele_fonte
    max_duration: 75s
    #optimistic: true
    #assumed_state: true
    #has_position: true

script:
  - id: check_sensors
    then:
      - lambda: |-
          if (id(cover_sensor_chuva).state < id(chuva_limit)) {
            id(rainning) = 0;
            id(previousMillis) = millis();
          }
          else if ((id(cover_sensor_chuva).state > id(chuva_limit)) && (id(rainning) == 0)) {
            if ((millis() - id(previousMillis)) >= id(dry_delay)) {
            id(previousMillis) = 0;
            id(rainning) = 1;
            }
          }


          if (id(rainning) == 0) {
            id(cover_clima).publish_state("CHOVENDO");
          }
          else if ((id(rainning) == 1) && (id(horizon) == 0) && (id(cover_varanda_temp).state <= id(noite_frio))) {
            id(cover_clima).publish_state("NOITE/FRIO");
          }
          else if ((id(rainning) == 1) && (id(horizon) == 0) && (id(cover_varanda_temp).state >= id(noite_quente))) {
            id(cover_clima).publish_state("NOITE/QUENTE");
          }
          else if ((id(rainning) == 1) && (id(horizon) == 1) && (id(cover_varanda_temp).state <= id(dia_frio))) {
            id(cover_clima).publish_state("DIA/FRIO");
          }
          else if ((id(rainning) == 1) && (id(horizon) == 1) && (id(cover_varanda_temp).state >= id(dia_quente))) {
            id(cover_clima).publish_state("DIA/QUENTE");
          }
          else {
            id(cover_clima).publish_state("LIMBO");
          }


      - if:
          condition:
            switch.is_off: cover_modo_manual
          then:
              - lambda: |-
                  if ((id(rainning) == 0) && (id(cover_sensor_fechado).state == 0)) {
                    auto call = id(cover_controller).make_call();
                    call.set_position(0.0);
                    call.perform();
                    id(cover_if_status).publish_state(1);
                  }
                  else if ((id(rainning) == 1) && (id(horizon) == 0) && (id(cover_varanda_temp).state <= id(noite_frio)) && (id(cover_sensor_fechado).state == 0)) {
                      auto call = id(cover_controller).make_call();
                      call.set_position(0.0);
                      call.perform();
                      id(cover_if_status).publish_state(2);
                  }
                  else if ((id(rainning) == 1) && (id(horizon) == 0) && (id(cover_varanda_temp).state >= id(noite_quente)) && (id(cover_sensor_aberto).state == 0)) {
                        auto call = id(cover_controller).make_call();
                        call.set_position(1.0);
                        call.perform();
                        id(cover_if_status).publish_state(3);
                  }
                  else if ((id(rainning) == 1) && (id(horizon) == 1) && (id(cover_varanda_temp).state <= id(dia_frio)) && (id(cover_sensor_fechado).state == 0)) {
                        auto call = id(cover_controller).make_call();
                        call.set_position(0.0);
                        call.perform();
                        id(cover_if_status).publish_state(4);
                  }
                  else if ((id(rainning) == 1) && (id(horizon) == 1) && (id(cover_varanda_temp).state >= id(dia_quente)) && (id(cover_sensor_aberto).state == 0)) {
                        auto call = id(cover_controller).make_call();
                        call.set_position(1.0);
                        call.perform();
                        id(cover_if_status).publish_state(5);
                  }
                  else {
                    id(cover_if_status).publish_state(6);
                  }
                  





      - if:
          condition:
            - sun.is_below_horizon :
          then:
           - globals.set:
               id: horizon
               value: '0'
          else:
           - globals.set:
               id: horizon
               value: '1'

3 curtidas