Intégrer un reTerminal E1002 dans Home Assistant avec ESPHome

0
(0)

Dans un tutoriel précédent, je vous expliquais comment créer un capteur de température Zigbee à base d’ESP32C6 et comment l’intégrer dans Home Assistant.

Dans ce nouveau tutoriel, je vous guide pour intégrer un écran à encre électronique (e-paper) Seeed Studio reTerminal E1002 dans Home Assistant, afin d’y afficher les données issues de ce capteur.

Nous utiliserons le framework ESPHome, qui facilite grandement l’intégration de l’écran reTerminal dans Home Assistant via une configuration simple en YAML. Cette configuration permet de décrire précisément les périphériques connectés au microcontrôleur ESP32-S3 (écran, boutons, buzzer, LED, etc.), ainsi que les actions à exécuter localement. ESPHome compile ensuite ce fichier YAML pour générer un firmware qui sera téléversé sur le reTerminal.

Présentation du reTerminal

Le reTerminal E1002 est un appareil prêt à l’emploi doté d’un boîtier métallique robuste abritant un écran e-paper couleur de 7.3″ d’une résolution de 800×480. Il est équipé d’un microcontrôleur ESP32-S3 et il intègre 3 boutons, un buzzer, une LED de status (en plus de la LED d’alimentation), un capteur de température et de pression, un microphone et un lecteur de carte MicroSD. Il est alimenté par une batterie interne de 2000 mAh offrant jusqu’à 3 mois d’autonomie.

Les caractéristiques détaillées du reTerminal E1002 ainsi que son guide de démarrage rapide sont disponibles sur le wiki de Seeed Studio.

Mise à jour du firmware du reTerminal

Il est recommandé d’installer le dernier firmware disponible dès la première mise en service de votre appareil. Après avoir créé votre compte utilisateur sur le site sensecraft.seeed.cc, connectez votre reTerminal à un port USB de votre ordinateur, puis utilisez l’outil Device Flasher pour flasher le firmware le plus récent.

Dans ce tutoriel, SenseCraft HMI ne sera pas utilisé : il n’est donc pas nécessaire de suivre la procédure affichée sur l’écran du reTerminal, ni de se connecter au point d’accès Wi-Fi qu’il diffuse. L’objectif ici est de faire fonctionner le reTerminal avec Home Assistant, en le configurant directement via le framework ESPHome.

Configuration du reTerminal avec ESPHome

Installer le module complémentaire ESPHome Device Builder sur votre serveur Home Assistant puis le démarrer.

Dans le module ESPHome Builder, ajoutez le reTerminal comme nouvel appareil de type ESP32-S3. Étant donné que le reTerminal n’est pas encore configuré pour rejoindre le réseau Wi-Fi et que Home Assistant fonctionne en HTTP (et non HTTPS), le téléversement direct du firmware n’est pas possible depuis ESPHome Builder. Utilisez alors l’option Manual Download pour récupérer le firmware compilé au format Factory format (Previously Modern).

Note: l’installation des outils et la compilation du firmware peuvent être relativement longues si Home Assistant est hébergé sur un Raspberry Pi, notamment sur les modèles moins puissants. Il n’est pas rare d’attendre plusieurs minutes pour chaque compilation.

Téléversez ensuite ce fichier .bin sur le reTerminal à l’aide de l’outil en ligne ESPHome. Après ce premier flashage, le reTerminal rejoindra votre réseau Wi-Fi. Par la suite, il sera possible d’effectuer les futures mises à jour du firmware directement depuis Home Assistant via le Wi-Fi, sans nécessiter de connexion filaire.

Hello World!

Nous allons maintenant créer un exemple pour vous permettre de comprendre le principe de ESPHome et la configuration du reTerminal. Dans cet exemple, nous allons simplement afficher le message Hello World! sur l’écran du reTerminal.

Dans le module ESPHome Builder, cliquer sur Edit afin de pouvoir modifier la configuration YAML pour que le reTerminal affiche notre message.

L’écran du reTerminal E1002 de Seeed Studio est une dalle E Ink® Spectra™ 6 couleur de 7,3 pouces avec une résolution de 800×480 pixels. Comme vous pouvez le voir sur le schéma du reTerminal, l’ESP32-S3 communique avec l’écran au travers d’un bus SPI via les broches suivantes :

  • SPI Clock (CLK) : GPIO 7
  • Master In Slave Out (MISO) : GPIO8 (non utilisé par l’écran mais uniquement par le lecteur de carte microSD qui est sur le même bus SPI)
  • Master Out Slave In (MOSI) : GPIO9
  • Chip Select (CS) : GPIO10
  • Data/Command (DC) : GPIO11
  • Reset (RST) : GPIO12

Voici la configuration qui affiche le message « Hello Worlds! » en bleu, avec la police Google Inter 700 et une taille de 36 points. Vous pouvez utiliser cet exemple en copiant le code ci-dessous et en le collant juste après la ligne captive_portal dans votre fichier YAML.

YAML
captive_portal:
    
external_components:
  - source:
      type: git
      url: https://github.com/lublak/esphome
      ref: dev
    components: [ waveshare_epaper ]

# define font to display words
font:
  - file: "gfonts://Inter@700"
    id: myFont
    size: 36

# define SPI interface
spi:
  clk_pin: GPIO7
  mosi_pin: GPIO9

display:
  - platform: waveshare_epaper
    id: epaper_display
    model: 7.30in-e
    cs_pin: GPIO10
    dc_pin: GPIO11
    reset_pin:
      number: GPIO12
      inverted: false
    busy_pin:
      number: GPIO13
      inverted: true
    update_interval: 300s
    lambda: |-
      const auto BLUE    = Color(0,   0,   255, 0);
      it.print(0, 0, id(myFont), BLUE, "Hello World!");    

Note : sur un écran e-paper, il est essentiel de rafraîchir régulièrement l’affichage afin d’éviter les effets de rémanence caractéristiques de cette technologie. Dans la configuration ci-dessus, l’affichage est rafraîchi toutes les 300 secondes (5 minutes) via la configuration update_interval: 300s

Il suffit ensuite de cliquer sur Install et de choisir l’option Wirelessly pour téléverser le firmware correspondant à cette configuration YAML dans le reTerminal via votre réseau Wi-Fi (qui a été configuré lors du premier téléversement via ESPHome).

Après compilation et téléversement, le reTerminal affiche bien le message Hello World! en bleu sur son écran.

Première configuration du reTerminal E1002 affichant le célèbre “Hello World!”

Capteur de température et d’humidité interne au reTerminal

Le reTerminal possède un capteur interne de témperature et d’humidité STH40.

L’ESP32-S3 communique avec ce capteur au travers d’un bus I2C. Son adresse I2C est 0x44, et le bus I2C utilise les broches suivantes :

  • Serial Data (SDA) : GPIO19
  • Serial Clock (SCL) : GPIO20

Voici la configuration YAML qui permet de récupérer la température et l’humidité depuis ce capteur et de l’afficher sur l’écran, à copier juste après la ligne captive_portal dans votre fichier YAML :

YAML
captive_portal:
    
external_components:
  - source:
      type: git
      url: https://github.com/lublak/esphome
      ref: dev
    components: [ waveshare_epaper ]

# define I2C interface
i2c:
  sda: GPIO19
  scl: GPIO20
  scan: false

# temperature and humidity sensor
sensor:
  - platform: sht4x
    temperature:
      name: "Temperature"
      id: sht4x_temperature
    humidity:
      name: "Humidity"
      id: sht4x_humidity
    address: 0x44
    update_interval: 60s

# define font to display words
font:
  - file: "gfonts://Inter@700"
    id: myFont
    size: 36

# define SPI interface
spi:
  clk_pin: GPIO7
  mosi_pin: GPIO9

display:
  - platform: waveshare_epaper
    id: epaper_display
    model: 7.30in-e
    cs_pin: GPIO10
    dc_pin: GPIO11
    reset_pin:
      number: GPIO12
      inverted: false
    busy_pin:
      number: GPIO13
      inverted: true
    update_interval: 300s
    lambda: |-
      const auto BLUE    = Color(0,   0,   255, 0);
      it.printf(10, 10, id(myFont), BLUE, "Temperature: %.1f°C", id(sht4x_temperature).state);  
      it.printf(10, 40, id(myFont), BLUE, "Humidity: %.1f%%", id(sht4x_humidity).state);  

Le reTerminal affichera sur son écran la température et l’humidité mesurées par son capteur interne.

Grâce à ESPHome, il est possible d’afficher les données issues du reTerminal dans Home Assistant.

Affichage des données d’un capteur externe sur l’écran du reTerminal

Il est parfaitement possible d’afficher n’importe quelle entité de Home Assistant sur l’écran du reTerminal. Comme mentionné au début de ce tutoriel, nous allons afficher sur l’écran du reTerminal, la température et l’humidité mesurée par le capteur Zigbee externe à base d’ESP32-C6 que j’ai conçu dans mon tutoriel précédent.

La température et l’humidité mesurées par ce capteur externe correspondent aux entité d’ID suivantes dans Home Assistant :

  • sensor.tutoduino_esp32c6tempsensor_temperature
  • sensor.tutoduino_esp32c6tempsensor_humidite
ID des entités correspondant à la température et humidité du capteur externe dans Home Assistant

Voici le code à copier juste après la ligne captive_portal dans votre fichier YAML :

YAML
captive_portal:
    
external_components:
  - source:
      type: git
      url: https://github.com/lublak/esphome
      ref: dev
    components: [ waveshare_epaper ]

# define I2C interface
i2c:
  sda: GPIO19
  scl: GPIO20
  scan: false

sensor:
  # internal temperature and humidity sensor
  - platform: sht4x
    temperature:
      name: "Temperature"
      id: sht4x_temperature
    humidity:
      name: "Humidity"
      id: sht4x_humidity
    address: 0x44
    update_interval: 60s

  # external EP32C6 sensor
  - platform: homeassistant
    id: tutoduino_esp32c6tempsensor_temperature
    entity_id: sensor.tutoduino_esp32c6tempsensor_temperature

  - platform: homeassistant
    id: tutoduino_esp32c6tempsensor_humidite
    entity_id: sensor.tutoduino_esp32c6tempsensor_humidite

# define font to display words
font:
  - file: "gfonts://Inter@700"
    id: myFont
    size: 36
  - file: "gfonts://Inter@700"
    id: myFontLarge
    size: 50
  - file: "gfonts://Inter@700"
    id: myFontVeryLarge
    size: 70

# define SPI interface
spi:
  clk_pin: GPIO7
  mosi_pin: GPIO9

display:
  - platform: waveshare_epaper
    id: epaper_display
    model: 7.30in-e
    cs_pin: GPIO10
    dc_pin: GPIO11
    reset_pin:
      number: GPIO12
      inverted: false
    busy_pin:
      number: GPIO13
      inverted: true
    update_interval: 300s
    lambda: |-
      const auto BLUE = Color(0, 0, 255, 0);
      const auto GREEN = Color(0, 255, 0, 0);
      const auto BLACK = Color(0, 0, 0, 0);

      it.line(400, 0, 400, 480, BLACK);

      it.printf(130, 15, id(myFont), BLACK, "INDOOR");
      it.printf(510, 15, id(myFont), BLACK, "OUTDOOR");

      if (isnan(id(sht4x_temperature).state)) {
        it.printf(90, 120, id(myFontVeryLarge), BLUE, "--.-°C");
      } else {
        it.printf(90, 120, id(myFontVeryLarge), BLUE, "%.1f°C", id(sht4x_temperature).state);
      }

      if (isnan(id(sht4x_humidity).state)) {
        it.printf(120, 250, id(myFontLarge), BLUE, "--.-%%");
      } else {
        it.printf(120, 250, id(myFontLarge), BLUE, "%.1f%%", id(sht4x_humidity).state);
      }

      if (isnan(id(tutoduino_esp32c6tempsensor_temperature).state)) {
        it.printf(500, 120, id(myFontVeryLarge), GREEN, "--.-°C");
      } else {
        it.printf(500, 120, id(myFontVeryLarge), GREEN, "%.1f°C", id(tutoduino_esp32c6tempsensor_temperature).state);
      }

      if (isnan(id(tutoduino_esp32c6tempsensor_humidite).state)) {
        it.printf(540, 250, id(myFontLarge), GREEN, "--.-%%");
      } else {
        it.printf(540, 250, id(myFontLarge), GREEN, "%.1f%%", id(tutoduino_esp32c6tempsensor_humidite).state);
      }

Cette configuration affiche les données du capteur interne au reTerminal dans la partie INDOOR et les données issues du capteur externe dans la partie OUTDOOR.

Affichage des données issues du capteur interne et d’un capteur externe

Affichage de la charge des batteries et ajout d’icônes

Mon capteur externe à base d’ESP32-C6 et le reTerminal étant tous les deux alimentés par batterie, il est utile de pouvoir afficher leur niveau sur l’écran.

Concernant le niveau de la batterie du capteur externe, elle est simplement récupérée via l’entité Home Assistant sensor.tutoduino_esp32c6tempsensor_batterie.

Pour récupérer le niveau de batterie du reTerminal, il faut activer la mesure de la tension de la batterie en configurant le GPIO21 (VBAT ENABLE). La lecture s’effectue ensuite sur le GPIO1 (VBAT ADC), qui est relié en interne à la batterie via un circuit de mesure. En lisant la valeur analogique (tension) sur ce GPIO1, il est possible d’obtenir une estimation précise du niveau de charge de la batterie.

Pour ajouter les icônes de thermomètre, d’hygromètre et de batterie, il faut créer le répertoire fonts dans le répertoire esphome (avec l’extension File editor) et y ajouter le fichier de font suivant : MaterialDesignIconsDesktop.ttf

Voici la configuration qui permet de récupérer le niveau des batteries et d’afficher les icônes.

YAML
esphome:
  name: reterminal
  friendly_name: reTerminal
  on_boot:
    priority: 600
    then:
      - output.turn_on: bsp_battery_enable

esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: esp-idf

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "XXXX"

ota:
  - platform: esphome
    password: "XXXX"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Reterminal Fallback Hotspot"
    password: "XXXX"

captive_portal:
    
output:
  - platform: gpio
    pin: GPIO21
    id: bsp_battery_enable

external_components:
  - source:
      type: git
      url: https://github.com/lublak/esphome
      ref: dev
    components: [ waveshare_epaper ]

# define I2C interface
i2c:
  sda: GPIO19
  scl: GPIO20
  scan: false

sensor:
  # internal temperature and humidity sensor
  - platform: sht4x
    temperature:
      name: "Temperature"
      id: sht4x_temperature
    humidity:
      name: "Humidity"
      id: sht4x_humidity
    address: 0x44
    update_interval: 300s

  # external EP32C6 sensor
  - platform: homeassistant
    id: tutoduino_esp32c6tempsensor_temperature
    entity_id: sensor.tutoduino_esp32c6tempsensor_temperature

  - platform: homeassistant
    id: tutoduino_esp32c6tempsensor_humidite
    entity_id: sensor.tutoduino_esp32c6tempsensor_humidite

  - platform: homeassistant
    id: tutoduino_esp32c6tempsensor_batterie
    entity_id: sensor.tutoduino_esp32c6tempsensor_batterie

  - platform: adc
    pin: GPIO1
    name: "Battery Voltage"
    id: battery_voltage
    update_interval: 300s
    attenuation: 12db
    filters:
      - multiply: 2.0  # Voltage divider compensation

  - platform: template
    name: "Battery Level"
    id: battery_level
    unit_of_measurement: "%"
    icon: "mdi:battery"
    device_class: battery
    state_class: measurement
    lambda: 'return id(battery_voltage).state;'
    update_interval: 300s
    filters:
      - calibrate_linear:
          - 4.15 -> 100.0
          - 3.96 -> 90.0
          - 3.91 -> 80.0
          - 3.85 -> 70.0
          - 3.80 -> 60.0
          - 3.75 -> 50.0
          - 3.68 -> 40.0
          - 3.58 -> 30.0
          - 3.49 -> 20.0
          - 3.41 -> 10.0
          - 3.30 -> 5.0
          - 3.27 -> 0.0
      - clamp:
          min_value: 0
          max_value: 100

# define font to display words
font:
  - file: "gfonts://Inter@700"
    id: mySmallFont
    size: 15
  - file: "gfonts://Inter@700"
    id: myFont
    size: 36
  - file: "gfonts://Inter@700"
    id: myFontLarge
    size: 50
  - file: "gfonts://Inter@700"
    id: myFontVeryLarge
    size: 70
  - file: 'fonts/MaterialDesignIconsDesktop.ttf'
    id: font_mdi_large
    size: 50
    glyphs:
      - "\U000F050F"  # thermometer
      - "\U000F058E"  # humidity
  - file: 'fonts/MaterialDesignIconsDesktop.ttf'
    id: font_bat_icon
    size: 50
    glyphs:
      - "\U000F0079"  # mdi-battery

# define SPI interface
spi:
  clk_pin: GPIO7
  mosi_pin: GPIO9

display:
  - platform: waveshare_epaper
    id: epaper_display
    model: 7.30in-e
    cs_pin: GPIO10
    dc_pin: GPIO11
    reset_pin:
      number: GPIO12
      inverted: false
    busy_pin:
      number: GPIO13
      inverted: true
    update_interval: 10min
    lambda: |-
      const auto BLUE = Color(0, 0, 255, 0);
      const auto GREEN = Color(0, 255, 0, 0);
      const auto BLACK = Color(0, 0, 0, 0);
      const auto RED   = Color(255, 0,   0,   0);

      it.line(400, 0, 400, 480, BLACK);

      it.printf(130, 15, id(myFont), BLACK, "INDOOR");
      it.printf(510, 15, id(myFont), BLACK, "OUTDOOR");

      it.printf(60, 165, id(font_mdi_large), BLACK, TextAlign::CENTER, "\U000F050F");

      if (isnan(id(sht4x_temperature).state)) {
        it.printf(90, 120, id(myFontVeryLarge), BLUE, "--.-°C");
      } else {
        it.printf(90, 120, id(myFontVeryLarge), BLUE, "%.1f°C", id(sht4x_temperature).state);
      }

      it.printf(60, 283, id(font_mdi_large), BLACK, TextAlign::CENTER, "\U000F058E");

      if (isnan(id(sht4x_humidity).state)) {
        it.printf(90, 250, id(myFontLarge), BLUE, "--.-%%");
      } else {
        it.printf(90, 250, id(myFontLarge), BLUE, "%.1f%%", id(sht4x_humidity).state);
      }

      it.printf(60, 390, id(font_bat_icon), BLACK, TextAlign::CENTER, "\U000F0079");

      if (isnan(id(battery_level).state)) {
        it.printf(90, 360, id(myFontLarge), BLUE, "--%%");
      } else {
        it.printf(90, 360, id(myFontLarge), BLUE, "%2.0f%%", id(battery_level).state);
      }

      it.printf(470, 165 , id(font_mdi_large), BLACK, TextAlign::CENTER, "\U000F050F");

      if (isnan(id(tutoduino_esp32c6tempsensor_temperature).state)) {
        it.printf(500, 120, id(myFontVeryLarge), BLUE, "--.-°C");
      } else {
        it.printf(500, 120, id(myFontVeryLarge), BLUE, "%.1f°C", id(tutoduino_esp32c6tempsensor_temperature).state);
      }

      it.printf(470, 283, id(font_mdi_large), BLACK, TextAlign::CENTER, "\U000F058E");

      if (isnan(id(tutoduino_esp32c6tempsensor_humidite).state)) {
        it.printf(500, 250, id(myFontLarge), BLUE, "--.-%%");
      } else {
        it.printf(500, 250, id(myFontLarge), BLUE, "%.1f%%", id(tutoduino_esp32c6tempsensor_humidite).state);
      }

      it.printf(470, 390, id(font_bat_icon), BLACK, TextAlign::CENTER, "\U000F0079");

      if (isnan(id(tutoduino_esp32c6tempsensor_batterie).state)) {
        it.printf(500, 360, id(myFontLarge), BLUE, "--%%");
      } else {
        it.printf(500, 360, id(myFontLarge), BLUE, "%2.0f%%", id(tutoduino_esp32c6tempsensor_batterie).state);
      }

Voici le rendu des icones sur l’écran du reTerminal E1002, mais n’hésitez pas à les adapter à vos besoins.

Affichage de la température, de l’humidité et du niveau de la batterie d’un capteur externe et du capteur interne du reTerminal E1002

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?