You are currently viewing Un cadre connecté e-ink avec ESP32 pour votre domotique

Un cadre connecté e-ink avec ESP32 pour votre domotique

tags : cadre e-ink esp32 domotique

1. Matériel Requis

Epaper ESP32 Driver Board + Ecran Waveshare 7,5 v2 + Cadre Photo

ESPhome installé sur Home Assistant

Je vous laisse faire un beau montage sur votre cadre. Et pour l’ESP32, vous trouverez des fichiers 3D à imprimer pour le protéger.

https://cults3d.com/en/3d-model/tool/case-for-waveshare-e-paper-esp8266-driver-board 

L’idée initiale : https://beta.gammatroniques.fr/projects/epaper-ha

GitHub de mon cadre : https://gist.github.com/FabioR46/2f059bfb8ad08aac8beb38deedc3167d

Info : Je débute totalement sur le YAML / Python donc c’est erreur de débutant peuvent être visible dans le code proposé, si vous êtes en maitrise, n’hésitez pas à le modifier et à partager vos bonnes astuces.

Dans le tuto, nous décrypterons en quelques étapes : le code, comment installer les polices et afficher des entités de HA sur l’écran.

2. C’est parti pour l’installation !

Branché en USB l’ESP32 sur un port usb de votre machine avec Home Assistant

Allez dans ESPHome -> New Device -> Continue -> Nom -> ESP32 (copié le code) -> Skip

Et c’est parti pour le code ci-dessous (ou le GitHub direct):

esphome:
name: cadre-connecte friendly_name: Cadre Connecté platform: ESP32
board: esp32dev on_boot:
-	delay: 60s
-	script.execute: update_screen
wifi:
ssid: #nom de votre wifi password: #clé de votre wifi
ap:
ssid: "Epaper-Esp32 Fallback Hotspot" password: "xUrnzdTgz"
captive_portal:
logger:


ota:
script:
-		id: update_screen then:
- component.update: eink_display

Communication de l’écran :

spi:
 clk_pin: 13
 mosi_pin: 14

- Polices d’écriture
font:
 ######### REGULAR #################
 - file: "epaper/GothamRnd-Book.ttf"
 id: book20
 size: 20
 glyphs: &font-glyphs
 ['!', '"', '%', '(', ')', '+', '=', ',', '-', '_', '.', ':', '°', ' ',
 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z',
 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
 'é', 'à', 'è', 'ç', 'ù', 'É', 'À', 'È', 'Ç', 'Ù']
 - file: "epaper/GothamRnd-Book.ttf"
 id: book25
 size: 25
 glyphs : *font-glyphs
 ########## BOLD ##################
 - file: "epaper/GothamRnd-Bold.ttf"
 id: bold15
 size: 15
 glyphs : *font-glyphs
 - file: "epaper/GothamRnd-Bold.ttf"
 id: bold20
 size: 20
 glyphs : *font-glyphs
 - file: "epaper/GothamRnd-Bold.ttf"
 id: bold25
 size: 25
 glyphs : *font-glyphs
 - file: "epaper/GothamRnd-Bold.ttf"
 id: bold30
 size: 30
 glyphs : *font-glyphs
 - file: "epaper/GothamRnd-Bold.ttf"
 id: bold35
 size: 35
 glyphs : *font-glyphs
 - file: "epaper/GothamRnd-Bold.ttf"
 id: bold40
 size: 40
 glyphs : *font-glyphs
 - file: "epaper/GothamRnd-Bold.ttf"
 id: bold55
 size: 55
 glyphs: ['.', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'C', '-']
 - file: 'epaper/materialdesignicons-webfont.ttf'
 id: mdi120
 size: 120
 glyphs: &mdi-weather-glyphs
 - "\U000F0590" # mdi-weather-cloudy
 - "\U000F0F2F" # mdi-weather-cloudy-alert
 - "\U000F0E6E" # mdi-weather-cloudy-arrow-right
 - "\U000F0591" # mdi-weather-fog
 - "\U000F0592" # mdi-weather-hail
 - "\U000F0F30" # mdi-weather-hazy
 - "\U000F0898" # mdi-weather-hurricane
 - "\U000F0593" # mdi-weather-lightning
 - "\U000F067E" # mdi-weather-lightning-rainy
 - "\U000F0594" # mdi-weather-night
 - "\U000F0F31" # mdi-weather-night-partly-cloudy
 - "\U000F0595" # mdi-weather-partly-cloudy
 - "\U000F0F32" # mdi-weather-partly-lightning
 - "\U000F0F33" # mdi-weather-partly-rainy
 - "\U000F0F34" # mdi-weather-partly-snowy
 - "\U000F0F35" # mdi-weather-partly-snowy-rainy
 - "\U000F0596" # mdi-weather-pouring
 - "\U000F0597" # mdi-weather-rainy
 - "\U000F0598" # mdi-weather-snowy
 - "\U000F0F36" # mdi-weather-snowy-heavy
 - "\U000F067F" # mdi-weather-snowy-rainy
 - "\U000F0599" # mdi-weather-sunny
 - "\U000F0F37" # mdi-weather-sunny-alert
 - "\U000F14E4" # mdi-weather-sunny-off
 - "\U000F059A" # mdi-weather-sunset
 - "\U000F059B" # mdi-weather-sunset-down
 - "\U000F059C" # mdi-weather-sunset-up
 - "\U000F0F38" # mdi-weather-tornado
 - "\U000F059D" # mdi-weather-windy
 - "\U000F059E" # mdi-weather-windy-variant
 - "\U000F05F1" # mdi-wallbox
 - "\U000F0CD4" # mdi-boks-parcel
 - "\U000F1A74" # mdi-solar-power-variant-outline
 - "\U000F1904" # mdi-home-lightning-bolt-outline
 - "\U000F067B" # mdi-tempoEDF
 - "\U000F05D6" # mdi-alert-circle-outline
 - "\U000F05D5" # mdi-plane
 - "\U000F0531" # mdi-centerparc

 - "\U000F0A7A" # mdi-trash
 - "\U000F044C" # mdi-recycle
 - "\U000F0438" # mdi-radiator_on
 - "\U000F0902" # mdi-radiator_off
 - "\U000F0E66" # mdi-carbonfree
 - "\U000F1806" #mdi-waterboil
 - file: 'epaper/materialdesignicons-webfont.ttf'
 id: mdi36
 size: 36
 glyphs: *mdi-weather-glyphs
 - file: 'epaper/materialdesignicons-webfont.ttf'
 id: mdi20
 size: 20
 glyphs: *mdi-weather-glyphs

Bon, maintenant que ESPHome sait ce que nous allons utiliser, il faut quand même envoyer ces
polices à l’EPS32. Cependant, par défaut, elles ne sont pas toutes dans Home Assistant ni
dans ESPHome.

Pour le moment : Save

3. Installation de Samba

Afin de pouvoir accéder au dossier de configuration de Home Assistant, une des solutions
graphiques la plus simple est Samba !
À défaut de nous jouer de la musique, il nous permet d’ajouter et modifier des fichiers / dossier à
la racine de Home Assistant. Pour se faire, voici la procédure :
Paramètres -> Modules Complémentaires -> Boutique des modules complémentaires -> Samba
share
Une fois fait, vous devriez trouver cet écran :

Pour fonctionner, il faut le configurer :

Configuration puis créer un nom d’utilisateur « Username » et un mot de passe « Password » Puis retour sur l’onglet « Info » et « Démarrer »

Pour vérifier que tout fonctionne

Mac OS :

  • Clique secondaire sur le logo Finder -> Se connecter au serveur -> smb://ip_de_homeassistant Puis choisir le dossier « config » -> esphome puis créer un dossier « epaper »

Windows :

  • Cliquez sur l’explorateur windows -> clique droit sur « Réseau » -> Connecter un lecteur réseau

-> \\ip_de_homeassistant\config

Une fois connecter au dossier, allez dans esphome et créez un dossier « epaper »

4. Téléchargement des polices et installation :

La police Book :

https://github.com/electrode-io/electrode-webpack-reporter/blob/master/client/styles/fonts/Gotham-Rounded-Book.ttf

Récupérer le fichier .ttf et glisser le dans le dossier « epaper » créer précédemment. Renommez le fichier .ttf : Gotham-Rnd-Book.ttf

La police Bold :

https://github.com/electrode-io/electrode-webpack-reporter/blob/master/client/styles/fonts/Gotham-Rounded-Bold.ttf

Récupérer le fichier .ttf et glisser le dans le dossier « epaper » créer précédemment. Renommez le fichier .ttf : Gotham-Rnd-Bold.ttf

La police Material Design Icons :

https://github.com/Templarian/MaterialDesign-Webfont/blob/master/fonts/materialdesignicons-webfont.ttf

Récupérer le fichier .ttf et glisser le dans le dossier « epaper » créer précédemment. Renommez le fichier .ttf : materialdesignicons-webfont.ttf

5. Ajout des données

Maintenant que ESPHome a les polices requises, nous allons récupérer des données de capteurs pour la météo / température d’une pièce et les transmettre au cadre. Libre à vous d’en ajouter à votre guise.

sensor:
 - platform: homeassistant
 entity_id: weather.nantes
 attribute: temperature
 id: weather_temperature
 - platform: homeassistant
 entity_id: sensor.thc238_268_thn132_thwr288_thrn122_thn122_aw129_131_f8_04_temperature
 id: temp_bedroom_1

Donc :
« – plaform: homeassistant » sert à trouver l’information attendu
« entity_id: weather.nantes » se trouve sur le capteur dans Home Asisstant
« id » va permettre au cadre de faire le lien entre ce qu’il affiche (en suivant la taille, police et position défini) avec l’information recupérer via entity_id

Nous avons donc, les paramètres graphiques et les données utilisables. Il faut donc configurer l’esp32 afin qu’il affiche correctement :


Dans le premier bloc, nous avons ce qui sert à la communication, la rotation d’affichage, l’intervalle d’affichage (cf : #informant de la fonction)

L’usage de la fonction « traduction » afin d’afficher le texte correspondant à ce que nous souhaitons :
Exemple :
Si un véhicule est branché sur ma borne de charge, dans Home Assistant cela active un curseur ON mais je souhaitais plutôt afficher le mot « Branché », j’ai donc fait ceci :

std::map<std::string, std::string> charge_traduction
{
{"on", "En Charge"},
{"off", "Stoppé"},
};

Voici donc la suite du code attendu :

display:
 - platform: waveshare_epaper
 id: eink_display
 cs_pin: 15
 dc_pin: 27
 busy_pin: 25
 reset_pin: 26
 reset_duration: 2ms
 model: 7.50inv2
 rotation: 270° #Rotation d’affichage
 update_interval: 300s #Délai d’actualisation des données
 lambda: |
 std::map<std::string, std::string> weather_icon_map
 {
 {"cloudy", "\U000F0590"},
 {"cloudy-alert", "\U000F0F2F"},
 {"cloudy-arrow-right", "\U000F0E6E"},
 {"fog", "\U000F0591"},
 {"hail", "\U000F0592"},
 {"hazy", "\U000F0F30"},
 {"hurricane", "\U000F0898"},
 {"lightning", "\U000F0593"},
 {"lightning-rainy", "\U000F067E"},
 {"night", "\U000F0594"},
 {"night-partly-cloudy", "\U000F0F31"},
 {"partlycloudy", "\U000F0595"},
 {"partly-lightning", "\U000F0F32"},
 {"partly-rainy", "\U000F0F33"},
 {"partly-snowy", "\U000F0F34"},
 {"partly-snowy-rainy", "\U000F0F35"},
 {"pouring", "\U000F0596"},
 {"rainy", "\U000F0597"},
 {"snowy", "\U000F0598"},
 {"snowy-heavy", "\U000F0F36"},
 {"snowy-rainy", "\U000F067F"},
 {"sunny", "\U000F0599"},
 {"sunny-alert", "\U000F0F37"},
 {"sunny-off", "\U000F14E4"},
 {"sunset", "\U000F059A"},
 {"sunset-down", "\U000F059B"},
 {"sunset-up", "\U000F059C"},
 {"tornado", "\U000F0F38"},
 {"windy", "\U000F059D"},
 {"windy-variant", "\U000F059E"},
 };
 std::map<std::string, std::string> weather_traduction
 {
 {"cloudy", "Nuageux"},
 {"cloudy-alert", "Alerte"},
 {"cloudy-arrow-right", "--"},
 {"fog", "Brouillard"},
 {"hail", "Grêle"},
 {"hazy", "Brume"},
 {"hurricane", "Ouragan"},
 {"lightning", "Orage"},
 {"lightning-rainy", "Orageux"},
 {"night", "Nuit"},
 {"night-partly-cloudy", "Nuageux"},
 {"partlycloudy", "Nuageux"},
 {"partly-lightning", "Orageux"},
 {"partly-rainy", "Pluvieux"},
 {"partly-snowy", "Neigeux"},
 {"partly-snowy-rainy", "Neigeux"},
 {"pouring", "À verse"},
 {"rainy", "Pluvieux"},
 {"snowy", "Neigeux"},
 {"snowy-heavy", "Neigeux"},
 {"snowy-rainy", "Neigeux"},
 {"sunny", "Ensoleillé"},
 {"sunny-alert", "Alerte"},
 {"sunny-off", "--"},
 {"sunset", "Crépuscule"},
 {"sunset-down", "Crépuscule"},
 {"sunset-up", "Aube"},
 {"tornado", "Tornade"},
 {"windy", "Venteux"},
 {"windy-variant", "Venteux"},
 {"on", "Branché"},
 {"off", "Débranché"},
 };
 std::map<std::string, std::string> info_traduction
 {
 {"on", "Livré"},
 {"off", "Vide"},
 };
 std::map<std::string, std::string> charge_traduction
 {
 {"on", "En Charge"},
 {"off", "Stoppé"},
 };
 std::map<std::string, std::string> trash_traduction
 {
 {"on", "à sortir"},
 {"off", " "},
 };
 std::map<std::string, std::string> heat_traduction
 {
 {"on", "\U000F0438"},
 {"off", "\U000F0902"},
 };

Et maintenant place à la composition d’affichage !
Premier bloc : Date / ligne / Météo du jour

it.printf(240, 75, id(bold35), TextAlign::TOP_CENTER, "%s", id(date_fr_complete).state.c_str());
 it.filled_rectangle(50, 120, 380, 2);
 it.printf(135, 135, id(mdi120), TextAlign::TOP_CENTER, "%s", weather_icon_map[id(weather_name).state].c_str());
 it.printf(215, 145, id(bold35), TextAlign::TOP_LEFT, "%s",weather_traduction[id(weather_name).state].c_str());
 it.printf(215, 187, id(bold55), TextAlign::TOP_LEFT, "%2.1f°C", id(weather_temperature).state);
 it.filled_rectangle(50, 260, 380, 2);

Voilà le résultat attendu

Dans le détail :

It.printf = Afficher des caractères sur un écran

(215, 145,) = Abscisse et ordonnée soit dans notre exemple : 215 Position en partant de la gauche et 145 positions en partant du haut.

id(bold35) = Police et taille de caractère

TextAlign::TOP_LEFT = Comme sous Word ou Pages, c’est le positionnement du texte

«%s »,weather_traduction[id(weather_name).state].c_str()); » : Affichage de la météo via l’id Libre à vous de compléter le reste !

6. Défauts possibles

Contraste faible

Changer le switch A sur la position ON sur l’ESP32

Case noir à la place d’une icône

  1. – Vérifier si le code de l’icône est bien présent dans la liste mdi et s’il n’y a aucune erreur
  2. – S’assurer du bon renommage des fichier .ttf

Où trouver les icônes pour Material Design

ICI

Merci à tous d’avoir suivi l’excellent tuto de Fabien EON que nous remercions vivement ! Nous nous languissons de le lire à nouveau !

N’oubliez pas que la vie est une fête !