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 :
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 :
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
- – 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
- – S’assurer du bon renommage des fichier .ttf
Où trouver les icônes pour Material Design
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 !