samedi 11 avril 2020

Un afficheur TFT pour DOMOTICZ ou JEEDOM (version ESP8266)



 Un afficheur TFT pour DOMOTICZ ou JEEDOM

(version ESP8266)



Dans un article de mai 2019 j'avais décrit la réalisation d'un module d'affichage d'informations pour un serveur domotique :
https://riton-duino.blogspot.com/2019/05/un-afficheur-pour-domoticz-ou-jeedom.html

Nous allons simplifier ce projet et lui apporter quelques améliorations en utilisant un ESP8266 :
  • affichage de la météo avec une icône
  • affichage du saint du jour
Pour rappel ce montage était composé des modules suivants :
  • un ARDUINO NANO
  • un module radio NRF24L01
  • un afficheur 2.8 pouces ILI9341
  • un capteur de température DHT31D
  • 5 résistances de 10K
  • une alimentation 5V
  • un buzzer 5V
Avec un ESP8266 nous pourrons :
  • remplacer le module radio NRF24L01 par le WIFI
  • éliminer les résistances car l'ESP8266 fonctionne en 3.3V
La carte utilisée sera une NodeMCU ou une WEMOS D1 MINI.

Ce projet, même s'il n'est pas réalisé dans son intégralité, peut apporter pas mal de renseignements sur différents points de programmation ESP8266 :
Nous allons aborder :
  • l'affichage d'informations sur un écran TFT SPI
  • le chargements d'images à partir du SPIFFS
  • le lecture d'un capteur de température et humidité I2C
  • la récupération de l'heure avec NTP
  • les requêtes JSON
  • les requêtes et parsing HTTP 
  • formulaire de configuration HTML et sauvegarde en EEPROM
Il vaut mieux se familiariser avec DOMOTICZ :
https://riton-duino.blogspot.com/2019/05/mysensors-presentation.html
L'adaptation des requêtes JSON à d'autres serveurs comme JEEDOM devrait se faire sans difficultés à partir du moment où l'on aura pris le temps de se familiariser avec le principe.

1. Informations affichées

1.1. Date et  heure

Le module affiche la date et l'heure. Ces informations sont obtenues en questionnant un serveur NTP.
La librairie NTP utilisée permet une correction automatique en fonction de l'heure été / hiver.

1.2. Éphéméride

Je n'ai pas trouvé de site proposant une API permettant de récupérer le nom du saint du jour sans devoir s'inscrire avec une adresse IP non fixe.

Le nom du saint du jour sera obtenu grâce à un petit serveur PHP tournant sur la RASPBERRY PI. Ce script est présent dans le projet.

1.3. Météo

1.3.1. weatherstack
La météo est plus facile à récupérer. Il suffit de s'inscrire sur un serveur proposant une API : https://weatherstack.com/ par exemple.
Le service gratuit propose la météo en temps réel et autorise 1000 requêtes par mois.
L'inscription : https://weatherstack.com/signup/free

L'abonnement gratuit ne donne pas accès à certaines fonctions, par exemple l'internationalisation. La météo sera en anglais :
  • Sunny
  • Cloudy
  • Partly cloudy
  • etc.
L'idéal est d'afficher une icône associée à la météo du jour, ce qui est fait dans ce projet.

La documentation :
https://weatherstack.com/documentation

La liste des codes météo :
https://weatherstack.com/site_resources/weatherstack-weather-condition-codes.zip

Le serveur fournit les images PNG nécessaires et nous allons les convertir en utilisant l'outil de conversion de rinkydinkelectronics :
http://www.rinkydinkelectronics.com/t_imageconverter565.php

Toutes les images converties sont présentes dans le projet. Elles devront être chargées dans le système de fichiers SPIFFS de l'ESP8266.

1.3.2. openweathermap
L'autre alternative est https://openweathermap.org/

L'abonnement gratuit est plus généreux : 1000 appels par jour.

Cette API propose aussi un nom d'icône à associer à la météo.

La liste complète des codes météo se trouve ici :

J'avoue franchement que je n'ai pas le courage dans l'immédiat de faire une nouvelle version avec cette API.

1.4. Température et humidité

Comme précédemment le module comporte un capteur de température et d'humidité. Les valeurs sont affichées sur l'écran et également envoyées au serveur domotique.

Le projet propose le choix entre 3 capteurs : HDC2080, SHT31D et HTU21.
Ces trois modules ont une précision de 0.2°C en température et 2% en humidité.

Je n'ai pas envisagé d'intégrer un DHT22 car je préfère ces capteurs, plus précis et plus fiables.

1.5. Informations diverses

Les informations à récupérer sont les suivantes :
  • température à l'étage
  • température au garage
  • température & humidité extérieures
  • température du congélateur
Ces informations proviennent de différents capteurs MYSENSORS :
https://riton-duino.blogspot.com/2018/01/un-thermometre-mysensors-sur-batterie.html
https://riton-duino.blogspot.com/2019/05/un-thermometre-hygrometre-mysensors-sur.html
https://riton-duino.blogspot.com/2018/04/un-detecteur-de-mouvement-mysensors-sur.html
https://riton-duino.blogspot.com/2019/05/un-thermometre-mysensors-pour-freezer.html
Auparavant les informations supplémentaires à afficher étaient récupérées via le module NRF24L01 et la passerelle MYSENSORS.
Avec une liaison WIFI le principe de récupération des informations sera différent. Nous allons utiliser des requêtes JSON.

2. Requêtes JSON

Les requêtes JSON sont utilisées pour :
  • récupération des informations DOMOTICZ
  • récupération des informations météo
  • envoi de la température et de l'humidité à DOMOTICZ 
Bien évidemment ces requêtes sont adaptées à mon système domotique.
Les informations à afficher seront forcément différentes sur une autre installation.

2.1. DOMOTICZ

Les URLs utilisées ici sont celles de mon serveur DOMOTICZ.
Il faut bien sûr remplacer http://192.168.1.134:8080 par l'adresse réelle du serveur et son port.

2.1.1. Dispositifs

Nous allons devoir créer des dispositifs. Domoticz ne possède pas d'interface pour faire cette opération simplement. Il faut le faire via le navigateur :

Un capteur de température / humidité :

http://192.168.1.134:8080/json.htm?type=createvirtualsensor&idx=100&sensorname=Température Salon&sensortype=82

Le buzzer est un dispositif du type lighting que l'on peut créer dans l'interface DOMOTICZ.

Par contre rien n'est prévu pour les dispositifs du type général (sous-type text).
Il sera donc impossible de faire comme dans le projet précédent, dont le principe reposait sur la récupération de données de dispositifs texte mises à jour par des scripts PYTHON tournant sur la RASPBERRY PI.

Il va falloir opérer autrement. Le plus simple est de récupérer directement la valeur des capteurs et d'afficher des messages dédiés :

http://192.168.1.134:8080/json.htm?type=devices&rid=350

Cette requête récupère les informations du capteur de température dont l'identifiant est 350 :
       
ActTime    1586603674
ServerTime    "2020-04-11 13:14:34"
Sunrise    "06:55"
Sunset    "20:18"
result  
    0  
        AddjMulti    1

        AddjMulti2    1 
        AddjValue    0
        AddjValue2    0 
        BatteryLevel    69 
        CustomImage    0 
        Data    "14.4 C, 62 %"
        Description    "" 
        DewPoint    "7.21"
        Favorite    1 
        HardwareID    4 
        HardwareName    "MYSENSORS" 
        HardwareType    "MySensors Gateway USB"
        HardwareTypeVal    41 
        HaveTimeout    false 
        Humidity    62 
        HumidityStatus    "Wet" 
        ID    "0800" 
        LastUpdate    "2020-04-11 13:11:10"
        Name    "Temp & Humidité Extérieure" 
        Notifications    "false" 
        PlanID    "0" 
        PlanIDs
                    0    0 
        Protected    false 
        ShowNotifications    true 
        SignalLevel    "-" 
        SubType    "WTGR800" 
        Temp    14.4
        Timers    "false" 
        Type    "Temp + Humidity" 
        TypeImg    "temperature" 
        Unit    0 
        Used    1 
        XOffset    "0" 
        YOffset    "0" 
        idx    "350" 
        status    "OK" 
        title    "Devices"

Ensuite on formatera un message et on l'affichera :

Out : 14.4° 62%

Reste la 5ème ligne à afficher, un éventuel message d'erreur. Ce message est "Everything is Fine" si tout va bien.
S'il s'agit d'un message d'erreur il est affiché en jaune sur fond rouge.

Par exemple si la batterie d'un détecteur de mouvement est trop faible :

Motion: Battery too low

Ou si la température du congélateur est trop haute :

Freezer Temp: High

Nous allons inclure dans le code ESP8266 les traitements effectué auparavant par les scripts PYTHON :
  • surveillance des batteries
  • surveillance de la température du congélateur
Et le buzzer sera activé si un problème est détecté.

Donc pour résumer :

Les scripts PYTHON deviennent inutiles.
La souplesse sera moindre car sur le projet précédent il suffisait de modifier les scripts pour afficher des informations différentes.
Sur la version précédente la température et l'humidité extérieures étaient auparavant affichées sur les lignes 2 et 3.
Dernièrement j'ai regroupé ces deux informations sur la ligne 3,  et ajouté la température du garage sur la ligne 2, sans modifier le code ARDUINO !

Avec la version ESP8266 il faudra modifier la configuration. Mais avec un peu de travail la mise à jour pourra se faire par OTA.

Un seul capteur devra être créé manuellement dans le navigateur, l'écran TFT du type capteur de température et humidité :

http://192.168.1.134:8080/json.htm?type=createvirtualsensor&idx=100&sensorname=ESP8266 TFT&sensortype=82


2.1.2. Récupération des IDX

Chaque dispositif DOMOTICZ possède un identifiant unique, dit IDX, que l'on peut récupérer en recherchant le dispositif par son nom.
Cela suppose de récupérer la liste de dispositifs en filtrant par type, par exemple "temp" pour recevoir la liste des capteurs de température :

http://192.168.1.134:8080/json.htm?type=devices&filter=temp&&used=true&order=Name

Dans le cas où le nombre de dispositifs est important l'ESP8266 n'aura pas assez de mémoire pour charger la réponse à la requête.
Une solution à base d'ESP32 serait préférable.

Dans le code une valeur d'IDX par défaut est prévue. Tous les noms et identifiants des dispositifs sont configurables par un formulaire HTML.


2.1.3. Envoi et récupération d'informations

L'envoi d'une requête JSON pour récupérer les infos d'un capteur se présente ainsi :

void getSensorInfo(int idx, char *temp, char *hum, char *batt, int len)
{
  String request;
  HTTPClient http;
  int httpCode;
  // https://arduinojson.org/v5/assistant/
  const size_t bufferSize = 2 * JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(7) + 

                                          JSON_OBJECT_SIZE(50);
  if (idx == 0) {
    strncpy(temp, "not found", len);
  }
  else {
    request = DOMOTICZ_URL;
    request += "/json.htm?type=devices&rid=";
    request += idx;
    http.begin(request);
    httpCode = http.GET();
    Serial.printf("%s %d\n", request.c_str(), httpCode);
    if (httpCode > 0) {
      DynamicJsonBuffer jsonBuffer(bufferSize);
      JsonObject& root = jsonBuffer.parseObject(http.getString());
      if (temp) {
        strncpy(temp, root["result"][0]["Temp"], len);
      }
      if (hum) {
        strncpy(hum, root["result"][0]["Humidity"], len);
      }
      if (batt) {
        strncpy(batt, root["result"][0]["BatteryLevel"], len);
      }
    }
  }
  http.end();
}


Le WEB est bien fourni en tutoriels expliquent le fonctionnement de la librairie ArduinoJson.
Un lien plus qu'indispensable pour calculer la taille du buffer nécessaire :
https://arduinojson.org/v5/assistant/

La documentation JSON DOMOTICZ est très bien faite :
 https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Retrieve_status_of_specific_device

3. Le schéma

Le schéma est réalisé à l'aide de KICAD.
Il n'y a pas de routage de PCB pour l'instant.

Pour récupérer le projet voir plus bas :  7. Téléchargements.

Sur le schéma apparaissent 3 modules capteurs de température et humidité. Bien entendu un seul sera utilisé, au choix.
Ces trois modules ont une précision de 0.2°C en température et 2% en humidité.

Un transistor a été ajouté afin de pouvoir commander le buzzer en 5V.

4. IDE ARDUINO


J'utilise JSON 5. Quelques modifications seront nécessaires pour utiliser JSON 6.

Il faut ajouter une de ces 3 librairie au choix pour le capteur de température / humidité :

Dans l'IDE, dans le menu "Outils/Type de Carte" choisir "NodeMCU" ou "Wemos D1 R1" en fonction de la carte choisie.

Dans le menu "Outils / Flash Size" choisir 4M (1M SPIFFS).

5. Le code

Pour récupérer le projet voir plus bas :  7. Téléchargements.

5.1. Le service PHP

Le petit service PHP permettant de mettre à disposition le nom du saint du jour est à installer dans le répertoire /var/www/html/ de la RASPBERRY PI :

https://bitbucket.org/henri_bachetti/domoticz-esp8266-tft-display/src/master/apache/ephemeris.php

Bien entendu il faudra installer APACHE et PHP :

$ sudo apt-get install apache2
$ sudo apt-get install php5


Il est facile de le tester depuis son PC avec un navigateur :

http://192.168.1.134/ephemeris.php

Le navigateur affichera :

Le Saint du Jour



5.2. Configuration

Il faudra tout d'abord entrer le SSID, le mot de passe de la box et le nom du serveur NTP dans le sketch : esp8266-tft-display.ino

const char* ssid = "........";
const char* password = "........";


String ntpUrl("pool.ntp.org");

Tout le reste est dans le fichier config.h :

Le capteur de température à utiliser est choisi par option de compilation :

#define SENSOR      HDC2080
//#define SENSOR      SHT31D
//#define SENSOR      HTU21D


Il faut également configurer les accès à api.weatherstack.com :

#define METEO_URL         "http://api.weatherstack.com"
#define METEO_CITY        "Paris"
#define METEO_KEY             "................................"
#define METEO_PERIOD      2 // 2 Hours


La clé METEO_KEY sera récupérée en s'incrivant ici :
https://weatherstack.com/signup/free

Ensuite il faut renseigner le nom et l'identifiant du dispositif DOMOTICZ :

// sensor names in DOMOTICZ
#define THIS_SENSOR_NAME      "ESP8266 TFT"

5.3. DOMOTICZ

Créer manuellement le dispositif dans le navigateur :

http://192.168.1.134:8080/json.htm?type=createvirtualsensor&idx=100&sensorname=ESP8266 TFT&sensortype=82

Remplacer bien évidemment l'adresse IP, le port et éventuellement le nom du dispositif, qui doit être le même que dans le code (THIS_SENSOR_NAME).

5.4. Adaptations

L'écran TFT est assez grand pour afficher confortablement 4 à 5 lignes d'informations. Au delà il faudra utiliser soit une police de plus petite taille soit un écran plus grand.

5.5. Aspect serveur

Le code ESP8266 comporte une partie serveur HTTP. Un formulaire de configuration est prévu afin de pouvoir changer certains paramètres :
  • URL de DOMOTICZ
  • URL du service PHP
  • serveur NTP
  • ville pour la météo
  • clé d'accès api.weatherstack.com
  • période d'affichage de la météo
  • utilisation de l'API weatherstack.com
  • période d'affichage de la température
  • période d'affichage des informations
  • nom, identifiants et rôle des dispositifs

Les données de départ sont celles que l'on a configurées dans le sketch et fichier config.h, sauf la ville et la clé d'accès weatherstack : https://weatherstack.com/dashboard?logged_in=1

Le compteur d'utilisation de l'API weatherstack.com peut être consulté sur le dashboard weatherstack.

Auparavant les dispositifs (noms, identifiants) étaient configurés dans le code. Dernièrement, suite à une réinstallation de DOMOTICZ, la configuration a été étendue aux dispositifs, afin de rendre le système plus souple.

Les dispositifs à afficher sont configurés comme suit :
  • idx : l'identifiant du dispositif
  • prompt : le message à afficher sur l'écran
  • Temp : est-ce un capteur de température ? 
  • Humidité : est-ce un capteur d'humidité ? 
  • Battery : le capteur est-il alimenté par batterie ?
Ces renseignements sont à récupérer en affichant la fenêtre "Réglages / Dispositifs" de DOMOTICZ.
 
Pour que la surveillance du capteur de température du congélateur soit effectuée, le dispositif DOMOTICZ doit s'appeler "Freezer".

Tous les capteurs alimentés par batterie seront également surveillés.

Les données sont sauvegardées d'une part en RAM pour être utilisées immédiatement, mais également en EEPROM et seront donc relues au prochain démarrage.

5.6. Difficultés

Le code de gestion de l'afficheur TFT (tft.cpp et tft.h) est le même que dans le projet précédent, aux définition des broches près.
L'adaptation du code à l'ESP8266 et aux requêtes JSON a été très rapide, de l'ordre d'une petite journée.
La librairie Adafruit est parfaitement compatible ARDUINO et ESP8266.

6. Chargement

Pendant le chargement de l'ESP8266, le buzzer émet un bip continu. Ceci est dû à la broche GPIO16 choisie (la LED rouge). Il est conseillé de le débrancher si plusieurs chargements sont prévus pour des modifications.

En fonctionnement normal, le buzzer émet un seul bip après la connexion au réseau WIFI.

Il faut charger les icônes à l'aide du menu "Outils /  ESP8266 Sketch Data Upload".

Avant cela, si ce n'est déjà fait, il faut installer le plugin :
https://github.com/esp8266/arduino-esp8266fs-plugin

Il peut arriver que les images ne soient pas chargées. L'IDE se contente d'afficher ceci :

[SPIFFS] data    : /home/riton/projects/domoticz-esp8266-tft-display/arduino/esp8266-tft-display/data
[SPIFFS] size    : 1004
[SPIFFS] page    : 256
[SPIFFS] block   : 8192
/0010.raw
/0029.raw
/0033.raw
/0040.raw
/0013.raw
/0035.raw
/0019.raw
/0003.raw
/0001.raw
/0018.raw
/0028.raw
/0002.raw
/0026.raw
/0016.raw
/0007.raw
/0037.raw
/0020.raw
/0009.raw
/0021.raw
/0008.raw
/0024.raw
/0011.raw
/0004.raw
/0012.raw
/0025.raw
/0034.raw
/0006.raw
/0032.raw
/0017.raw
/0027.raw
/0036.raw
[SPIFFS] upload  : /tmp/arduino_build_710250/esp8266-tft-display.spiffs.bin
[SPIFFS] address  : 0x300000
[SPIFFS] reset    : nodemcu
[SPIFFS] port     : /dev/ttyUSB1
[SPIFFS] speed    : 115200
[SPIFFS] python   : python3
[SPIFFS] uploader : /home/riton/.arduino15/packages/esp8266/hardware/esp8266/2.5.2/tools/upload.py


Dans ce cas on peut le faire manuellement :

$ python esptool.py --baud 115200 --port /dev/ttyUSB1 write_flash 0x300000 /tmp/arduino_build_710250/esp8266-tft-display.spiffs.bin

Il faut installer esptool :
https://github.com/espressif/esptool

Ensuite après la connexion au serveur, l'heure s'affichera, ainsi que les autres informations :


7. Téléchargement

Pour télécharger le projet :
https://bitbucket.org/henri_bachetti/domoticz-esp8266-tft-display

Cette page vous donne toutes les informations nécessaires :
https://riton-duino.blogspot.com/p/migration-sous-bitbucket.html

8. Consommation

Ce montage consomme 130mA sous 5V, c'est à dire 0.65W.

9. Conclusion

Ce dispositif est plus complet et plus agréable que le précédent.

Cela n'empêche pas l'ancien modèle d'être encore utilisé. Il a simplement changé d'emplacement. Le nouveau se trouve dans le salon, l'ancien dans le bureau.

Ce genre de projet est assez amusant à mettre en œuvre et rend service au quotidien.
La fonction de surveillance des niveaux de batteries est un plus indéniable et permet d'éviter qu'une batterie ne tombe en décharge profonde.

La surveillance de la température du congélateur a déjà fait la preuve de son utilité dans la version précédente, suite à une panne de groupe compresseur en fin d'année dernière.
Dans ce genre de situation, il faut réagir vite car même avec un congélateur ayant une isolation tenant 72H, l'achat du remplaçant prend du temps, et le temps de descente en température du nouveau congélateur après branchement n'est pas négligeable.


Cordialement
Henri

10. Mises à jour

12/04/2020 : configuration HTML
14/08/2020 : configuration des devices


5 commentaires:

  1. Super projet, en effet!
    Je suis arrivé ici à la recherche d'infos sur la méthode OTA: j'utilise un nodeMCU ESP8266 comme serveur web pour afficher une info de relais lue à intervalle par un 2nd ESP8266 configuré en client. Ca fonctionne mais j'ai voulu tester l'upload des sketchs avec OTA (vsCode + Platformio). L'IP est codée fixe dans le main.cpp à 192.168.1.100. 1er upload en USB puis test OTA. Ca a marché une fois (et l'upload est très rapide!) mais depuis, rien à faire, j'ai:
    10:09:08 [DEBUG]: Options: {'esp_ip': '192.168.1.100', 'host_ip': '0.0.0.0', 'esp_port': 8266, 'host_port': 34101, 'auth': 'otapasswd', 'image': '.pio\\build\\nodemcuv2\\firmware.bin', 'spiffs': False, 'debug': True, 'progress': True}
    10:09:08 [INFO]: Starting on 0.0.0.0:34101
    10:09:08 [INFO]: Upload size: 332992
    10:09:08 [INFO]: Sending invitation to: 192.168.1.100
    10:09:18 [ERROR]: No Answer
    l'ESP8266 ne répond pas alors qu'un ping se fait avec succès (bien que je trouve le délai un peu long):
    Envoi d’une requête 'Ping' 192.168.1.100 avec 32 octets de données :
    Réponse de 192.168.1.100 : octets=32 temps=3 ms TTL=255
    Réponse de 192.168.1.100 : octets=32 temps=21 ms TTL=255
    Réponse de 192.168.1.100 : octets=32 temps=33 ms TTL=255
    Réponse de 192.168.1.100 : octets=32 temps=40 ms TTL=255
    J'ai redémarré le routeur mais sans succès...
    Une idée du problème?

    RépondreSupprimer
    Réponses
    1. Sans avoir aucune idée du code utilisé, difficile de répondre. Exposez votre problème sur le forum ARDUINO, en postant le code :
      https://forum.arduino.cc/c/international/francais/49

      Supprimer
  2. Bonjour Henri. toujours un plaisir de parcourir ce blog ou de vous retrouver sur le forum Adruino. Merci de mettre a notre disposition tous vos montages et de partager vos connaissances. Je me permet de vous poser une question: J'ai aussi comme vous fait des capteurs de températures que je met a jour comme vous en Json. Pas de soucis. Par contre j'ai voulu associer ma station météo (Oregon WMR200) dans DomoticZ mais bien que les relevées des capteurs vent et rafale soient reçut tous les 14 secondes DomoticZ ne prends en compte mes mesures qu'avec un pas de 5 Minutes! Avez vous mis en place une astuce pour parer a cela. Cordialement Alain

    RépondreSupprimer
    Réponses
    1. Non, je n'ai pas remarqué ce détail, probablement parce que j'utilise une période de 15 minutes, largement suffisante pour une mesure de température.

      Supprimer
  3. Bonjour Henry, bonjour a tous.
    OK. Merci pour la réponse. je viens de vérifier les mesures arrivent bien toutes les 14 Secondes, et dans les devices c'est bien mis a jour toutes les 14 secondes. Par contre sur l’historique, par exemple des dernières 24H le pas est de 5 minutes; J'imagine que la base de donnée est mise a jour avec ce pas sans faire de calculs afin de garder trace de la mesure de rafale la plus grande dans ce lap de temps. Effectivement cela ne pose aucun problèmes pour des mesures de température dont la période entre deux mesures peut être assez longue. Par contre dans le cas d'un capteur de rafales ça ne va pas. J'ai écris vite fait une petite routine arduino qui garde la valeur MAX des rafales sur cinq minutes, la c'est bon. Mais cela m'oblige a ajouter une interface supplémentaires.entre RFLINK et DOMOTIC.
    Je vais regarder si je trouve trace d'un script conçue pour des mesures rapprochées (rafales de vent) et si je trouve je reviendrais partager ici. Encore merci pour ce blog. Alain

    RépondreSupprimer