Esphome oled+capteur (nodemcu)

Salut
J’adore les Nodemcu esp8266 pour me faire mes capteurs en mode full DIY pour un cout extraordinairement…ridiculement bas
J’ai commençé avec Tasmota mais maintenant je passe tout en ESPHOME tellement c’est puissant : on peut mettre un peu de logique dans le code pour éviter de surcharger les automatisations au niveau HA - et en plus j’aime avoir un mode local en bakup

quelques points pour s’y retrouver (il y a pas mal de petits trucs que je me suis mitoné au fil des créations, voila ou j’en suis (mais demandez pas trop des fois je comprends pas tout, mais ça marche…chez moi)

ici :
Capteur température (DS18B20) (j’en ai mis 1 mais on peut en mettre plusieurs a la suite sur le pin)
écran Oled (pour affichage de la température)
un bouton pour allumer l’écran
un économiseur d’écran : automatisme sur l’heure pour éteindre l’écran Toutes les minutes (parce que j’ai pas su faire un timer propre !!..MegaLOL)
un morceau de ruban WS2812 avec 2 led pour des voyants de statut
Le tout monté sur mon fidèle PCB custom « qui facilite bien le job »

# les substitutions c'est super pratique ça permet de rendre le code facilement copiable et cohérent
#et le include pointe directement sur le fichier secrets central de HA  avec le ../
substitutions:
  device: n184
  device_ip: 192.168.1.184
  <<: !include ../secrets.yaml

esphome:  
  name: "${device}_display"
  platform: ESP8266
  board: nodemcuv2
  
#super utile le tag on_boot pour les initialisations, E/S, voyants indicateur (wifi,....)
  on_boot:
    - priority: 600.0 # after sensor setup, before WIFI initialization 
      then:
        - light.turn_on:
            id: "${device}_p1"
            brightness: 25%
            red: 50%
            green: 0%
            blue: 0%
        - light.turn_on:
            id: "${device}_p2"
            brightness: 50%
            red: 100%
            green: 0%
            blue: 0%    
        - switch.turn_on:
            id: "${device}_screen"
    - priority: -1000.0 #after wifi initialized
      then:
        if:
          condition:
            wifi.connected:
          then:
            - light.turn_on:
                id: "${device}_p1"
                brightness: 25%
                red: 0%
                green: 25%
                blue: 0%    
######################   WIFI 
wifi:
  ssid: ${wifi_ssid}
  password: ${wifi_password}
  manual_ip:
    static_ip: ${device_ip}
    gateway: 192.168.1.1
    subnet: 255.255.255.0
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "recovery_${device}"
    password: "a1b2c3d4"

captive_portal:

web_server:
  port: 80
# Enable logging
logger:

# Enable Home Assistant API
api:
#  password: "a1b2c3d4"  mdp DE l ESP pour acceder a l'esp depuis home assistant

ota:
######################   Initialisations, on peut récupérer des variable home assistant
# et en plus c'est la qu'on mets les trucs qui peuvent se déclencher en automatique 
# (ici a chaque minute je teste le wifi et je force l'extinction pour l'économiseur d'écran )
time:
  - platform: homeassistant
    id: ha_time
    on_time:
      - seconds: 0
        minutes: '*'
        then:
          - switch.turn_off: "${device}_screen"
          - light.turn_off: "${device}_p2"          
          - if:
              condition:
                wifi.connected:
              then:
                - light.turn_on:
                    id: "${device}_p1"
                    brightness: 25%
                    red: 0%
                    green: 25%
                    blue: 0%
              else:
                - light.turn_on:
                    id: "${device}_p1"
                    brightness: 50%
                    red: 100%
                    green: 0%
                    blue: 0%
              
########################### Déclaration protocoles DALLAS  + I2C
dallas:
  - pin: D5 #GPIO14 - Sensor IOT
    update_interval: 60s
    
i2c:
  sda: D2
  scl: D1
# important pour faire marcher l'écran
# faut pas oublier de télécharger une font et la mettre dans le rep qui va bien
font:
  - file: "Roboto-Regular.ttf"
    id: roboto
    size: 20
    
# la, beaucoup d'essai erreur avec le lamda pour faire marcher
# j'ai une variable pour controler l'allumage de l'écran
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    address: 0x3C
    id: my_display
    lambda: |-
      if (id(n184_screen).state) {
        it.print(0, 0, id(roboto), "ESP_OLED :");
        it.printf(127, 30, id(roboto), TextAlign::TOP_RIGHT, "T : %.1f°C", id(n184_temp_ds18b20).state);
      } else {
        it.printf(0, 0, id(roboto), TextAlign::TOP_RIGHT, "---------");
      }


##### declaration DS18B20 1 et 2  +    TC Max 6675         +      Analog A0     +     Pixel WS2812  D4
switch:
  - platform: restart
    name: "${device}_Restart"
    
  - platform: gpio
    name: "${device}_screen"
    id: "${device}_screen"
    pin: D6
    
#  avant j'avais une bete led R+G+B prenant 3 sorties.... l'idiot !!!!
# qui dit mieux plein (ici 2) led RGB controlables avec 1 seul pin, vive les WS2812
light:
  - platform: fastled_clockless
    chipset: WS2811
    pin: D4
    num_leds: 2
    rgb_order: GRB
    name: "n184_ws2812"
    id: "${device}_ws2812"
    internal: true
    
  - platform: partition
    name: "${device}_p1"
    id: "${device}_p1"
    segments:
      - id: "${device}_ws2812"
        from: 0
        to: 0
  - platform: partition
    name: "${device}_p2"
    id: "${device}_p2"
    segments:
      - id: "${device}_ws2812"
        from: 1
        to: 1
# le reste est plus simple : un bouton (avec une automatisation sur l'activation)
binary_sensor:
  - platform: status
    name: "${device}_Status"
    
  - platform: gpio
    pin: D7
    name: "${device}_Tac_BTN"
    id: "${device}_tact_btn"
    on_press:
      - light.toggle: "${device}_p2"
  - platform: gpio
    pin: D7
    name: "${device}_tactbtnN"
    id: "${device}_tactbtn"
    on_press:
      - switch.turn_on: "${device}_screen"
    
sensor:
  - platform: wifi_signal
    name: "${device}_WiFi"
    update_interval: 60s
  - platform: uptime
    name: "${device}_Uptime"
    
  - platform: dallas
    index: 0 #address: 0x0D8000001F97B428  #index: 0
    name: "${device}_temp_ds18b20"
    id: "${device}_temp_ds18b20"

  - platform: homeassistant
    name: "Temp.Exter"
    id: temp_exter
    entity_id: sensor.node_177_ds18b20_2_temperature
    internal: true
    
text_sensor:
  - platform: homeassistant
    name: "Météo"
    entity_id: weather.maison
    id: meteo
    internal: true

prochaine étape :
step up the game

quelques photos :

4 « J'aime »

Bonjour Yvan,

comment tu intègres le component display pour activer le oled ssd1306?

slt

Renaud

Bonjour

j’ai bricolé a partir de tutos trouvés au hasard de mes recherches, et finalement ça a a peu près marché comme je voulais - voir le code de mon thermostat en bas du mail pour mon appli « frigo »

le plus compliqué (AMHA) c’est :

  • bien récupérer la (ou les) font en fichier TTF a utiliser et les mettre la ou esphome les veut (
    (il faut un fichier + déclarer chaque taille utilisée)
  • être sur de l’adresse Hexa de l’ecran (chez moi 0x3c) qio peut être récuperée en vert sur le log du boot de l’ESP
  • être sur du modele exact de l’écran dans le code yaml de l’ESP
  • comprendre la syntaxe du « lambda » d’affichage (ou pomper sans trop changer si comme moi on comprends pas bien)
  • Déclarer l’interface I2C avec les pins / déclarer les font / déclarer le display

Prochaine amélioration : Mettre un détecteur de mouvement et Piloter l’allumage de l’écran seulement par un bouton, ou mieux, si il y a une présence devant (pour éviter de cramer l’écran avec un allumage en continu)
(exemple par un capteur zigbee dont l’ESP va récupérer la valeur dans HA, soit par un capteur de mouvement embarqué sur l’ESP (il me reste qq E/S sur le nodemcu)

détail du code avec le lambda pour piloter l’affichage (ou pas) suivant une variable déclarée comme un switch « n184_screen » qui peut être à On ou Off (commandé en interne, par HA ou sur un timer:
il y a surement une meilleur methode, mais la mienne marche

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    address: 0x3C
    id: my_display
    lambda: |-
      if (id(n184_screen).state) {
        it.print(0, 0, id(roboto), "PISCINE :");
        it.printf(128, 21, id(roboto_big), TextAlign::TOP_RIGHT, "%.1f°C", id(temp_piscine).state);
      } else {
        it.printf(0, 0, id(roboto), TextAlign::TOP_RIGHT, "---------");
      }

Code complet de l’ESP frigo :

substitutions:
  device: n182
  device_ip: 192.168.1.182
  <<: !include ../secrets.yaml

esphome:  
  name: "${device}_frigo_display"
  platform: ESP8266
  board: nodemcuv2
  
  on_boot:
    - priority: 600.0 # after sensor setup, before WIFI initialization 
      then:
        - light.turn_on:
            id: "${device}_p1"
            brightness: 25%
            red: 50%
            green: 0%
            blue: 0%
        - light.turn_on:
            id: "${device}_p2"
            brightness: 50%
            red: 100%
            green: 0%
            blue: 0%
            
    - priority: -500.0
      then:
        - climate.control:
            id: "${device}_climate"
            mode: COOL
            target_temperature: 8°C


    - priority: -1000.0 #after wifi initialized
      then:
        if:
          condition:
            wifi.connected:
          then:
            - light.turn_on:
                id: "${device}_p1"
                brightness: 25%
                red: 0%
                green: 25%
                blue: 0%
            - light.turn_off:
                id: "${device}_p2"
            - switch.turn_on: "${device}_screen"  # allumage de l'écran au boot
######################   WIFI 
wifi:
  ssid: ${wifi_ssid}
  password: ${wifi_password}
  manual_ip:
    static_ip: ${device_ip}
    gateway: 192.168.1.1
    subnet: 255.255.255.0
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "recovery_${device}"
    password: "a1b2c3d4"

captive_portal:

web_server:
  port: 80
# Enable logging
logger:

# Enable Home Assistant API
api:
#  password: "a1b2c3d4"  mdp DE l ESP pour acceder a l'esp depuis home assistant

ota:
######################   Initialisations
time:
  - platform: homeassistant
    id: ha_time
    on_time:
      - seconds: 0
        minutes: '*'
        then:
#          - switch.turn_off: "${device}_screen"
          - light.turn_off: "${device}_p2"          
          - if:
              condition:
                wifi.connected:
              then:
                - light.turn_on:
                    id: "${device}_p1"
                    brightness: 25%
                    red: 0%
                    green: 25%
                    blue: 0%
              else:
                - light.turn_on:
                    id: "${device}_p1"
                    brightness: 50%
                    red: 100%
                    green: 0%
                    blue: 0%
              
########################### Déclaration protocoles DALLAS  + I2C
dallas:
  - pin: D5 #GPIO14 - Sensor IOT
    update_interval: 60s
    
i2c:
  sda: D2
  scl: D1

font:
  - file: "Roboto-Regular.ttf"
    id: roboto
    size: 20
    
  - file: "Roboto-Regular.ttf"
    id: roboto_big
    size: 40
    
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    address: 0x3C
    id: my_display
    lambda: |-
      if (id(n182_screen).state) {
        it.print(0, 0, id(roboto), "FRIGO :");
        it.printf(128, 21, id(roboto_big), TextAlign::TOP_RIGHT, "%.1f°C", id(temp_frigo).state);
      } else {
        it.printf(0, 0, id(roboto), TextAlign::TOP_RIGHT, "---------");
      }


##### declaration DS18B20 1 +    +    Pixel WS2812  D4
output:
  - platform: gpio
    pin: D7
    id: "${device}_relay"

switch:
  - platform: restart
    name: "${device}_Restart"
    
  - platform: gpio
    name: "${device}_screen"    #bouton allumage ecran pin virtual 
    id: "${device}_screen"
    pin: D6

  - platform: output
    name: "Relay"
    id: "relay"
    output: "${device}_relay"
    
light:
  - platform: fastled_clockless
    chipset: WS2811
    pin: D4
    num_leds: 2
    rgb_order: GRB
    name: "${device}_ws2812"
    id: "${device}_ws2812"
    internal: true
    
  - platform: partition
    name: "${device}_p1"
    id: "${device}_p1"
    segments:
      - id: "${device}_ws2812"
        from: 0
        to: 0
  - platform: partition
    name: "${device}_p2"
    id: "${device}_p2"
    segments:
      - id: "${device}_ws2812"
        from: 1
        to: 1

binary_sensor:
  - platform: status
    name: "${device}_Status"
    
#  - platform: gpio
#    pin: D7
#    name: "${device}_Tac_BTN"
#    id: "${device}_tact_btn"
#    on_press:
#      - light.toggle: "${device}_p2"

    
sensor:
  - platform: wifi_signal
    name: "${device}_WiFi"
    update_interval: 60s
  - platform: uptime
    name: "${device}_Uptime"
    
  - platform: homeassistant
    name: "temp_frigo"
    id: temp_frigo
    entity_id: sensor.z_lumi_th02_temperature
#    internal: true

#  - platform: homeassistant
#    name: "HA_MS_sensor"
#    id: ha_ms_sensor
#    entity_id: sensor.z_lumi_th02_temperature
#    internal: true
    
  - platform: dallas
    index: 0 #address: 0x0D8000001F97B428  #index: 0
    name: "${device}_temp_ds18b20"
    id: "${device}_temp_ds18b20"

climate:
  - platform: thermostat
    name: "Frigo.Climate"
    id: "${device}_climate"
    sensor: temp_frigo       #"${device}_temp_ds18b20"
    min_idle_time: 1 min
    min_cooling_off_time: 1 min
    min_cooling_run_time: 1 min
    default_target_temperature_high: 8 °C
    
#    hysteresis: 0.2 °C
    visual:
      min_temperature: 2 °C
      max_temperature: 24 °C
      temperature_step: 0.5 °C

    cool_action:
      - switch.turn_on: relay 
      - light.turn_on:
          id: "${device}_p2"
          brightness: 50%
          red: 00%
          green: 00%
          blue: 50%   
#      - switch.turn_off: relay_2
    idle_action:
      - switch.turn_off: relay
      - light.turn_on:
          id: "${device}_p2"
          brightness: 25%
          red: 00%
          green: 25%
          blue: 00%   
#      - switch.turn_on: relay_2