Transformer du code Arduino en plugin ESP Easy Mega pour ESP8266 / ESP32

Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram

ESP Easy Mega dispose déjà d’une liste impressionnante de plugins pour les capteurs et actionneurs les plus courants. Si vous n’avez pas trouvé votre bonheur dans les plugins existants ou si vous disposez d’un code Arduino déjà fonctionnel, nous allons voir comment faire pour le transformer en plugin.

 

Tutoriel actualisé le 15 mai 2020

Nous allons adapter le code Arduino d’une caméra thermique AMG8833 pour le transformer en plugin ESP Easy Mega. Le plugin fera une mesure par seconde et calculera la température moyenne (64 mesures), la température minimum et la température maximale relevée par la caméra thermique.

Il n’est plus possible de développer des plugins pour ESP Easy R120 (version stable). En effet, le code source est trop ancien et génère de nombreuses erreurs durant la compilation.

Installer Visual Studio Code et le plugin PlatformIO

Il est possible de développer un plugin à l’aide de l’IDE Arduino. Cependant, le code source du firmware ESP Easy Mega étant développé avec PlatformIO, ce sera beaucoup plus facile d’opter pour la même solution. PlatformIO est disponible sous la forme d’un plugin pour de nombreux éditeur de code (Atom, CLion, CodeBlocks, Eclipse, Emacs, NetBeans, Qt Creator, Sublime Text, Vim, Visual Studio, VSCode). Les fonctionnalités sont identiques quelque soit l’éditeur. J’ai opté pour Visual Studio Code de Microsoft, un éditeur rapide, gratuit et multi-plateforme. A vous de choisir !

Si vous ne connaissez pas encore PlatformIO, je vous conseille de commencer par lire ce tutoriel.

A LIRE AUSSI :
Débuter avec PlatformIO IDE sur VSCode (Windows, macOS, Raspbian, Linux)

install platformio vscode discover

Code Arduino utilisé pour l’imageur thermique AMG8833

L’AMG88xx (AMG8833 / AMG8831) de Panasonic est un capteur infrarouges matriciel Grid-EYE permettant de cartographier simultanément 64 températures (8×8 pixels). Il détecte la chaleur (le rayonnement infrarouge) du corps humain ou tout autre objet.
Attention, ce capteur n’offre pas une précision suffisante (± 2,5°C) pour un usage médical. Il ne faut pas l’utiliser pour un usage médical tel que la détection du COVID-19. On pourra par exemple l’utiliser pour faire de la détection de présence, du diagnostic de panne par analyse thermique..

Spécifications techniques du AMG8833

  • Breakout AMG8831 / AMG8833 mesure de température IR matricielle 64 pixelsMesure de température à matrice carrée constituée de 64 points (8×8 pixels)
  • Tension d’utilisation : 3.3V ou 5V
  • Précision de la température : ± 2,5°C ou ±4,5°F (typique)
  • Distance de détection humaine : 7m maximum
  • Différence de température équivalente au bruit est de 0,05°C à 1 Hz
  • Angle de mesure : 60°
  • Consommation de courant : 4,5mA (mode normal), 0,2mA (mode sommeil), 0,8mA (mode veille)
  • Interface I2C
  • Fréquence d’images : de 1 ou 10 images par seconde
  • Temps pour activer la communication après la configuration : 50ms puis 15ms
  • Notices techniques Panasonic

Il existe 4 versions du capteur. Les différences étant situés au niveau de la tension d’alimentation (3V3 ou 5V) et le facteur de gain (faible ou élevé). Dans le grand public, on trouve surtout la version AMG8833/AMG8831. La seconde référence indiquée sur le breakout (carte fille) est la référence de l’ancienne génération. Cela n’a aucun impact sur le fonctionnement. Panasonic n’indique pas clairement les changements d’une génération à l’autre.

Plus d’informations technique ici

Code source

Pour le code Arduino, j’ai simplifié l’exemple installé avec la librairie Adafruit. Ce code récupère une matrice de températures chaque seconde et calcul le minimum, le maximum et la température moyenne des 64 points. Rien de bien compliqué mais c’est assez pour l’exemple.

#include <Wire.h>
#include <Adafruit_AMG88xx.h>

Adafruit_AMG88xx amg;

float pixels[AMG88xx_PIXEL_ARRAY_SIZE];

void setup() {
  Serial.begin(9600);
  Serial.println(F("AMG88xx pixels"));

  bool status;

  status = amg.begin();
  if (!status) {
    Serial.println("Could not find a valid AMG88xx sensor, check wiring!");
    while (1);
  }

  Serial.println("--  Begin AMG88xx Test --");
  Serial.println();

  delay(100);   // let sensor boot up - attend le démarrage de capteur
}

void loop() {
  //read all the pixels - lit tous les pixels du capteur
  amg.readPixels(pixels);

  // Variables temporaires - Temp. var.
  float sum = 0;
  float mini = 80;
  float maxi = 0;
  float average = 0;

  for(int i=1; i<=AMG88xx_PIXEL_ARRAY_SIZE; i++){
    if ( pixels[i-1] < mini ) mini = pixels[i-1];  // trouve la température mini - find min temp.
    if ( pixels[i-1] > maxi ) maxi = pixels[i-1];  // trouve la température maxi - find max. temp.
    sum += pixels[i-1];                            // additionne toutes les températures - add all temp.
  }

  average = sum/AMG88xx_PIXEL_ARRAY_SIZE;  // calcul la température moyenne de la matrice - calculate matrix average
  // Imprime les résultats - print results
  Serial.print("Temp. mini: ");Serial.print(mini);
  Serial.print(" Temp. maxi: ");Serial.print(maxi);
  Serial.print(" Average: ");Serial.print(average);Serial.println();

  delay(1000); // Attend 1 seconde - wait a second
}

Matériel utilisé

Pour ce tutoriel, nous aurons simplement besoin d’un module ESP8266. N’importe quel NodeMCU ferra l’affaire.

Plus de cartes

Circuit

La communication avec l’AMG8833 se faisant via le bus I2C, le circuit est rudimentaire.

AMG8833 ESP8266
SDA D2
SCL D1
GND GND
3V 3V3

 

Circuit I2C AMG8833 sur ESP8266

Les étapes à suivre pour développer un plugin pour ESP Easy Mega

Disposer d’un code Arduino fonctionnel. Ce n’est pas une obligation, mais c’est plus facile de convertir du code Arduino déjà fonctionnel que de devoir le mettre au point dans un plugin ESP Easy. Un problème à la fois !

Adapter le code Arduino en plugin ESP Easy

Déclarer le plugin

Compiler, téléverser et tester !

Convertir le code Arduino en plugin ESP Easy

Un modèle (template) nommé _Pxxx_PluginTemplate.ino est disponible à la racine du dossier src (source). C’est un modèle général, voici une version minimale

Permet d’inclure le plugin lors de la compilation (nous verrons plus bas comment faire)

#ifdef USES_P129
Une série de define pour définir les constantes
#define PLUGIN_129
#define PLUGIN_ID_129 129
#define PLUGIN_NAME_129 "Nom du plugin"
#define PLUGIN_VALUENAME1_129 "Libellé de la première valeur retournée par le plugin"
Le coeur du plugin est constitué par une méthode switch / case.
Tout est expliqué en détail plus bas dans l’article
boolean Plugin_129(byte function, struct EventStruct *event, String& string)
{
  boolean success = false;

  switch (function)
  {
    case PLUGIN_DEVICE_ADD:
      {
        Device[++deviceCount].Number = PLUGIN_ID_129;
        Device[deviceCount].Type =     DEVICE_TYPE_I2C;
        Device[deviceCount].VType =    SENSOR_TYPE_TRIPLE; // Domoticz type, see controlleremu.py
        Device[deviceCount].PullUpOption = false;
        Device[deviceCount].InverseLogicOption = false;
        Device[deviceCount].FormulaOption = true;
        Device[deviceCount].DecimalsOnly = true;
        Device[deviceCount].ValueCount = 3;
        Device[deviceCount].SendDataOption = true;
        Device[deviceCount].TimerOption = true;
        Device[deviceCount].GlobalSyncOption = true;
        break;
      }
    case PLUGIN_GET_DEVICENAME:
      {
        string = F(PLUGIN_NAME_129);
        break;
      }
    case PLUGIN_GET_DEVICEVALUENAMES:
      {
        strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_129));
        break;
      }
    case PLUGIN_WEBFORM_LOAD:
      {
      }
    case PLUGIN_WEBFORM_SAVE:
      {
        success = true;
        break;
      }
    case PLUGIN_INIT:    
      {
        break;
      }     
    case PLUGIN_ONCE_A_SECOND:
      {    
      }   
  }
  return success;
}
#endif
Voici ce qu’il faut maintenant faire pour convertir votre code Arduino facilement :

Juste après le #ifdef USES_PXXX, déclarez les librairies au début du code,

Après la déclaration des constantes (DEFINE), déclarez les variables temporaires et initialisez les objets. Ici par exemple, on aura besoin de créer un objet pour communiquer avec le capteur AMG88xx et d’un tableau de 64 floats pour stocker les températures.

Adafruit_AMG88xx amg;
float pixels[AMG88xx_PIXEL_ARRAY_SIZE];

Insérer enfin le contenu de la boucle loop dans le cas (case) PLUGIN_ONCE_A_SECOND pour que la température soit actualisée chaque seconde.

Il y a quelques petites adaptations à faire dans le code :

  • Remplacer les Serial.print par addLog(LOG_LEVEL_INFO, message_a_envoyer)
  • Publier chaque valeur dans le UserVar. La position dans le tableau doit correspondre à la déclaration des libellés ce qui donne
    • UserVar[event->BaseVarIndex + 0] = mini; pour la température mini.
    • UserVar[event->BaseVarIndex + 1] = maxi; pour la température maxi.
    • UserVar[event->BaseVarIndex + 2] = average; pour la valeur moyenne
  •  Supprimer le delay(1000). Le délai d’attente est maintenant géré par ESP Easy

Code Arduino initial

amg.readPixels(pixels);
float sum = 0;
float mini = 80;
float maxi = 0;
float average = 0;

for(int i=1; i<=AMG88xx_PIXEL_ARRAY_SIZE; i++){
  if ( pixels[i-1] < mini ) mini = pixels[i-1]; if ( pixels[i-1] > maxi ) maxi = pixels[i-1];
  sum += pixels[i-1];
  
}

average = sum/AMG88xx_PIXEL_ARRAY_SIZE;
Serial.print("Temp. mini: ");Serial.print(mini);
Serial.print(" Temp. maxi: ");Serial.print(maxi);
Serial.print(" Average: ");Serial.print(average);Serial.println();
//delay a second
delay(1000);

Code ESP Easy

amg.readPixels(pixels);
float sum = 0;
float mini = 80;
float maxi = 0;
float average = 0;
for(int i=1; i<=AMG88xx_PIXEL_ARRAY_SIZE; i++){
  if ( pixels[i-1] < mini ) mini = pixels[i-1]; if ( pixels[i-1] > maxi ) maxi = pixels[i-1];
  sum += pixels[i-1];
}

average = sum/AMG88xx_PIXEL_ARRAY_SIZE;
String log = F("AMG88xx : Temp. mini: ");
log += mini;
UserVar[event->BaseVarIndex + 0] = mini;
addLog(LOG_LEVEL_INFO, log);
log = F("AMG88xx : Temp. maxi: ");
log += maxi;
UserVar[event->BaseVarIndex + 1] = maxi;
addLog(LOG_LEVEL_INFO, log);

log = F("AMG88xx : Temp. avg ");
log += average;
UserVar[event->BaseVarIndex + 2] = average;
addLog(LOG_LEVEL_INFO, log);

Déclarer le nouveau plugin au compilateur

Maintenant que le code du plugin est prêt, il nous reste à le déclarer pour qu’il soit intégré lors de la compilation. Tout ce passe dans le fichier define_plugin_sets.h situé à la racine du dossier src.

Ce fichier permet de configurer les plugins à embarquer en fonction de la version compilée (stable / dev / test). Inutile de trop chercher, placez directement votre plugin dans la version stable en créant une nouvelle clé

#define USES_P129

Il n’y a rien de plus à faire ! Enregistrez le fichier

Déclarer le plugin utilisateur pour l'embarquer dans ESP Easy

Compiler et téléverser le firmware ESP Easy Mega avec le plugin

Tout est prêt, il ne reste plus qu’à téléverser le firmware comme d’habitude avec PlatformIO

Depuis le menu PIO ➀, cliquez sur l’environnement qui vous intéresse ➁ pour afficher les fonctions de PIO. Cliquez sur Build pour compiler ou sur Upload pour compiler et téléverser

Compiler ou téléverser ESP Easy Mega depuis PIO

Ou depuis le Terminal, exécutez la commande suivante en remplaçant <version> par la version désirée

platformio run --target upload --environment <version>

Vérifier que le plugin a bien été embarqué

Comme d’habitude, connectez-vous à l’interface d’administration d’ESP Easy Mega puis ajoutez un nouveau device.

Dans la liste de sélection, vous devriez trouver votre plugin

Nouveau plugin utilisateur dans la liste de sélection

Et l’interface utilisateur de notre plugin !

Interface du plugin utilisateur

Description détaillées des méthodes

Si tout est claire, voici des explications un peu plus détaillées du fonctionnement du plugin

Entête du plugin ESP Easy : include et #define

Dans l’entête du plugin, nous peut définir les librairies à inclure éventuellement

#include <SPI.h>

Ensuite, tous les modules doivent être identifiés par une série de clés. Il est important de bien attribué l’ID choisi à toutes les clés pour que le plugin fonctionne.

#define PLUGIN_129 Identifiant du plugin
#define PLUGIN_ID_129 129 L’ID du plugin
#define PLUGIN_NAME_129 “Indoor Air Quality – MQ135” Le libellé qui sera affiché dans la liste de choix
#define PLUGIN_VALUENAME1_129 “Temp. mini Variable de sortie du plugin. Libellé affiché entre guillemets
#define PLUGIN_VALUENAME2_129 “Temp. maxi”
La seconde sortie numérique du plugin
#define PLUGIN_VALUENAME3_129 “Average”
Et ainsi de suite

Fonction Plugin_XXX

Le plugin est encapsulé dans une fonction. Cette fonction prend plusieurs paramètres qu’il suffit de tester. Le moteur d’ESP Easy lance à intervalle régulier les plugins associés aux Devices configurés.

boolean Plugin_129(byte function, struct EventStruct *event, String& string) 
{
   // contient le code du plugin
}

Par convention, on nomme le plugin par Plugin_ID_DU_PLUGIN

Plusieurs méthodes sont obligatoires. Chaque méthode est appelée par un switch / case à intervalle régulier. Une méthode renvoi éventuellement une valeur

Méthode PLUGIN_DEVICE_ADD

La première méthode (PLUGIN_DEVICE_ADD) permet de définir les paramètres qui sont communs à tous les Devices

case PLUGIN_DEVICE_ADD:
      {
        Device[++deviceCount].Number = PLUGIN_ID_129;
        Device[deviceCount].Type = DEVICE_TYPE_I2C;     // Device I2C, voir plus bas
        Device[deviceCount].VType = SENSOR_TYPE_TRIPLE; // Voir plus bas
        Device[deviceCount].PullUpOption = false;
        Device[deviceCount].InverseLogicOption = false;
        Device[deviceCount].FormulaOption = true;       // Autorise la formule
        Device[deviceCount].DecimalsOnly = true;        // Valeur décimale
        Device[deviceCount].ValueCount = 3;
        Device[deviceCount].SendDataOption = true;
        Device[deviceCount].TimerOption = true;
        Device[deviceCount].GlobalSyncOption = true;
        break;
      }

Les principaux paramètres sont

  • Type : le type de matériel connecté. On peut choisir parmi
    • DEVICE_TYPE_SINGLE (1) : connecté sur une entrée numérique (datapin)
    • DEVICE_TYPE_I2C (2) : l’appareil communique avec l’ESP8266 / ESP32 via le bus I2C
    • DEVICE_TYPE_ANALOG 3 : on utilise le convertisseur A/N de l’ESP8266 (Pin TOUT, par exemple A0)
    • DEVICE_TYPE_DUAL (4) : appareil connecté à l’aide de 2 entrée numériques
    • DEVICE_TYPE_DUMMY (99) : appareil logique sans connexion physique (Dummy device). Lisez cet article pour en savoir plus
  • VType. correspond au type de renvoyer par le plugin suivant le format Domoticz. Tous les types sont listés dans le fichier controlleremu.py
    • SENSOR_TYPE_SINGLE (1) : un sortie
    • SENSOR_TYPE_TEMP_HUM (2) : 2 sorties de type température & humidité (DHT11 ou DHT22)
    • SENSOR_TYPE_TEMP_BARO (3) : 2 sorties de type température & pression atmosphérique (BMP180)
    • SENSOR_TYPE_TEMP_HUM_BARO (4) : 3 sorties, température, humidité, pression atmosphérique (BME280)
    • SENSOR_TYPE_DUAL (5) : générique, 2 sorties
    • SENSOR_TYPE_TRIPLE (6) : générique, 3 sorties
    • SENSOR_TYPE_SWITCH (10) : 2 états, interrupteur
    • SENSOR_TYPE_DIMMER (11) : 1 sortie variateur
    • SENSOR_TYPE_LONG (20) : 1 sortie
  • ValueCount : nombre de variable de sortie. Ce compteur doit correspondre au nombre de clé PLUGIN_VALUENAME1_xxx

PLUGIN_GET_DEVICENAME

Cette méthode renvoi le nom du Device.

PLUGIN_GET_DEVICEVALUENAMES

Cette méthode est appelée à l’ouverture de la page de configuration du module. Elle permet d’ajouter une nouvelle ligne pour chaque variable de sortie du plugin. Utilisez le formalisme imposé sans oublier d’incrémenter l’indice du tableau TaskDeviceValueNames[X] et de la variable PLUGIN_VALUENAMEX_129

strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_129));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_129));
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_129));

Voici par exemple ce que l’on obtient.

PLUGIN_GET_DEVICEVALUENAMES déclaration des libellés pour chaque variable

PLUGIN_INIT

Cette méthode est appelée à l’initialisation du plugin. On pourra par exemple recharger des paramètres.

La méthode doit obligatoirement se terminer par success = true;

PLUGIN_READ,  PLUGIN_ONCE_A_SECOND, PLUGIN_TEN_PER_SECOND:

Cette méthode permet de lire la valeur des capteurs et d’une manière plus générale de réaliser tous les traitements que l’on réalise habituellement dans la boucle loop() d’un programme Arduino. En fonction de la fréquence de traitement désiré, on dispose de 3 méthodes :

  • PLUGIN_READ le plugin est exécuté suivant le délai indiqué sur la page de configuration du Device une seule fois.
  • PLUGIN_ONCE_A_SECOND cette tâche sera exécutée une fois par seconde avec toutes les autres tâches appelant cette fonction.
  • PLUGIN_TEN_PER_SECOND idem mais 10 fois par seconde.

Au démarrage de l’ESP, les tâches sont donc ajoutées dans des listes. Elle seront exécutez à la fréquence choisie. Il faut donc bien choisir la fréquence d’exécution et ne pas créer un code trop lourd pour que l’ESP ait le temps de traiter toutes les tâches.

La méthode doit obligatoirement se terminer par success = true;

 

Voilà, vous connaissez l’essentiel pour débuter le développement de vos propres plugins. D’apparence compliquée, c’est en fait assez simple.

Avez-vous aimé cet article ?
[Total: 2 Moyenne: 5]
Partager sur facebook
Partager sur twitter
Partager sur linkedin
Partager sur pinterest
Partager sur email
Partager sur telegram

Vous avez aimé ce projet ? Ne manquez plus aucun projet en vous abonnant à notre lettre d’information hebdomadaire!

quel modèle esp8266 choisir
Quel modèle d'ESP8266EX choisir en 2020 ?
guide choix esp32 development board
Quel ESP32 choisir en 2020 ?

Vous rencontrez un problème avec ce sujet ?

Peut-être que quelqu’un a déjà trouvé la solution, visitez le forum avant de poser votre question

8 Commentaires
  1. bonjour, je voudrais savoir svp pour créer un device, avec le code d’un autre : j’ai trouver le code pour intégrer un LIDAR (TFmini) mais je ne sais pas où l’intégrer, sur la D1 mini via PC? sur le portail en ligne de ESP easy?…
    merci d’avance !

    le code : https://www.letscontrolit.com/forum/viewtopic.php?f=5&t=3956&p=37172#p37172

  2. Bonjour! Une question svp, quand on a codé le plugin, on doit mettre où le code? En effet j’aimerais créer le TFmini (LIDAR) grâce au code trouvé ici : https://www.letscontrolit.com/forum/viewtopic.php?f=5&t=3956&p=37172#p37172
    mais je ne vous pas où coller ce code…Si qqn peut me donner une piste, merci !

    Après, si j’ai compris le précédent tuto, je devrai compiler et exporter le binaire, on verra bien 😉

  3. Bonsoir, pas de nouvelles sur la publication de la source, même à débogguer ? Merci.

  4. Bonjour, je suis également intéressé par ce code. J’aimerais le tester et aussi l’adapter pour un MQ-7

  5. J’attends impatiemment la suite de cet épisode pour inclure mon mq135 ! Et un bin compilé pour les flemmards 😉
    je vais essayé en attendant de le réaliser de mon coté !
    merci encore pour tout ces tutos !!!

    • Bonjour Sébastien. J’ai également la même demande sur la version anglaise du blog. Le plugin est développé mais je suis un peu déçu par les mesures. Je voulais prendre le temps de vérifier avant de publier. C’est peut être mon capteur qui est défectueux. Je vais le publier sur GitHub pour que vous puissiez essayer et me dire si vos mesures sont meilleures que les miennes. J’ai aussi regarder d’autres capteurs de CO2 sans calibration, mais le prix est plus élevé (30€).

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

Domotique et objets connectés à faire soi-même
Vous avez aimé ce tutoriel

Ne manquez plus les prochains projets

Recevez chaque semaine le récapitulatif des tutoriels et projets.

Vous pouvez vous désabonner à tout moment.