Este tutorial trata-se da instalação de sensor ultrassônico na caixa de água para medir o volume da mesma integrado ao home assistant e entidades de alerta para volume mínimo e máximo.
O código deste tutorial aplica-se a caixas de água com formato como o mostrado na figura a seguir:
O cálculo do volume da caixa será aproximado para a forma de um tronco de cone.
O volume máximo calculado para a caixa será o volume útil (volume utilizável) com base nas características da mesma (principalmente a posição que a boia fecha e a posição das tubulações de saída e do extravasor/ladrão), sendo que pode ser diferente do volume nominal da caixa.
O volume morto é o volume de água que está abaixo da tubulação de saída.
1. Materiais utilizados:
- Nodemcu (esp8266)
- Fonte 5V HiLink HLK-PM01
- Módulo de sensor ultrasônico JSN-SR04T ou JSN-SR20-Y1.
A principal diferança entre os dois sensores é que o modelo JSN-SR04T tem uma distância mínima de medição de aproximadamente 25 cm (na prática trabalha bem até 22~23 cm) e o modelo JSN-SR20-Y1 a distância mínima é de 2 cm (ainda não testei para validar). Logo você deve avaliar a distância que o sensor ficará do nível máximo da caixa para escolher.
2. Ligação do sensor:
A ligação do sensor ao nodemcu é bem simples:
- Ligar o pino 5V do sensor ao pino aos 5V da fonte ou ao pino Vin do nodemcu.
- Ligar o pino Trig do sensor ao pino D6 do nodemcu.
- Ligar o pino Echo do sensor ao pino D7 do nodemcu.
- Ligar o pino GND do sensor a um pino GND do nodemcu.
Atenção: A ligação do sensor diretamente no pino do NodeMCU/ESP pode diminuir a vida útil do NodeMCU/ESP. Apesar de funcionar sem, é recomendado instalar um level shift converter de 5V para 3.3V.
O sensor deve ser instalado na parte central da tampa da caixa.
3. Informações da instalação e caixa de água:
É necessário obter alguns parâmetros físicos da caixa de água para o cálculo correto do nível e volume de água, a imagem abaixo mostra cada informação necessária com a respectiva sigla da configuração no código:
Configurando os parâmetros físicos da caixa, este código se aplica ao cálculo do volume de caixas deste formato independente do capacidade da mesma (um ponto a se observar é a distância máxima que o sensor é capaz de medir).
4. Código ESPHOME:
Confirme os pinos ligados ao sensor, altere os parâmetros físicos da caixa de água e realize as configurações de rede.
A configuração do sensor ultrasônico no código está para utilizar a medida resultante da mediana móvel de 20 valores que são atualizados a casa 0,5 segundo. Isso descarta eventuais leituras com erros extremos, porém o tempo para o sensor refletir o novo nível será de 10 segundos.
substitutions:
#Configurações da placa:
Plataforma: ESP8266
TipoPlaca: d1_mini
#Configurações do dispositivo:
hostname: 'caixaagua' #Hostname do dispositivo na rede
PrefixoNome: "Caixa Água - "
#Configurações da Rede:
RedeWifi: !secret RedeWifi #Nome da rede wifi que o dispositivo irá se conectar
SenhaWifi: !secret SenhaWifi #Senha da rede wifi que o dispositivo irá se conectar
SenhaWifiReconfig: !secret SenhaWifiReconfig #Senha do AP Wifi para reconfiguração do wifi do dispositivo
EndConfig: ${hostname}.local #192.168.1.50 #Endereço para configuração (IP que o esp está acessível atualmente na rede), especialmente usado quando quer alterar o hostname via OTA
WifiOculto: 'False' #Se a rede wifi está oculta defina como 'True'
WifiFastConnect: 'False' #Se o esp realizará a conexão à rede wifi sem escanear as redes disponíveis defina como 'True'
#Senhas
SenhaAPI: !secret SenhaAPI #Senha para adicionar o esp no HA
SenhaOTA: !secret SenhaOTA #Senha para atualizar o firmware do esp via OTA
#Pinos do Sensor
SensorTriggerPin: D6
SensorEchoPin: D7
#INFORMAÇÕES FÍSICAS DA CAIXA E DA INSTALAÇÃO DO SENSOR (medidas em metros):
#Diametro interno da base da caixa (fundo)
DD1: "0.95"
#Diametro interno da borda superior sem a tampa
DM: "1.22"
#Distância entre o fundo da caixa e a borda sem a tampa
HB: "0.58"
#Distância entre o fundo da caixa e a borda superior da tampa (onde o sensor será instalado)
HT: "0.72"
#Distância entre o fundo da caixa e o nível da base da tubulação de saída (altura da coluna de água do nível morto)
HMT: "0.038"
#Distância entre o fundo da caixa e o nível máximo normal (altura da água onde a boia é fechada)
HM: "0.54"
#Distância entre o sensor e o nível máximo normal (altura onde a boia é fechada até o sensor)
HS: "0.22"
#Distância entre o fundo da caixa e o nível de transbordamento (ou nível do extravasor/ladrão, o que o ocorrer primeiro)
HMA: "0.55"
#Logger
LoggerUART: UART0_SWAP
LoggerLevel: DEBUG
esphome:
name: $hostname
platform: ${Plataforma}
board: ${TipoPlaca}
wifi:
networks:
- ssid: ${RedeWifi}
password: ${SenhaWifi}
hidden: ${WifiOculto}
fast_connect: ${WifiFastConnect}
use_address: ${EndConfig}
# Enable fallback hotspot (captive portal) in case wifi connection fails
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:
hardware_uart: ${LoggerUART}
level: ${LoggerLevel}
#Habilita a api para comunicar com o Home Assistant
api:
password: ${SenhaAPI}
switch:
############################# SENSORES DEVICE ##################################
#Comando reinicilizar esp remotamente
- platform: restart
id: ${hostname}_restart
name: ${PrefixoNome} Reiniciar
icon: mdi:restart
text_sensor:
############################# SENSORES DEVICE ##################################
#Informações da conexão wifi
- platform: wifi_info
#Endereço IP
ip_address:
id: ${hostname}_IP
name: ${PrefixoNome} Endereço IP
icon: mdi:ip-network
#Nome da Rede
ssid:
id: ${hostname}_SSID
name: ${PrefixoNome} Rede Wifi
icon: mdi:wifi
#Informação da versão da compilação
- platform: version
id: ${hostname}_versao
name: ${PrefixoNome} Versão
icon: mdi:information
binary_sensor:
############################# SENSORES DEVICE ##################################
#Status (conectado ou desconectado)
- platform: status
id: ${hostname}_status
name: ${PrefixoNome} Status
device_class: connectivity
############################# ALERTA DE NIVEIS #################################
#Nível mínimo de alerta
- platform: template
id: NAMIN
name: ${PrefixoNome} Nível Mínimo de Alerta
##internal: True
lambda: |-
if (id(VAGUAP).state <= id(AMIN).state) {
return true;
} else {
return false;
}
#Nível máximo de alerta
- platform: template
id: NAMAX
name: ${PrefixoNome} Nível Máximo de Alerta
##internal: True
lambda: |-
if (id(VAGUAP).state >= id(AMAX).state) {
return true;
} else {
return false;
}
#Erro medição
- platform: template
id: ERRO_MED
name: ${PrefixoNome} Erro Medição
#internal: True
lambda: |-
if (((id(HMED).state>((id(HM).state+id(HS).state)))) or (id(HMED).state<id(HS).state)) {
return true;
} else {
return false;
}
sensor:
############################# SENSORES DEVICE ##################################
#Sensor Intensidade Sinal Wifi
- platform: wifi_signal
id: ${hostname}_wifi_sinal
name: ${PrefixoNome} Intensidade Wifi
icon: mdi:signal
update_interval: 10s
############################ IMPORT VARIAVÉIS HA ###############################
- platform: homeassistant
id: AMIN
name: ${PrefixoNome} Nível Mínimo de Alerta
internal: true #false Apenas para debug
entity_id: input_number.caixa_agua_alerta_nivel_minimo
accuracy_decimals: 2
- platform: homeassistant
id: AMAX
name: ${PrefixoNome} Nível Máximo de Alerta
internal: true #false Apenas para debug
entity_id: input_number.caixa_agua_alerta_nivel_maximo
accuracy_decimals: 2
############################ SENSOR ULTRASONICO ################################
- platform: ultrasonic
id: HMED
trigger_pin: ${SensorTriggerPin}
echo_pin: ${SensorEchoPin}
name: ${PrefixoNome} Distância Medida Sensor
internal: false
accuracy_decimals: 6
update_interval: 0.5s
filters:
- median:
window_size: 20
send_every: 20
send_first_at: 20
#################### INFORMAÇÕES FÍSICAS DA INSTALAÇÃO #########################
#Diametro interno da base da caixa (fundo)
- platform: template
id: DD1
name: ${PrefixoNome} Diâmentro Interno Base
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return ${DD1};
accuracy_decimals: 4
update_interval: 1s
#Diametro interno da borda superior sem a tampa
- platform: template
id: DM
name: ${PrefixoNome} Diâmetro Interno Superior
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return ${DM};
accuracy_decimals: 4
update_interval: 1s
#Distância entre o fundo da caixa e a borda sem a tampa
- platform: template
id: HB
name: ${PrefixoNome} Altura Interna até a borda
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return ${HB};
accuracy_decimals: 4
update_interval: 1s
#Distância entre o fundo da caixa e a borda superior da tampa (onde o sensor será instalado)
- platform: template
id: HT
name: ${PrefixoNome} Altura com Tampa
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return ${HT};
accuracy_decimals: 4
update_interval: 1s
#Distância entre o fundo da caixa e o nível da base da tubulação de saída (altura da coluna de água do nível morto)
- platform: template
id: HMT
name: ${PrefixoNome} Coluna de Água Nível Morto
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return ${HMT};
accuracy_decimals: 4
update_interval: 1s
#Distância entre o fundo da caixa e o nível máximo normal (altura da água onde a boia é fechada)
- platform: template
id: HM
name: ${PrefixoNome} Coluna de Água Útil
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return ${HM};
accuracy_decimals: 4
update_interval: 1s
#Distância entre o sensor e o nível máximo normal (altura onde a boia é fechada até o sensor)
- platform: template
id: HS
name: ${PrefixoNome} Distância Sensor Nível Máximo
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return ${HS};
accuracy_decimals: 4
update_interval: 1s
#Distância entre o fundo da caixa e o nível de transbordamento (ou nível do extravasor/ladrão, o que o ocorrer primeiro)
- platform: template
id: HMA
name: ${PrefixoNome} Coluna de Água Transbordamento
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return ${HMA};
accuracy_decimals: 4
update_interval: 1s
######################### CÁLCULOS AUXILIARES ##################################
#Coluna de água medida (descontado a distância do sensor)
- platform: template
id: H
name: ${PrefixoNome} Coluna de Água Atual
internal: false
unit_of_measurement: m
lambda: return (id(HM).state+id(HS).state-id(HMED).state);
accuracy_decimals: 4
update_interval: 1s
#Raio menor do reservatório
- platform: template
id: R1
name: ${PrefixoNome} Raio Menor
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return (id(DD1).state/2);
accuracy_decimals: 4
update_interval: 1s
#Raio maior máximo do reservatório
- platform: template
id: RM
name: ${PrefixoNome} Raio Maior Máximo Físico
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return (id(DM).state/2);
accuracy_decimals: 4
update_interval: 1s
#Raio maior máximo de acordo com o nível máximo de água
- platform: template
id: R2M
name: ${PrefixoNome} Raio Maior com Nível Máximo
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return (id(R1).state+(id(HM).state*tan(atan(((id(DM).state-id(DD1).state)/2)/(id(HB).state)))));
accuracy_decimals: 4
update_interval: 1s
#Raio maior atual do reservatório (de acordo com o nível da água)
- platform: template
id: R2
name: ${PrefixoNome} Raio Maior com o Nível Atual
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return (id(R1).state+(id(H).state*tan(atan(((id(DM).state-id(DD1).state)/2)/(id(HB).state)))));
accuracy_decimals: 4
update_interval: 1s
#Raio maior o volume morto
- platform: template
id: RHMT
name: ${PrefixoNome} Raio Maior no Nível Mínimo
internal: true #false Apenas para debug
unit_of_measurement: m
lambda: return (id(R1).state+(id(HMT).state*tan(atan(((id(DM).state-id(DD1).state)/2)/(id(HB).state)))));
accuracy_decimals: 4
update_interval: 1s
########################## CÁLCULOS DOS VOLUMES#################################
#Volume com o reservatório cheio (altura da borda)
- platform: template
id: VTT
name: ${PrefixoNome} Volume com o Reservatório Cheio
internal: true
unit_of_measurement: litros
lambda: return ((1.047197*id(HB).state)*((id(RM).state*id(RM).state)+(id(RM).state*id(R1).state)+(id(R1).state*id(R1).state))*1000)-id(VMT).state;
accuracy_decimals: 0
update_interval: 1s
#Volume de água do volume morto (abaixo da saída)
- platform: template
id: VMT
name: ${PrefixoNome} Volume Morto
internal: false
unit_of_measurement: litros
lambda: return ((1.047197*id(HMT).state)*((id(RHMT).state*id(RHMT).state)+(id(RHMT).state*id(R1).state)+(id(R1).state*id(R1).state))*1000);
accuracy_decimals: 0
update_interval: 1s
#Volume de água com o nível máximo
- platform: template
id: VT
name: ${PrefixoNome} Volume com o Nível Máximo
internal: false
unit_of_measurement: litros
lambda: return ((1.047197*id(HM).state)*((id(R2M).state*id(R2M).state)+(id(R2M).state*id(R1).state)+(id(R1).state*id(R1).state))*1000)-id(VMT).state;
accuracy_decimals: 0
update_interval: 1s
#Volume de Água
- platform: template
id: VAGUA
name: ${PrefixoNome} Volume
unit_of_measurement: litros
lambda: |-
if ( (((1.047197*id(H).state)*((id(R2).state*id(R2).state)+(id(R2).state*id(R1).state)+(id(R1).state*id(R1).state))*1000)-id(VMT).state) <0 ) {
return 0;
} else if ( (((1.047197*id(H).state)*((id(R2).state*id(R2).state)+(id(R2).state*id(R1).state)+(id(R1).state*id(R1).state))*1000)-id(VMT).state) > id(VTT).state) {
return id(VTT).state;
} else {
return (((1.047197*id(H).state)*((id(R2).state*id(R2).state)+(id(R2).state*id(R1).state)+(id(R1).state*id(R1).state))*1000)-id(VMT).state);
}
accuracy_decimals: 0
update_interval: 1s
#Volume Percentual
- platform: template
id: VAGUAP
name: ${PrefixoNome} Volume Percentual
unit_of_measurement: "%"
lambda: return ((id(VAGUA).state / id(VT).state)*100);
accuracy_decimals: 1
update_interval: 1s
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).
4. Criação dos input number:
Código para os input number de configuração do alerta de nível (os mesmos id_entity usados aqui devem ser usados no código do esphome, nos ids AMIN e AMAX):
input_number:
caixa_agua_alerta_nivel_minimo:
icon: mdi:percent
name: Caixa de Água Nível Mínimo
min: 0
max: 110
step: 1
mode: slider
caixa_agua_alerta_nivel_maximo:
icon: mdi:percent
name: Caixa de Água Nível Máximo
min: 0
max: 110
step: 1
mode: slider
Você pode criar os input number incluindo o código acima no arquivo de configuração do home assistant ou manualmente acessando Configurações > Ajudantes > Adicionar Ajudante > Número.
5. Lovelace
Card para exibir as principais informações sobre o nível no lovelace:
Código:
type: grid
columns: 1
title: Caixa de Água
cards:
- type: grid
columns: 2
cards:
- type: entity
entity: sensor.caixa_agua_volume
state_color: true
name: Volume
icon: mdi:water
- type: entity
entity: binary_sensor.caixa_agua_erro_medicao
state_color: true
name: Erro de Medição
icon: mdi:water-alert
square: false
- type: gauge
entity: sensor.caixa_agua_volume_percentual
min: 0
max: 100
needle: true
severity:
green: 75
yellow: 25
red: 0
name: Volume Percentual
- type: entities
entities:
- entity: input_number.caixa_agua_alerta_nivel_maximo
icon: mdi:water-percent-alert
- entity: binary_sensor.caixa_agua_nivel_maximo_de_alerta
icon: mdi:water-alert-outline
- entity: input_number.caixa_agua_alerta_nivel_minimo
icon: mdi:water-percent-alert
- entity: binary_sensor.caixa_agua_nivel_minimo_de_alerta
icon: mdi:water-alert-outline
state_color: true
title: Níveis de Alerta
square: false
Card simples para exibir todas as entidades implementadas no lovelace:
Código:
type: grid
columns: 1
title: Caixa de Água
cards:
- type: entities
entities:
- binary_sensor.caixa_agua_erro_medicao
- sensor.caixa_agua_volume
- sensor.caixa_agua_volume_percentual
- sensor.caixa_agua_volume_com_o_nivel_maximo
- sensor.caixa_agua_volume_morto
title: Volume
- type: entities
entities:
- entity: sensor.caixa_agua_distancia_medida_sensor
- entity: sensor.caixa_agua_coluna_de_agua_atual
title: Sensor
- type: entities
entities:
- entity: input_number.caixa_agua_alerta_nivel_maximo
- entity: input_number.caixa_agua_alerta_nivel_minimo
- entity: binary_sensor.caixa_agua_nivel_maximo_de_alerta
- entity: binary_sensor.caixa_agua_nivel_minimo_de_alerta
title: Níveis de Alerta
- type: entities
entities:
- entity: binary_sensor.caixa_agua_status
- entity: sensor.caixa_agua_rede_wifi
- entity: sensor.caixa_agua_intensidade_wifi
- entity: sensor.caixa_agua_endereco_ip
- entity: switch.caixa_agua_reiniciar
- entity: sensor.caixa_agua_versao
title: Informações do Dispositivo
square: false
6. Erro de Medição:
A entidade erro de medição para ser verdadeira verifica uma das seguintes condições:
- Se a distância medida pelo sensor é maior que a altura do nível máximo + a distância do sensor ao nível máximo.
- Se a distância medida pelo sensor é menor que a distância entre o sensor e o nível máximo.