ESPHome + LCD ili9341

Bonjour,

en premier lieu je remercie les aides pour pouvoir monter ce petit projet.

  • Un écran OLED 3.2 pouces à 5€45 sur Aliexpress
  • Un ESP32-WROOM-32S 32D ESP 32 à 3€53 sur Aliexpress

Reste à l’intégrer dans un boitier.

Mon objectif est d’avoir sur mon bureau (ou ailleurs) un petit écran me donnant des informations, pour moi, essentielles.
Je n’utilise pas le tactile, je fais un slider sur 4 pages

  • Page 1 me donnant des informations sur mes températures, hygrométrie des pièces (bureau, chambre, chambre d’amis, cuisine, à l’extérieur, devant et dans le jardin)
  • Page 2 me donnant des informations sur les deux personnes du foyer (mon épouse et moi même), avec la charge du téléphone, si nous sommes dans une des deux voitures, et la géolocalisation
  • Page 3 me donnant des informations sur mon abonnement TEMPO
  • Page 4 avec date, heure et éphéméride du jour et du lendemain

Ce que j’ai eu besoin

  • script python pour récupérer les ‹ saints ›

Si le projet vous intéresse, ou si vous avez des conseils.
Je pense ajouter une page sur la consommation du compteur, comme ce qui se présente sur Energie sur HM en gros.

3 « J'aime »

Bonjour

Je sais pas si c’est possible pour toi, mais peux tu détailler ton projet un peu plus ?

Schéma de cablage,Code utilisé, lien des produits utilisés et lien utile pour la réalisation de ce projet

Merci

MATERIEL

  • ESP32 sur Aliexpress [Lien]
  • LCD ILI9341 2.8 pouces [lien]
  • Cable femelle/femelle 10cm [lien]

CABLAGE

SCRIPT PYTHON

  • Infos du jour [lien]

CODE esp-affichage.yaml

time:
  - platform: homeassistant
    id: esptime

esphome:
  name: esp-affichage
  friendly_name: esp-affichage  
  
esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "X3tSsqsyHPK2e3KyiHHxgjgLQdDPPKAJYCf8b/JWLjo="

ota:
  password: "080de7bf5f81b03b41384214726ecc00"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp-Affichage Fallback Hotspot"
    password: "Thj37Xq8iNsN"

captive_portal:
    # Example configuration entry

web_server:
  port: 80

psram:
  mode: octal
  speed: 80MHz

spi:
  clk_pin: GPIO18 # (Pin on display - SCK/T_CLK)
  mosi_pin: GPIO23 # (Pin on display - SDI(MOSI)/T_DIN)
  miso_pin: GPIO19 # (Pin on display - SDO(MISO)/T_DO)



display:
  - platform: ili9xxx  
    model: ili9341    

    rotation: 0
    cs_pin: GPIO15  # Broche CS (Chip Select)
    dc_pin: GPIO05  # Broche DC (Data/Command)
    reset_pin: GPIO04  # Broche de réinitialisation    
    dimensions: 320x240
    update_interval: 1s
    color_order: rgb

   
    id: my_display    
    pages:
      - id: page1
        lambda: |-
          auto cadre = Color(113, 113, 113);
          auto jaune = Color(250, 255, 143);
          auto bureau = Color(200, 255, 178);
          auto chambre = Color(178, 255, 226);
          auto ami = Color(178, 183, 255);
          auto cuisine = Color(255, 255, 178);
          auto avant = Color(251, 139, 255);
          auto arriere = Color(145, 255, 139);

          it.filled_rectangle(10, 20, 100, 100, bureau);
          it.filled_rectangle(110, 20, 100, 100, chambre);
          it.filled_rectangle(210, 20, 100, 100, ami);
          it.filled_rectangle(10, 120, 100, 100, cuisine);
          it.filled_rectangle(110, 120, 100, 100, avant);
          it.filled_rectangle(210, 120, 100, 100, arriere);


          it.rectangle(10, 20, 100, 100, cadre);
          it.rectangle(110, 20, 100, 100, cadre);
          it.rectangle(210, 20, 100, 100, cadre);

          it.rectangle(10, 120, 100, 100, cadre);
          it.rectangle(110, 120, 100, 100, cadre);
          it.rectangle(210, 120, 100, 100, cadre);

          it.print(42, 26, id(temperature), my_black, "\U000F07C0");          
          it.print(14, 60, id(material20), my_black, "\U000F050F");
          it.printf(26, 60, id(font_temperature), my_black, " %5.1f°", id(temperature_bureau).state);
          it.print(14, 80, id(material20), my_black, "\U000F1503");
          it.printf(26, 80, id(font_temperature), my_black, " %5.1f%%", id(hygro_bureau).state);
          it.print(14, 100, id(material20), my_black, "\U000F17E3");
          it.printf(26, 100, id(font_temperature), my_black, " %5.1f%%", id(batterie_bureau).state);
          
          it.print(142, 26, id(temperature), my_black, "\U000F0099");          
          it.print(114, 60, id(material20), my_black, "\U000F050F");
          it.printf(126, 60, id(font_temperature), my_black, " %5.1f°", id(temperature_chambre).state);
          it.print(114, 80, id(material20), my_black, "\U000F1503");
          it.printf(126, 80, id(font_temperature), my_black, " %5.1f%%", id(hygro_chambre).state);
          it.print(114, 100, id(material20), my_black, "\U000F17E3");
          it.printf(126, 100, id(font_temperature), my_black, " %5.1f%%", id(batterie_chambre).state);

          it.print(242, 26, id(temperature), my_black, "\U000F0097");          
          it.print(214, 60, id(material20), my_black, "\U000F050F");
          it.printf(226, 60, id(font_temperature), my_black, " %5.1f°", id(temperature_chambre_ami).state);
          it.print(214, 80, id(material20), my_black, "\U000F1503");
          it.printf(226, 80, id(font_temperature), my_black, " %5.1f%%", id(hygro_chambre_ami).state);
          it.print(214, 100, id(material20), my_black, "\U000F17E3");
          it.printf(226, 100, id(font_temperature), my_black, " %5.1f%%", id(batterie_chambre_ami).state);

          it.print(42, 126, id(temperature), my_black, "\U000F1061");          
          it.print(14, 160, id(material20), my_black, "\U000F050F");
          it.printf(26, 160, id(font_temperature), my_black, " %5.1f°", id(temperature_cuisine).state);
          it.print(14, 180, id(material20), my_black, "\U000F1503");
          it.printf(26, 180, id(font_temperature), my_black, " %5.1f%%", id(hygro_cuisine).state);
          it.print(14, 200, id(material20), my_black, "\U000F17E3");
          it.printf(26, 200, id(font_temperature), my_black, " %5.1f%%", id(batterie_cuisine).state);

          it.print(142, 126, id(temperature), my_black, "\U000F0F9B");          
          it.print(114, 160, id(material20), my_black, "\U000F050F");
          it.printf(126, 160, id(font_temperature), my_black, " %5.1f°", id(temperature_avant).state);

          it.print(242, 126, id(temperature), my_black, "\U000F09F0");          
          it.print(214, 160, id(material20), my_black, "\U000F050F");
          it.printf(226, 160, id(font_temperature), my_black, " %5.1f°", id(temperature_arriere).state);
          
      - id: page2
        lambda: |-
          auto white = Color(255, 255, 255);
          it.rectangle(0,  0, it.get_width(), it.get_height());
          it.strftime(70, 100, id(font_heure), TextAlign::BASELINE_LEFT, "%H:%M:%S", id(esptime).now());
          it.strftime(40, 160, id(font_heure), TextAlign::BASELINE_LEFT, "%d-%m-%Y", id(esptime).now()); 
          
          
          it.printf(40, 180, id(tempo3), my_white, "Aujourd'hui, nous faitons %s", id(saint_jour).state.c_str());
          it.printf(40, 196, id(tempo3), my_yellow, "Demain, nous faiterons %s", id(saint_demain).state.c_str());

          

      
      - id: page3
        lambda: |-
          it.image(2 , 2, id(edf_tempo));
          it.print(129, 22, id(tempo), my_white, "En ce moment");
          
          if (id(aujourdhui).state == "BLANC") { 
            it.filled_rectangle(9, 78, 142, 40, my_white);
            it.print(20, 87, id(tempo), my_black, "Aujourd'hui");
          }

          if (id(aujourdhui).state == "BLEU") { 
            it.filled_rectangle(9, 78, 142, 40, my_blue);
            it.print(20, 87, id(tempo), my_white, "Aujourd'hui");
          }

          if (id(aujourdhui).state == "ROUGE") { 
            it.filled_rectangle(9, 78, 142, 40, my_red);
            it.print(20, 87, id(tempo), my_white, "Aujourd'hui");
          }

          if (id(demain).state.substr(0, 3) == "Ind") { 
            it.filled_rectangle(169, 78, 142, 40, my_orange);          
            it.print(200, 87, id(tempo), my_black, "Demain");
          } 

          if (id(demain).state == "BLANC") { 
            it.filled_rectangle(169, 78, 142, 40, my_white);          
            it.print(200, 87, id(tempo), my_black, "Demain");
          }

          if (id(demain).state == "BLEU") { 
            it.filled_rectangle(169, 78, 142, 40, my_blue);          
            it.print(200, 87, id(tempo), my_white, "Demain");
          }

          if (id(demain).state == "ROUGE") { 
            it.filled_rectangle(169, 78, 142, 40, my_red);          
            it.print(200, 87, id(tempo), my_white, "Demain");
          }

          it.print(9, 130, id(tempo), my_white, "Jours restants");
          it.print(9, 150, id(tempo2), my_white, "Pour la période du 1er septembre au 31 aout");

          it.print(17, 180, id(tempo2), my_white, "Jours bleus");
          it.filled_circle(25, 205, 8, my_blue);
          it.printf(39, 200, id(tempo2), my_white, "%.0f-301", id(jours_bleus).state);

          it.print(117, 180, id(tempo2), my_white, "Jours blancs");
          it.filled_circle(125, 205, 8, my_white);
          it.printf(139, 200, id(tempo2), my_white, "%.0f-43", id(jours_blancs).state);

          it.print(217, 180, id(tempo2), my_white, "Jours rouges");
          it.filled_circle(225, 205, 8, my_red);
          it.printf(239, 200, id(tempo2), my_white, "%.0f-22", id(jours_rouges).state);

      - id: page4
        lambda: |-
          
          auto white = Color(255, 255, 255);
          it.rectangle(0,  0, it.get_width(), it.get_height(), white);
          
          it.filled_rectangle(20, 20, 80, 80, my_blue);
          it.rectangle(20, 20, 80, 80, my_white);
          it.print(22, 22, id(material80), my_white, "\U000F0CE3");

          it.print(110, 23, id(material20), my_white, "\U000F0DAB");
          it.print(140, 22, id(font_tempo), my_white, "Alain");
          if (id(batterie_tel_alain).state > 65) {
            it.print(110, 46, id(material20), my_white, "\U000F12A3");    
          }  
          if ((id(batterie_tel_alain).state > 33) and (id(batterie_tel_alain).state < 66)) {
            it.print(110, 46, id(material20), my_yellow, "\U000F12A2");    
          } 
          if (id(batterie_tel_alain).state < 34) {
            it.print(110, 46, id(material20), my_red, "\U000F12A1");    
          }  
          it.printf(140, 52, id(tempo3), my_white, "Téléphone: %2.0f%%", id(batterie_tel_alain).state);          
          it.print(110, 69, id(material20), my_white, "\U000F010D");
          if (id(tel_alain_connect).state.find("28:CF:08:EC:36:31") != std::string::npos) {
            it.print(140, 75, id(tempo3), my_white, "EST DANS LA KIA");
          }
          if (id(tel_alain_connect).state.find("74:95:EC:EC:E3:A8") != std::string::npos) {
            it.print(140, 75, id(tempo3), my_white, "EST DANS LA NISSAN");
          } 
          it.print(20, 106, id(material20), my_white, "\U000F12FB");
          it.print(40, 110, id(tempo3), my_white, id(alain_lieu).state.c_str());  

          it.filled_rectangle(20, 130, 80, 80, my_red);
          it.rectangle(20, 130, 80, 80, my_white);
          it.print(22, 132, id(material80), my_white, "\U000F1078");

          it.print(110, 133, id(material20), my_white, "\U000F0DAB");
          it.print(140, 132, id(font_tempo), my_white, "Nadège");
          if (id(batterie_tel_nadege).state > 65) {
            it.print(110, 156, id(material20), my_white, "\U000F12A3");    
          }  
          if ((id(batterie_tel_nadege).state > 33) and (id(batterie_tel_alain).state < 66)) {
            it.print(110, 156, id(material20), my_yellow, "\U000F12A2");    
          } 
          if (id(batterie_tel_nadege).state < 34) {
            it.print(110, 156, id(material20), my_red, "\U000F12A1");    
          }  
          it.printf(140, 162, id(tempo3), my_white, "Téléphone: %2.0f%%", id(batterie_tel_nadege).state);
          
          it.print(110, 183, id(material20), my_white, "\U000F010D");
          if (id(tel_nadege_connect).state.find("28:CF:08:EC:36:31") != std::string::npos) {
            it.print(140, 189, id(tempo3), my_white, "EST DANS LA KIA");
          }
          if (id(tel_nadege_connect).state.find("74:95:EC:EC:E3:A8") != std::string::npos) {
            it.print(140, 189, id(tempo3), my_white, "EST DANS LA NISSAN");
          } 
          it.print(20, 216, id(material20), my_white, "\U000F12FB");
          it.print(40, 220, id(tempo3), my_white, id(nadege_lieu).state.c_str()); 


interval:
  - interval: 10s
    then:
      - display.page.show_next: my_display
      - component.update: my_display


font:    

  - file: "fonts/calibri.ttf"
    id: tempo
    size: 24
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéèfghijklmnopqrstuvwxyzôç"
  
  - file: "fonts/calibri.ttf"
    id: tempo2
    size: 16
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéèfghijklmnopqrstuvwxyzôç"
  
  - file: "fonts/calibri.ttf"
    id: tempo3
    size: 14
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéèfghijklmnopqrstuvwxyzôç"

  
  - file: "gfonts://Protest Guerrilla"
    id: Protest
    size: 64
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéfghijklmnopqrstuvwxyzôç"
  
  - file: "gfonts://Bebas Neue"
    id: font_heure
    size: 64
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéfghijklmnopqrstuvwxyzôç"

  - file: "gfonts://Roboto"
    id: font_tempo
    size: 20
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéèfghijklmnopqrstuvwxyzôç"

  - file: "gfonts://Sono"
    id: font_temperature
    size: 18
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéfghijklmnopqrstuvwxyzôç"

  - file: "gfonts://Bebas Neue"
    id: my_font12
    size: 12
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéfghijklmnopqrstuvwxyzôç"

  - file: "gfonts://Oxygen Mono"
    id: my_font_temp
    size: 24
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéfghijklmnopqrstuvwxyzôç"

  - file: "gfonts://Bebas Neue"
    id: my_font8
    size: 8
    glyphs: "<>♡ÆØÅæøå!'%(){}+,-_.:;*=°?~#0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdeéfghijklmnopqrstuvwxyzôç"
  
  - file: "fonts/materialdesignicons-webfont.ttf"
    id: material80
    size: 80
    glyphs: 
      - "\U000F0CE3" # mdi:account-tie
      - "\U000F1078" # mdi:face-woman-outline
      

  - file: "fonts/materialdesignicons-webfont.ttf"
    id: material20
    size: 20
    glyphs: 
      - "\U000F0DAB" # mdi:card-account-details-outline
      - "\U000F12A1" # mdi:battery-low
      - "\U000F12A2" # mdi:battery-medium
      - "\U000F12A3" # mdi:battery-high
      - "\U000F010D" # mdi:car-connected
      - "\U000F12FB" # mdi:map-marker-check-outline
      - "\U000F050F" # mdi:thermometer
      - "\U000F1503" # mdi:water-alert-outline
      - "\U000F17E3" # mdi:battery-check-outline
  
  - file: "fonts/materialdesignicons-webfont.ttf"
    id: temperature
    size: 32
    glyphs: 
      - "\U000F07C0" # mdi:desktop-classic
      - "\U000F12A1" # mdi:battery-low
      - "\U000F12A2" # mdi:battery-medium
      - "\U000F12A3" # mdi:battery-high
      - "\U000F010D" # mdi:car-connected
      - "\U000F12FB" # mdi:map-marker-check-outline
      - "\U000F0099" # mdi:bed-outline
      - "\U000F0097" # mdi:bunk-bed-outline
      - "\U000F1061" # mdi:table-chair
      - "\U000F0F9B" # mdi:home-export-outline
      - "\U000F09F0" # mdi:flower-outline   


  
color:
  - id: my_red
    hex: ff0000
  - id: my_green
    hex: 00ff91
  - id: my_blue
    hex: 00b3ff
  - id: my_yellow
    hex: cbed0c
  - id: my_white
    hex: FFFFFF
  - id: my_black
    hex: "000000"
  - id: my_orange
    hex: ff8400

sensor:
  - platform: homeassistant
    id: batterie_tel_alain
    entity_id: sensor.telephone_alain_battery_level
  - platform: homeassistant
    id: batterie_tel_nadege
    entity_id: sensor.sm_a505fn_battery_level

  - platform: homeassistant
    id: temperature_bureau
    entity_id: sensor.thermometre_bureau_temperature
  - platform: homeassistant
    id: hygro_bureau
    entity_id: sensor.thermometre_bureau_humidite
  - platform: homeassistant
    id: batterie_bureau
    entity_id: sensor.thermometre_bureau_batterie

  - platform: homeassistant
    id: temperature_chambre
    entity_id: sensor.exterieur_temperature
  - platform: homeassistant
    id: hygro_chambre
    entity_id: sensor.exterieur_humidite
  - platform: homeassistant
    id: batterie_chambre
    entity_id: sensor.exterieur_batterie


  - platform: homeassistant
    id: temperature_chambre_ami
    entity_id: sensor.wen_shi_du_chuan_gan_qi_chambre_d_ami_temperature
  - platform: homeassistant
    id: hygro_chambre_ami
    entity_id: sensor.wen_shi_du_chuan_gan_qi_chambre_d_ami_humidite
  - platform: homeassistant
    id: batterie_chambre_ami
    entity_id: sensor.wen_shi_du_chuan_gan_qi_chambre_d_ami_batterie

  - platform: homeassistant
    id: temperature_cuisine
    entity_id: sensor.cuisine_temperature
  - platform: homeassistant
    id: hygro_cuisine
    entity_id: sensor.cuisine_humidite
  - platform: homeassistant
    id: batterie_cuisine
    entity_id: sensor.cuisine_batterie

  - platform: homeassistant
    id: temperature_avant
    entity_id: camera.avant
    attribute: temperature_c

  - platform: homeassistant
    id: temperature_arriere
    entity_id: camera.arriere
    attribute: temperature_c

  - platform: homeassistant
    id: jours_bleus
    entity_id: sensor.jours_bleu_restants
  - platform: homeassistant
    id: jours_blancs
    entity_id: sensor.jours_blanc_restants
  - platform: homeassistant
    id: jours_rouges
    entity_id: sensor.jours_rouge_restants
  - platform: homeassistant
    id: puissance
    entity_id: sensor.compteur_linky_puissance_apparente
  


text_sensor:
  - platform: homeassistant
    id: aujourdhui
    entity_id: sensor.tempo_aujourd_hui
  - platform: homeassistant
    id: demain
    entity_id: sensor.tempo_demain
  - platform: homeassistant
    id: tel_alain_connect
    entity_id: sensor.telephone_alain_bluetooth_connection
    attribute: connected_paired_devices
  - platform: homeassistant
    id: alain_lieu
    entity_id: sensor.telephone_alain_geocoded_location
  - platform: homeassistant
    id: tel_nadege_connect
    entity_id: sensor.sm_a505fn_bluetooth_connection
    attribute: connected_paired_devices
  - platform: homeassistant
    id: nadege_lieu
    entity_id: sensor.sm_a505fn_geocoded_location
  - platform: homeassistant
    id: saint_jour
    entity_id: sensor.saint_du_jour
  - platform: homeassistant
    id: saint_demain
    entity_id: sensor.saint_de_demain
  



image:
  - file: "images/edf-tempo-logo.jpg"
    id: edf_tempo
    type: RGB24

IMAGE
edf-tempo-logo

S’il manque quelque chose, dites le moi

2 « J'aime »

Merci @Alain_L

Beau projet, je vais étudier comment l’adapter pour mes besoins.
Encore de nombreuses heures :grin: en perspectives.

Reste aussi à trouver comment intégrer cela dans un boitier.
(Si tu as une solution, je suis preneur)

Mis dans un boitier 2€11

  • Boîte de projet en plastique ABS étanche, boîtier de rangement, boîtier de boîtier, fournitures électroniques
    125x80x32mm-Grey

Sur Aliexpress 0.26€ 79% de réduction|Boîte de projet en plastique ABS étanche, boîtier de rangement, boîtier de boîtier, fournitures électroniques | AliExpress

1 « J'aime »

Bonjour,

Est il possible d’avoir le code complet avec l’ajout de la page météo ?
J’aimerai réussir à faire ce genre de chose

en utilisant l’intégration méteo france et j’aimerai réussir à afficher un peu comme sur la carte météo france la pluie à venir

meteofrance-weather-card

Je n’arrive pas à trouver un code au format esphome pour le réaliser donc je cherche à m’inspirer de tous les codes possibles :slight_smile:

Merci