A la découverte de ThingSpeak avec l'ESP8266 et un capteur de température.


Dans cet article nous allons voir comment envoyer des données d'un ESP8266 vers la plateforme d'IoT Thingspeak.



Après ce petit intermède de quelques articles consacrés aux Raspberry Pi, nous allons revenir à nos premiers amour que sont les ESP8266 et en profiter pour faire un peu de veille technologique. 
Dans ce nouvel article, je vous propose de découvrir la plateforme open source Thingspeak. Qu'est-ce que c'est ? A quoi ça sert ? Comment on l'utilise ? A quoi pourra t'elle nous être utile en domotique.

Et si vous me lisez de temps en temps, vous savez que dans mes articles il y trois constantes. La première est que je raconte souvent ma vie ! La seconde c'est que j'aime m'appuyer sur des cas d'usages concrets pour expliquer les choses et la dernière c'est que j'invente souvent des constantes quand ça m'arrange ! Pour une fois je ne vais pas vous raconter ma vie, mais nous allons découvrir ThingSpeak avec l'exemple du suivi de la température de mon salon en utilisant un ESP8266 pilotant un capteur DHT11 (ou DHT22). 

Et si la température de mon salon ne vous intéresse pas, vous pourrez faire la même chose avec le votre! 😁








Thingspeak 

Dans le monde des objets connectés (IoT), les services et les technologies sont en constante évolution. Presque tout le monde à désormais entendu parler du fameux service IFTTT qui permet de déclencher des actions lorsque certains événements sont détectés. Par exemple, lorsque je reçois la facture d'électricité dans ma boite mail, j'éteins le chauffage de la maison. Bon, ok, c'est un exemple et il vaut ce qu'il vaut ! 



Parmi tous ces nouveaux services qui commencent à prendre de l'envergure dans le monde de l'IoT, il y a Thingspeak, qui, comme son nom l'indique, permet aux objets de parler! Autrement dit, Thingspeak est service qui fourni des applications et des API qui permettent de collecter, afficher, analyser des données ainsi que de déclencher certaines actions en fonction de valeurs. Nous ne sommes pas dans la richesse d'actions de IFTTT mais les deux plateformes savent dialoguer entre elles et Thingspeak pourra déclencher un action programmée sur IFTTT. Par exemple, si la température de la salle de bain dépasse 50°C, IFTTT déclenche l'envois d'un SMS. Ok, pour les exemples j'ai des progrès à faire ...

ThingSpeak est une plateforme riche en possibilités et en fonctionnalités. Vous pourrez vous amuser à faire de l'analyse de données, à suivre votre consommation d'énergie, à compter les voitures qui passent dans votre rue, à prédire le débordement de la rivière où à construire une station météo. Mais avant de pouvoir accéder à toutes ces fonctionnalités avancées, il va falloir commencer par les bases. Et pour ce faire je vous propose un projet tout simple, qui va nous permettre de ressortir du tiroir un de nos ESP8266 (💜) et de le programmer pour qu'il nous permette de suivre les données d'une sonde de température sur une jolie courbe ThingSpeak.

Exemple de courbe de suivi de température


Créer un compte 

La première chose à faire pour utiliser les services de la plateforme ThingSpeak va être de se créer un compte. L'accès à la plateforme nécessite un compte MathWorks. Ne me demandez pas pourquoi, c'est comme ça!  Alors on le fait et on ne discute pas ...
  1. Allez sur le site ThingSpeak et cliquez sur <Sign In> puis cliquez en bas sur le texte "Sign up for the first time" ou directement sur CE lien (https://thingspeak.com/users/sign_up).
  2. Ensuite laissez vous guider: 
    1. Remplissez les champs qui sont demandé. Bien que ce soit en Anglais, aucune surprise: Adresse mail, mot de passe, nom, prénom, pays, tour de poitrine ... non je plaisante pour ce dernier. 


    2. Ensuite allez dans votre messagerie, vous devriez  trouver le mail de MathLab, dans lequel il y a un lien sur lequel il faudra cliquer vous valider votre adresse mail et de ce fait votre inscription. 


  3. Lorsque cette étape d'inscription est réalisée, vous pouvez revenir sur le site ThingSpeak, cliquer sur <Sign In> et cette fois vous pouvez vous identifier avec le compte que vous venez de créer: suivre les étapes 1,2 et 3 dans ci-dessous: 
    3 étapes pour le loger au service.



Welcome Home ! 

Créer un channel

Une fois connecté, nous allons devoir créer ce que ThingSpeak appel un "channel". Cela représente un ensemble de données regroupées entre elles et qui proviennent d'un objet connecté, d'un autre "channel" ou d'un service web. Un channel est composé de champs ("field" en Anglais). Il peu y en avoir jusqu'à 8. Et chaque champ représente une donnée.

Pour continuer sur notre exemple de sonde de température, nous allons créer le channel DHT11n1 qui représentera le capteur de température DHT11 numéro 1 dans notre installation. Si de votre coté vous utilisez un autre modèle de composant, le DHT22 par exemple, vous pouvez adapter le nom de votre channel.

Le capteur DHT11 permet d'avoir la température mais aussi le pourcentage d'humidité de l'air. Donc tout naturellement, dans notre channel nous allons créer deux champs:
  1. field1 = Température
  2. field2 = Humidité
Pour ce faire, encore une fois il faut se laisser guider:
  1. Cliquez sur <<New Channel>>
  2. Remplissez les premiers champs: Name, Description, Field 1 et Field 2. Tous les autres ne seront pas utiles pour le moment. 

  3. Et validez avec <<Save Channel>>

Et voila, nous disposons désormais d'un channel dans lequel nous allons pouvoir envoyer nos données. Nous voyons dès sa création deux tableaux qui pour le moment sont vides. Le temps de faire un petit montage électronique et d'écrire un petit programme informatique et ils ne le seront bientôt plus.

Channel avec deux champs, sans aucune données.

Menu de gestion du channel

Avant de passer à la partie externe, c'est à dire la collecte des données depuis le capteur et leur envois par l'ESP8266, faisons une petite visite sur les différents menus qui sont à notre disposition pour utiliser notre channel.

Les View



Ces deux menus permettent de spécifier une mise en forme et un affichage de nos données différents. La vue privée est uniquement accessible en vous connectant à votre compte utilisateur. La vue publique est ce que les autres verront lorsqu'ils visiteront votre "channel". Vous pouvez avoir des informations différentes sur chaque vue, personnaliser l'affichage avec des plug-ins et même désactiver la vue publique si vous souhaitez vivre caché.

Channel Settings

Ce menu permet de revenir sur les informations que nous avons donné à la création du channel. En plus il permet de supprimer toutes les données et même de supprimer le channel.

Sharing 

Permet de définir les options de confidentialité et de partage de votre channel.
ThingSpeak vous permet de contrôler qui peut voir vos données. Indépendamment des paramètres de cet onglet, la lecture ou l'écriture de données dans les champs d'un canal nécessite la clé API appropriée pour le canal.

API Keys

Ce menu est important car c'est ici que vous allez trouver les "clés" qui seront nécessaires pour accéder depuis l'extérieur à votre channel. Ces clés sont des identifiants qui ressemblent à quelque chose comme "KKB7O4JIP72ET8DNG". Il faudra donner cette clé dans toutes les requêtes que vous ferez en utilisant les API ThingSpeak et c'est ce qui permettra d'identifier votre channel.

Vous trouvez aussi dans ce menu des exemples de requêtes que vous pourrez faire pour déclencher diverses actions. Je vous laisse explorer tout cela, mais je peux déjà vous dire que nous allons utiliser celle qui s'appelle "Update Channel Feed" dont voici un exemple:

https://api.thingspeak.com/update?api_key=KKB7O4JIP72ET8DNG&field1=0
Cette requête permet d'envoyer des valeurs dans le champs 1 d'un channel. Si nous l'adaptons à notre situation nous pourrions avoir :

https://api.thingspeak.com/update?api_key=KKB7O4JIP72ET8DNG&field1=0&field2=0
C'est cette requête que nous allons utiliser pour envoyer des valeurs dans notre channel. Avec field1 qui sera la température et field2 l'hygrométrie.

Les requêtes fonctionnent en https ou en http sur le port 80.

Data Import / Export 

Cette dernière section est destinées à l'import et l'export de données via des fichiers au format CSV.








Coté Hardware

Maintenant que nous disposons d'un accès à la plateforme d'IoT dans le cloud (ça fait moderne de dire ça) nous allons regarder ce qu'il nous faut à la maison comme matériel et comment connecter tout ça ensemble avant de passer au programme. 

Liste du matériel 

Notre objectif étant de relever une température, l'humidité et de l'envoyer à ThingSpeak il va nous falloir :

  • Un capteur de type DHT11 ou DHT22. J'ai acheté un lot de 5 DHT11 avec la livraison express ICI (cout de reviens moins de 2€ par capteur).
  • Un Esp8266. J'ai choisi ICI un NodeMCU ESP12e (prendre la v3 compatible CH340). Vous pouvez prendre un Esp01 ou Esp01s mais dans ce cas vous devrez légérement adapter le programme que nous allons écrire plus bas (coût de revient moins de 4€).
  • Des LED (une bleue et une verte, mais c'est question de gout), des câbles Dupont  et des résistances 220Ω (deux). Mais si vous n'avais pas envie de vous embêter à commander tout ça individuellement, je vous invite à prendre un kit de composants comme CELUI-CI.
  • 3 breadboard 170 points. Pour le NodeMCU c'est compliqué de travailler sur des breadboard plus grande alors j'aime mieux utiliser des petites comme ICI


Je ne compte pas vraiment le coût des petits accessoires car en achetant des lots, les couts unitaires deviennent négligeables. Mais si je compte les 3 breadboard, l'ESP et le DHT11, nous allons fabriquer un capteur de température, humidité wifi pour moins de 7€.

Quelques conseils pour vos achats


Ma philosophie commerciale 


N'hésitez pas à faire vos achats après avoir cliqué sur mes liens. Déjà parce que cela ne vous fera pas payer plus cher, bien au contraire, car souvent vous bénéficierez d'un prix plus compétitif. Ensuite parce que les quelques centimes de commission qui me seront reversés, seront aussi utiles à m'aider pour investir dans du matériel et en faire profiter notre communauté, que dans les poches des grands sites marchands.

Vous pouvez trouver tous les petits accessoires électroniques, tels que les câbles dupont, les LED, les résistances sur tous les grands sites marchand (AliExpress, Amazon, Banggood, eBay, ...) a des prix compétitifs mais qui au final, lorsque l'on ajoute le transport, se rapprochent tous.
En ce qui me concerne je privilégie souvent Amazon pour la qualité de son service et les délais rapides de livraison avec l'abonnement Prime. Et aussi eBay, pour la qualité de leur site, la gestion du SAV et surtout la richesse du catalogue sur les composants.

Capteurs DHT

Les capteurs de températures existent sous différents modèles et différentes dénominations dont certaines sont équivalentes.

DHT11 = RHT01
DHT21 = RHT02= AM2301 = HM2301
DHT22 = RHT03= AM2302
DHT33 = RHT04 = AM2303
DHT44 = RHT05

Je n'évoquerai que le DHT11 et le DHT22 car je ne maîtrise que ceux-ci et j'en garantis la compatibilité avec tout ce que nous faisons dans cet article.

Vous pouvez les trouver sous forme de composants ou alors sous forme de modules.

Sous la forme de modules, vous n'aurez que 3 broches à câbler et surtout pas besoin de mettre une résistance de rappel.

DHT sous forme de modules

Sous forme de composants il vous faudra connecter une résistance de rappel entre le signal et VCC.

DHT sous forme de composants.

Si vous préférez ne pas trop alourdir votre montage ou si la notion de résistance de rappel (Pull Up) ne vous parle pas, procurez vous le DHT sous forme de module.

  • DHT22: Le moins cher que j'ai trouvé est sur eBay ICI (bien sélectionner la référence AM2302 Module).
  • DHT11: Le moins cher est aussi sur eBay ICI

En terme de performance les deux sont assez différents. Pour ma part j'ai pris le DHT11 pour son prix et parce que pour faire un essais je n'avais pas besoin de quelque chose de très précis.
Mais le DHT22 sera beaucoup mieux sur plusieurs points comme le montre le tableau ci-dessous:

Tableau de comparaison  DHT11 DHT22
Alimentation De 3 à 5V De 3,3 à 6 V
Consommation lors d’une mesure 2,5mA  1,5mA
Consommation au repos) Inconnu 50 µA
Plage de mesure d’humidité de 20 à 80% (précision 5%)  de 0 à 100% (précision 2 à 5%)
Plage de mesure de température de 0 à 50°C (± 2°C)  de -40 to 80°C (±0.5°C)
Fréquence de meure 1 par seconde  2 par seconde
Poids et dimensions 15.5mm x 12mm x 5.5mm  25 x 15 x 9 mm
Connexion 4 broches   4 broches 
Stabilité à long terme +/- 0.5% par an +/- 1% par an

Composants électroniques et câbles



Plutôt que de vous embêter à chercher les composants électroniques par lots du même type, n'hésitez pas à investir dans un lot comme CELUI-CI. Les Set A et Set B contiennent tout ce qu'il faut: résistances, breadboard, câbles, LED.

Connexions


Maintenant que nous avons rassemblé tous nos jouets composants, nous devons réfléchir à comment connecter tout ça. A priori rien de compliqué car il suffit de raccorder la broche de "signal" (S) du capteur de température à une broche numérique du microcontrôleur (j'ai vu sur les sites que souvent on écrit μC pour dire microcontrôleur). Mais ceux qui ont déjà suivi d'autres de mes articles, auront peut être déjà détecté que je n'aime pas quand c'est trop simple. Donc je vais rajouter une toute petite couche et en plus nous allons connecter deux LED à notre μC:

  • Une LED bleue qui nous servira à identifier que l'ESP8266 est bien alimenté electriquement. 
  • Une LED verte qui s’allumera à chaque fois que l'ESP enverra des donnés à ThingSpeak. 
Ces deux LED nous permettrons de suivre un peu le fonctionnement de notre système. Pour le choix des couleurs il est très personnel et libre à vous d'en changer.

Précisions sur les LED  

Comme vous le savez certainement, il faut toujours mettre une résistance dans la boucle d'alimentation d'une LED. La valeur de la résistance à mettre se calcul de la manière suivante:

R = (Vcc - Useuil) / I
Avec: 
  • Vcc = La tension d'alimentation. Dans notre cas ce sera 3,3V si la LED est alimentée par une broche de l'ESP ou 5V si le LED est alimentée par l'USB. 
  • Useuil = La tension seuil de la LED. Si vous ne connaissez pas ce concept je vous laisse chercher sur internet. En gros c'est la tension minimum nécessaire aux bornes de la LED pour qu'elle s’allume. 
  • I = l'intensité qui passe dans le circuit. Comme dans notre cas, la seule intensité qui circulera dans le circuit de chaque LED, sera le courant nécessaire pour allumer la LED, nous n'aurons que cela à prendre en compte. I sera donc le courant souhaité dans la LED. 

Et comme je suis très sympa, je vous ai même fait un petit tableau pour vous aider dans vos calculs: 

Tension et intensité en fonction de la couleur d'une LED

Ce tableau présente des ordres de grandeur car ces valeurs peuvent varier d'un contexte à un autre.

Comment on se sert de ce tableau ? 

C'est simple et on va calculer la résistance pour notre LED bleue qui servira de témoin d'alimentation.
Pour la tension de seuil, si vous ne connaissez pas les valeurs exactes de votre modèle, prenez la valeur la plus basse dans le tableau. On va donc prendre Useuil = 2,7V.
Pour l'intensité, on voit que la LED va commencer à s'allumer à partir de 1mA. Et qu'elle brillera au maximum à 20mA. Pour ne pas prendre de risque, on va prendre entre les deux. Disons qu'on va imposer un courant de 10mA dans notre LED. On aura donc I = 10mA.
Et pour finir, comme la LED servira à savoir si le μC est alimenté, nous allons donc l'alimenter par le circuit d'alimentation qui est l'USB. La tension de l'USB est de 5V. Vcc = 5V.

Ce qui nous donne: 
R = ( 5 - 2,7) / 0,01 = 230 Ω

Dans le monde des LED et des résistances, tout est question d'approximations. Il faut faire les calcul avec les valeurs pour lesquelles on a le plus de tolérance. Et ensuite on peut donc adapter le résultat.
Pour ma LED bleue, je prendrai la résistance à ma disposition qui est le plus proche de 230Ω, soit une 220Ω.

En refaisant le calcul pour le LED verte, j'obtiens 150Ω (n'oubliez pas qu'elle sera allimentée par une broche 3,3V de l'ESP). Mais pour voir un peu les capacités des LED et surtout mettre en exemple le coté approximatif de ces calculs, je vais placer une résistance 1000Ω.

Câblage du DHT

La photo ci-dessous montre comment se câble le DHT11, sous forme de composant ou directement sous forme de module. Pour le DHT22 c'est la même chose.

Schéma de câblage



Schéma de câblage du montage

Les points particuliers sont: 

  1. La LED bleue connectée à VU qui est une broche directement raccordée sur l'alimentation USB de l'ESP. Elle est donc alimentée en 5V et sous tension en même temps que le μC.
  2. On connecte D0 à RST ainsi nous pourrons faire un reset logiciel en envoyant un pulse à LOW sur D0. Pour plus d'information je vous invite à consulter mes articles de découverte sur l'ESP (comme ICI ).
  3. Le DHT est allimenté en 3,3V et sa broche de signal est connectée à D1. 
  4. La LED verte sera allumée par la broche D8 lorsque le programme sera dans un cycle de collecte puis envois des données.
Voici ce que ça donne:


Et voila! Nous avons désormais notre compte actif sur la plateforme ThingSpeak, nous avons notre montage câblé, il ne nous reste plus qu'à écrire le programme pour faire fonctionner tout ça ensemble. C'est que du bonheur! On fonce ...








Programmation 

Prérequis

Avant de commencer voici quelques prérequis qu'il vous faudra respecter.

Savoir utiliser programmer l'ESP

Pour programmer l'ESP j'utilise l'IDE Arduino en activant les bon paramètre pour que le code généré soit compatible avec l'ESP. Dans mon cas, c'est un NodeMCU ESP12e.


Je ne vais pas vous expliquer comment utiliser l'IDE Arduino, ni comment le configurer et je vais supposer que vous savez téléverser un programme dans votre ESP.

Installation des librairies 

Pour que le programme fonctionne, il va lui falloir la libraire DHT.
La  librairie DHT offre un moyen simple d'utiliser n'importe quel capteur DHT pour lire la température et l'humidité avec vos cartes ESP8266 ou Arduino.

Installation de la bibliothèque DHT
  1. Cliquez ici pour télécharger la bibliothèque de capteurs DHT . Vous devriez avoir un  dossier .zip dans vos téléchargements. 
  2. Décompressez le .zip dossier et vous devriez obtenir le dossier DHT-sensor-library-master 
  3. Déplacez ce dossier dans votre répertoire d'installation des librairies IDE Arduino puis renommez le en "DHT". Si vous ne savez pas où se trouve le répertoire d'installation des librairies, regardez dans le menu "préférences" de l'IDE. 


Pour que la librairie DHT fonctionne elle va avoir besoin de la librairie Adafruit Unified Sensor.

Installation de la bibliothèque Adafruit Unified Sensor

  1. Cliquez ici pour télécharger la  bibliothèque Adafruit Unified Sensor . Vous devriez avoir un dossier .zip dans votre dossier Téléchargements
  2. Décompressez le dossier .zip et vous devriez obtenir le dossier "Adafruit_sensor-master".
  3. Renommez le dossier en "Adafruit_sensor"
  4. Déplacer le dossier vers votre dossier d'installation des bibliothèques IDE Arduino, au même niveau que la librairie "DHT". 
Enfin, rouvrez votre IDE Arduino

Explications de code

Avant de vous laisser avec tout le code du programme, pour faciliter la compréhension, je vais détailler la logique de quelques sections.

Algorithme général

L'objectif du programme est de faire des relevés de température et humidité à intervalles réguliers et d'envoyer ces valeurs sur le channel ThinkSpeak créé à cet usage.
Le programme devra donc:

  • se connecter en wifi à un point d'accès local
  • lire les données sur le capteur
  • envoyer les données
  • attendre un moment et recommencer la lecture des données. 
Par rapport à la plateforme ThingSpeak, l'ESP sera "client". Mais je souhaite aussi pouvoir envoyer une requête à l'ESP pour lui demander des choses. L'ESP devra donc également être serveur. 

Connexion Wifi 

J'aime bien maîtriser les choses et notamment les adresses IP des équipements qui se connectent sur mon réseau local. Pour cette raison, lors de la connexion de l'ESP au Wifi, j'impose les adresses IP ainsi que le nom d’hôte.

// Définition des adresses IP
IPAddress oipIpEsp(192, 168, 43, 60);
IPAddress oipGateway(192, 168, 43, 1);
IPAddress oipSubnet(255, 255, 255, 0);
IPAddress oipDns(192, 168, 43, 1);

const char* sHostname ="esp12n1";

Lorsque je mets au point un programme, j'ai souvent besoin de connecter, déconnecter, re-connecter, rebooter, le wifi et l'ESP. Cela solicite beaucoup les connexions et parfois l'ESP à du mal à se reconnecter. Pour cette raison j'ai un peu amélioré le code que l'on trouve partout pour connecter l'ESP.

  • Je vais vérifier si l'ESP a déjà une adresse IP. 
  • Ensuite je demande une déconnexion, ce qui a pour effet de remettre les données à zero.
  • J'impose la configuration des données
  • Et je vais imposer un temps d'attente de la connexion "MAX_TIME_WAIT_WIFI". Si ce délais est dépassé, j'appelle la fonction vFonctionReboot() qui a pour effet de faire un RESET matériel de l'ESP. Suite à ce RESET, tout le SETUP est repris depuis le début. 

 ////////////////////////////////////////////////////////// disconnect au cas où! 
  WiFi.disconnect(1);

//////////////////////////////////////////////////////////// Initialisation Wifi 
  WiFi.hostname( sHostname ); 
  WiFi.config(oipIpEsp, oipGateway, oipSubnet, oipDns );
  delay(100);

while (WiFi.status() != WL_CONNECTED ){
     delay( 1000 ); 
     Serial.print( "." );
     if ( iCompteur++ > MAX_TIME_WAIT_WIFI ) vFonctionReboot();
  }


Reboot

La fonction vFonctionReboot() ne fait rien d'autre que de passer la broche D0 à LOW. Et comme nous l'avons vu lors du montage, DO est raccordé à la broche RST. Donc le passage de D0 à LOW a pour effet d'envoyer un pulse sur GND à RST et provoque un reset matériel du 𝜇C.

Fonction serveur

Lorsqu'il est connecté au wifi, l'ESP peut se comporter comme client wifi. C'est à dire qu'il peut envoyer une requête HTML à un serveur. Mais il peut aussi se comporter comme serveur. C'est à dire qu'il peut recevoir des requêtes et réagir en fonction de ces dernières.
Pour ce comportement en mode serveur, il faut initialiser un objet ESP8266WebServer et ensuite associer des fonctions qui seront appelées lorsque le serveur recevra une requête. La fonction appelée est associée à ce qui est reçu dans l'URL. L'URL d'appel de base est "/". Par exemple si j'appel sur mon navigateur l'URL "http://192.168.43.60/", mon serveur ESP recevra "/". On va donc pouvoir associer une fonction à "/". Vous trouverez plus d'informations sur ce fonctionnement dans mon article sur la programmation de l'ESP8266 et la réalisation d'un capteur de profondeur ICI.

  // Routage des requêtes HTTP
  oEspServer.on("/", vFonctionRoot);

  //Autre exemple oEspServer.on("/action",vFonctionAction);
   
  oEspServer.begin();
  Serial.println ( "HTTP server started" );

Lorsque le serveur est configuré (dans le setup), il faudra régulièrement appeler la fonction "handleClient()" qui permettra au programme d'aller voir s'il a reçu une requête. Si une requête est reçue, la fonction associée est exécutée et ensuite le programme reprend là où il a été interrompu.

En ce qui me concerne j'ai juste défini la fonction vFonctionRoot() pour qu'elle affiche une petite page html:


Relevé de température et d'humidité

On accède aux données du capteur par les méthode de l'objet dht :

  • readTemperature
  • readHumidity
Comme les capteurs DHT ne sont pas très précis, pour "lisser" la précision, j'ai décidé de prendre plusieurs mesures de suite et de faire la moyenne.
Entre chaque mesure il y a un temps d'attente.
Dans le programme j'ai fixé 5 mesures avant d'envoyer la moyenne à ThingSpeak. Et j'attends deux secondes entre chaque mesures. Ces données sont définies en début de programme, il est donc facile de les modifier.
Pour encore plus de précision, j'aurais pu faire comme dans mon programme de mesure de profondeur de cuve de récupération d'eau (ICI) et supprimer les valeurs extrêmes. En codant un algorithme intelligent, on peut pallier légérement à l’imprécision du capteur DHT11. Si vous avez investis dans un DHT22, vous aurez plus de précision par le matériel.



Code complet

/***********************************************************************
* Ce programme est destiné à ESP8266:
*     NodeMCU ESP12/ESP12E (ou ESP01/ESP01s possible)

* Permet de lire la température sur un capteur DHT11 et 
*   de l'envoyer dans un channel de la plateforme IoT ThingSpeak 
*   pour en visualiser le suivi. 
*    
* Evolutions possible :  

* Versions : 
* v1 : Création
* (c) acampeaux@gmail.com
*****************************************************************/
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>

#include <DHT.h>

///////////////////////////////////////////////////constantes relatives à la sonde DHT11 (ou DHT22)
#define  DHT_DATA D1

// Remplacez DHT11 par DHT22 ou DHT21 en fonction de votre modèle de capteur
#define DHTTYPE DHT11

DHT dht(DHT_DATA, DHTTYPE); 
// Delais d'inertie du capteur en ms=délais minimum entre deux prise de mesure.
// Pour le DHT11 il faut attendre 2s.
// Pour le DHT22 il faut attendre 0,5s (500ms)
#define DHT_INERTIE 2000

///////////////////////////////////////////////////constantes relatives aux autres broches de l'ESP
// Broche pour connecter une LED de controle qui s'alumera pour identifier l'envois de données
#define LED_CTRL  D8

///////////////////////////////////////////////////constantes pour le fonctionnement du programme
// Délais entre chaque série de mesures + envois à ThingSpeak (en secondes)
#define DELAIS 60
// Pour plus de précision, avant d'envoyer à ThingSpeak on va prendre plusieurs mesures et en faire la moyenne
#define NB_MESURE 5

////////////////////////////////////////////////////// Constantes et variable relatives au wifi 
// Temps d'attente en seconde pour se connecter au wifi
#define MAX_TIME_WAIT_WIFI 60

// Définition des adresses IP 
IPAddress oipIpEsp(192, 168, 43, 60);
IPAddress oipGateway(192, 168, 43, 1);
IPAddress oipSubnet(255, 255, 255, 0);
IPAddress oipDns(192, 168, 43, 1);

const char* sSsid = "votre ssid";
const char* sPassword = "votre mot de passe";
const char* sHostname ="esp12n1";

// Variables relatives au serveur web local qui sera hébergé sur cet ESP et permettra d'afficher une page.
#define ESP_SERVER_PORT 80
ESP8266WebServer oEspServer( ESP_SERVER_PORT );

////////////////////////////////////////////////////// Variables relatives à ThingSpeak
// On va appeler l'API sur le port 80 en http
char *sThinkSpeakUrl = "api.thingspeak.com";
int iThinkSpeakPort = 80;


// Indique l'identifiant du channel à récupérer sur le site dans l'onglet <API Keys>
char *szTSKeyChannel = "?????"; //mettre votre API thinhSpeak ici
int iTSFieldNumber = 1;
// Indique quel sont les numéros des champs pour la temperature et l'humidité
#define TEMPERATURE_FIELD 1
#define HUMIDITY_FIELD  2

// On instancie un client HTTP qui lancera la requete
HTTPClient oThinkSpeakClient;

/************************************************************************************************************
 * ***********************************************************************************************************
 * SETUP 
 * Fonction setup
 * ***********************************************************************************************************
 ************************************************************************************************************/
void setup() {
  byte tbMac[ 6 ] = {0,0,0,0,0,0};
  
  /////////////////////////////////////////////////////////Initialisation port série
  Serial.begin(9600);
  delay( 100 );
  Serial.println( "\nInitialisation liaison serie : OK" );

  ////////////////////////////////////////////////////////// Regarde si l'ESP dispose déjà d'une adresse IP locale 
  Serial.print( "Local IP avant connect = " );
  Serial.println( WiFi.localIP().toString() );

  ////////////////////////////////////////////////////////// disconnect au cas où! 
  WiFi.disconnect(1);
  //WiFi.mode(WIFI_STA);
  
  Serial.print( "Local IP apres disconnect = " );
  Serial.println( WiFi.localIP().toString() );

  ////////////////////////////////////////////////////////// Initialisation Wifi 
  WiFi.hostname( sHostname ); 
  WiFi.config(oipIpEsp, oipGateway, oipSubnet, oipDns );
  delay(100);
  
  ////////////////////////////////////////////////////////// Fixe les identifiants de connexion  
  WiFi.begin( sSsid, sPassword );
  delay( 1000 );

  ////////////////////////////////////////////////////////// Etablis la connexion
  // On attend le nb de secondes demandées et si la connexion n'est pas établie,
  //  on appel la fonction Reboot qui va reinitialiser l'ESP. 
  int iCompteur = 0;
  Serial.printf("Connection status: %d\n", WiFi.status());
  Serial.print( "Connecting WiFi ." );
  while (WiFi.status() != WL_CONNECTED ){
     delay( 1000 ); 
     Serial.print( "." );
     if ( iCompteur++ > MAX_TIME_WAIT_WIFI ) vFonctionReboot();
  }

 ////////////////////////////////////////////////////////// Affiche les données de connexion:
 // SSID
 // Adresse IP
 // Adresse MAC
  String stRes = "\nConnected to : " + String( sSsid );
  stRes += "\nAdresse IP : ";
  stRes += WiFi.localIP().toString() ; //Type IPAddress = tableau de 4 entiers.
  
  WiFi.macAddress( tbMac ); //récupère l'adresse MAC
  stRes += "\nAdresse MAC : ";
  for (int i = 0; i<=5; i++ ) {
    if ( i == 0 ) stRes += String( tbMac[ i ], HEX );
    else stRes += "." + String( tbMac[ i ], HEX );
  }
  
  Serial.println( stRes );


  ////////////////////////////////////////////////////////////// Initialisation des PIN
  // LED de controle 
  pinMode( LED_CTRL, OUTPUT );
  digitalWrite( D1, LOW) ; //On allumera la LED quand on enverra des données.
  
    
  /////////////////////////////////////////////////////////////// Initialisation sur serveur sur l'ESP
  // Lorsqu'il sera appelé (sur le réseau local et sur son adresse IP), on affichera une page HTML.
  
  // Routage des requêtes HTTP
  oEspServer.on("/", vFonctionRoot);
  
  //Autre exemple oEspServer.on("/action",vFonctionAction);
     
  oEspServer.begin();
  Serial.println ( "HTTP server started" );
  
  /////////////////////////////////////////////////////////////// Initialisation capteur de temperature
  dht.begin();

}

 /*****************************************************************************************
  * ***************************************************************************************
  * Fonction LOOP : 
  * Algorythme :
   *  Alumer la LED de controle
   *  Faire le nombre de lecture de sonde demandé et pour chaque lecture 
   *  Faire la moyenne
   *  Envoyer a ThingSpeak 
   *  Eteindre la LED de controle
   *  Attendre le temps demandé entre deux envois. 
   * **************************************************************************************
  ****************************************************************************************/
void loop() {

  // Regarde si le serveur a été appelé. Si oui, la fonction associée (dans le Setup) sera executée.
  oEspServer.handleClient();
     
  //Allume la LED indiquant qu'un cycle de mesure commence
  Serial.println( "\nOn debute un nouveau cycle de mesures ..................." );
  digitalWrite( LED_CTRL, HIGH );

  ///////////////////////////////////////////On va prendre les mesures 
  // Pour plus de fiabilité on va prendre un nombre de mesures et faire la moyenne
  float iTemp = 0.0;
  float iHum = 0.0;
  int i = 0;
  for ( i = 1; i <= NB_MESURE; i++){ 
    Serial.print( "Prise de la mesure numero " );
    Serial.println( i );
    // Lecture du taux d'humidité
    float h = dht.readHumidity();
  
    // Lecture de la température en Celcius
    float t = dht.readTemperature();

    // Stop le programme et renvoie un message d'erreur si le capteur ne renvoie aucune mesure
    if (isnan(h) || isnan(t) ) {
      Serial.println("Echec de lecture capteur temperature.");
      delay( DHT_INERTIE );
      return;
    }

  Serial.print("Humidite: "); 
  Serial.println(h);
  Serial.print("Temperature: "); 
  Serial.println(t);

  // Additionne les mesures
  iTemp += t;
  iHum += h;
  
  // Regarde si le serveur a été appelé. Si oui, la fonction associée (dans le Setup) sera executée.
  oEspServer.handleClient();
  
  // Attend un peu avant de prendre la mesure suivante
  delay( DHT_INERTIE );
  }

  iTemp = iTemp / NB_MESURE;
  Serial.print("Temperature moyenne: "); 
  Serial.println( iTemp );

  iHum = iHum / NB_MESURE;
  Serial.print("Humidite moyenne: "); 
  Serial.println( iHum );
  
  //////////////////// Appel ThingSpeak pour envoyer la température
  int iResCallThingSpeak = iEnvoiThingSpeak( iTemp, TEMPERATURE_FIELD, iHum, HUMIDITY_FIELD );
  switch ( iResCallThingSpeak ){
    case 0 :
      // L'appel de la fonction c'est bien passé
      Serial.println( "iEnvoiThingSpeak OK" );
      break;
     default :
      // On a un code <> 0 donc il y a une erreur.
      // Les codes erreurs sont 1,2.
      Serial.println( "iEnvoiThingSpeak NOK" );
      break;
  }
    
  //Attente entre deux cycles en ecoutant si une requete arrive sur le serveur.
  digitalWrite( LED_CTRL, LOW );
  for ( int i = 1; i<= DELAIS; i++ ) {
    oEspServer.handleClient();
    delay( 1000 );
  }
}


 /*****************************************************************************************
  * ***************************************************************************************
 * Fonction pour envoyer une valeur à un champs dans un canal ThingSpeak
 * fValue = la valeur 
 * iField = le numéro de champ associé
   * **************************************************************************************
  ****************************************************************************************/
 int iEnvoiThingSpeak(float fValue1, int iField1, float fValue2, int iField2 ){
  int iRes = 0;
  String osUrl = "";
  
  //////////////////// Calcul l'URL d'appel à ThingSpeak
  osUrl = "/update?api_key=";
  osUrl += szTSKeyChannel;
  osUrl += "&field" + String( iField1 );
  osUrl += "=" + String( fValue1 );
  osUrl += "&field" + String( iField2 );
  osUrl += "=" + String( fValue2 );

  Serial.print( "Url d'appel ThingSpeak = " ); 
  Serial.println( osUrl );

  //////////////////// Appel ThingSpeak pour mettre a jour le capteur
  oThinkSpeakClient.begin( sThinkSpeakUrl, iThinkSpeakPort, osUrl );
  int iHttpCode = oThinkSpeakClient.GET();
  if ( iHttpCode ){
    if ( iHttpCode == 200 ){
      String osPayload = oThinkSpeakClient.getString();
      Serial.println( "oThinkSpeakClient response" );
      Serial.println( osPayload );
    } else {
      String osPayload = oThinkSpeakClient.getString();
      Serial.println( "oThinkSpeakClient response error " );
      Serial.println( osPayload );
      Serial.print( "Adresse IP ESP : " );
      Serial.println( WiFi.localIP().toString() );
      Serial.print( "iHttpCode : " );
      Serial.println( iHttpCode );
      iRes = 1;
    }
  } else {
    Serial.println( "oThinkSpeakClient not response" );
    iRes = 2;
   }
  oThinkSpeakClient.end();

  // Attente car délais imposé entre deux mises à jour ThingSpeak
  return iRes;
 } 

/*****************************************************************************************
  * ***************************************************************************************
 * vFonctionRoot
 * Fonction qui renvois la page / du serveur
 * Affiche comment utiliser le serveur associé au module
 *    * *************************************************************************************
  ****************************************************************************************/
 void vFonctionRoot(){

  Serial.println( "Entre dans fonction vFonctionRoot" );

  //construit le code html a retourner
  String osMessage = "<html><body>";

  osMessage += "<br />";
  osMessage += "<u><b>Bienvenue sur la page d'aide:</b></u><br />";
  osMessage += "Hostname: " + String(sHostname) +"<br />";
  osMessage += "ThingSpeak API URL: " + String(sThinkSpeakUrl) +"<br />";
  osMessage += "ThingSpeak API Port: " + String(iThinkSpeakPort) +"<br />";
  osMessage += "ThingSpeak Channel ID: " + String(szTSKeyChannel) +"<br />";
  osMessage += "</body></html>";

  oEspServer.send(200, "text/html", osMessage );  
 }

/*****************************************************************************************
  * ***************************************************************************************
 * vFonctionReboot
 * Fonction lance le reboot de l'ESP en placant D0 à LOW
 * *************************************************************************************
  ****************************************************************************************/
 void vFonctionReboot(){
    pinMode( D0, OUTPUT );
    digitalWrite( D0, LOW ); //D0 connecté sur RST (obligatoire pour utilisation deepsleep)
 }


La conclusion du pote agé


Et voici en image les courbes que j'obtiens sur ThingSpeak :




Voila, j'espère que ces petites graines de connaissances que nous avons semé tout au long de cet article vont germer et nous donnerons de beaux fruits qui seront la nourriture intellectuelle que nous partagerons cet hivers. 

En ce qui me concerne, la rédaction de cet article m'a donné l'envie de créer plusieurs capteurs de température/humidité les moins chers possible, à base de DHT11 et en remplaçant le NodeMCU par un ESP01s. J'aimerais essayer de faire tourner tout ça en autonomie avec un accu 18650. 

J'ai aussi l'envie de me développer un petit site web,chez un hébergeur gratuit, pour y intégrer les données et les courbes proposées par ThingSpeak. En essayant d'exploiter d'autres données que la température. Et en poussant un peu plus loin dans la découverte des nouveaux services "cloud" associés à l'IoT et la domotique, j'aimerais expérimenter l'interconnexion de tout cet écosystème avec la plateforme IFTTT. 

Comme vous pouvez le voir, mes projets sont nombreux et ce sera toujours avec plaisir que je les partagerais avec vous en essayant de vous faire profiter au maximum de mes capacités, de toutes les connaissances et les découvertes que je récolte. 

Sites de référence 

Je vous laisse quelque liens vers des sites que j'ai trouvé utiles et qui m'ont aidé à écrire cet article.

Sur les capteurs DHT: 




Un autre méthode d'accès à la plateforme ThingSpeak avec une librairie dédié:


Pour faire vos achats

J'en profite pour envoyer un grand merci à tous ceux qui ont joué le jeu en faisant quelques achats sur Amazon ou eBay à partir de mes liens. Je n'ai aucun moyen d'avoir des informations qui me permettent de remercier individuellement. Mais sachez que depuis 14 mois (à la date du 30/09/2018) que je rédige des articles, j'ai récolté presque 32€. Soit une moyenne de 2,30€ par mois. Mais cette moyenne à tendance à progresser.

Merci également aux personnes qui ont cliqué sur un bandeau de publicité du site. Il est trop tôt pour que je puisse vous faire un retours sur les gains "espérés". Je le ferai dès que j'aurai de la visibilité. Ce que je peux dire c'est que le taux de clic est d'environ 2 clics pour 1000 pages affichées.

Si vous souhaitez vous procurer quelques-uns des composants que j'ai utilisé pour cet article je vous remet les liens:

   





Soutenez la blogoculture ...


Le plus simplement du monde, si vous avez un achat à faire sur Amazon, accédez au site à partir de ce lien (que vous pouvez ajouter dans vos favoris)https://amzn.to/2nbe4sm





Soutenez la blogoculture ...


Le plus simplement du monde, si vous avez un achat à faire sur Amazon, accédez au site à partir de ce lien (que vous pouvez ajouter dans vos favoris)https://amzn.to/2nbe4sm


... mais aussi ...


Vous appréciez les articles frais et vitaminés de ce blog et vous voulez faire un geste pour encourager ce partage, saluer le travail, ou parce que vous y avez trouvé des choses utiles ( et que vous êtes sympa ) ?

... c'est possible et vous avez le choix !
Si vous avez un compte Paypal et quelques euros à offrir sans vous mettre sur la paille, subventionnez la culture domotique à l'ancienne !
Vous ne dépenserez pas un radis de plus en faisant un achat sur eBay à partir de ce lien.
Economisez du blé avec Amazon Prime ! Offre d'essais 1 mois gratuit (et renouvelable).
Soyez chou et aidez les petits producteurs de blog à se faire connaitre auprès de vos amis facebook !

Merci


Commentaires

  1. Venant du monde du développement software, je découvre lentement mais sûrement le monde de l'électronique et de l'IoT en particulier. Je viens de lire tes 2 deux articles sur l'ESP8266 qui semble être le micro controlleur du moment. J'ai donc fait ma petite commande (en suivant tes liens Amazon bien évidemment :-) J'attends la livraison de mon premier kit.
    Premier challenge pour moi, développer des mini capteurs de température & lumière pour placer dans la chambre de mes enfants.

    Avec un objectif plus particulier également : la facilité du setup du device (vu qu'il devrait en y avoir plusieurs).

    Cad pouvoir gérer au mieux la première configuration au wifi local, et une fois le wifi local configuré, que le mini device puisse se "registrer" en vue de l'associer avec un identifiant (ou un nom de chambre).

    Bravo en tous cas pour tes articles ! Ca m'aidera très très certainement dans ce premier projet.

    Pierre

    RépondreSupprimer
  2. Bonjour Pierre,
    Merci pour ton commentaire et aussi merci pour ta commande en suivant mes liens. Je n'ai pas d'information là dessus donc cela me fait plaisir de pouvoir remercier quelqu'un.
    Concernant ton projet, j'aime bien l'idée du capteur de température et de luminosité associé.
    Tu sais comment tu vas collecter ces données ? As tu prévu un serveur domotique ?
    Sinon pour la connexion au wifi, bien que dans mes articles j'aime bien faire les choses à la main, il existe des librairies qui permettent de faciliter l'appairage des ESP et même de ne pas avoir à rentrer en dur le code d'accès au wifi dans le programme.
    En tout cas si je peux t'aider n'hésites pas.

    Alexandre

    RépondreSupprimer
    Réponses
    1. bsr svp j´ai esp8266 E01 relié à ma microbit
      bon je veux lire de thingspeak en utilisant makecode j´ai pas trouvé le bloc download dans l´extension esp8266 thingspeak ,j´ai trouvé seulement le bloc upload
      help please
      merci d´avance

      Supprimer
  3. Bonjour Mr, c'est un bon tutorial je connect sur Wi-Fi mais je n'arrive pas à envoyer mes données vers ThingSpeak.
    le monitor serial m'affiche toujours "othinkspeakclient response error " pourriez-vous m'aider svp pour résoudre ce problème :(

    RépondreSupprimer
    Réponses
    1. Bonjour, Avez vous essayé d'envoyer le requête manuellement via un navigateur ?
      Si cela fonctionne, c'est qu'il y a un paramètre qui n'est pas correct. Soit dans la connexion de l'ESP à internet, soit dans les paramètres ThingSpeak.
      Vous n'avez pas d'autres informations après "othinkspeakclient response error " ?
      Vous arrivez bien à vous connecter à l'ESP (affichage du texte par la fonction vFonctionRoot() en appelant le serveur ESP par son adresse IP sur votre navigateur) ?
      Dans tous les cas il faut vérifier un par un que toutes les étapes fonctionnent correctement.
      Bon courage.

      Supprimer
    2. Allo,
      je suis surpris que ta DEL verte s'allume ...

      selon ton tableau 1,8 à 2v
      lorsque la pin D8 est à HIGH il y a présence de 3.3v à sa borne

      pour 2v de seuil de la DEL
      3.3v - 2v = 1.1v et donc 1.1v / 10ma (0.010 A) = 110 ohms

      pour 1.8v de seuil
      3.3v - 1.8v = 1.5v et donc 1.5v / 10ma (0.010) = 150 ohms

      Puissance consommé --> P = UI et pour que la charge soit bonne il faut tenir compte de la puissance consommé par la diode ainsi que la puissance consommé par la DEL

      si p=ui alors 3.3v * 10ma(.01) = 0.033w et 33 milliwatts

      pour la résistance la puissance sera
      Rp=Ru * Ri et donc 2.1v le pire cas puisque le souhaite 10ma et qu'il est possible que le seuil de la DEL soit à 1.8v

      donc 3.3v - 1.8v = 1.5 v au borne de la résistance et donc Ru = 1.5v et Ri = 10ma

      ce qui donne 15 milliwatts et une résistance d'un 1/4w fait le travail et cela veut aussi dire que la DEL consomme la balance soit 33mw – 15mw = 18mw

      ¼ de watts = 250mw

      En passant j’aime beaucoup vos articles ….

      Supprimer
    3. Bonjour Eddy,

      C'est vraiment un grand plaisir pour moi de voir que certaines personnes comme vous lisent avec autant d'attention mes articles. C'est pour cela que j'essaie de toujours les rédiger de la manière la plus détaillée et pédagogue possible. Mais ce n'est pas toujours facile de s'adapter aux besoins de chacun.
      En ce qui concerne votre question / remarque, je vous confirme que la LED verte s'allume bien. J'avoue que je ne suis pas suffisamment calé pour comprendre tous vos calculs mais voici mon raisonnement.
      - La LED s'allume pour une tension qui dépasse 1,8V. Elle provoque donc une chutte de tension de 1,8V environ dans le circuit.
      - Si le circuit est à 3,3V, la tension aux bornes de la résistance est du 3,3 - 1,8 = 1,5V
      - Si la résistance est à 1000 Ohms, j'aurais un courant dans mon circuit de I = U / R donc I = 1,5 / 1000. Soit 1,5 mA.
      Et si la LED s'allume c'est que ce courant est suffisant pour la faire briller.
      Après, n'étant pas électronicien, je travaille plus en faisant des expérimentations. Je peux me tromper dans mes calculs. Mais ce que je confirme avec certitude c'est que la LED est bien allumée.
      Au plaisir de vous lire à nouveau.

      Supprimer
  4. Allo

    as tu regardé du coté de Thingsboard ?

    RépondreSupprimer
    Réponses
    1. Re-bonjour,
      Non je ne connais pas ce service. Je viens de regarder suite à ta remarque et cela me semble intéressant. Peux tu m'en dire un peu plus ?
      Pour le moment je finalise mon dernier article qui décrit l'utilisation d'un capteur 1-wire directement sur le Raspberry PI et quand ce sera fait je regarderais plus attentivement Thingsboard .
      Merci pour l'info.

      Supprimer
  5. Bonjour,
    j'ai un message d'erreur à la compilation :
    "280:26: error: call to 'HTTPClient::begin' declared with attribute error: obsolete API "...
    auriez-vous une solution svp ?

    RépondreSupprimer
    Réponses
    1. même problème, je cherche une solution

      Supprimer
  6. Bonjour, merci bcp pour la qualité de la rédaction de ce blog. pour ma part j'ai une petite question, je suis en train de réaliser un enregistreur de température avec ESP32 et 2 sondes DS18B120 pour mesurer les température d'eau départ et retour de mon plancher chauffant. Mon code fonctionne sur ThingSpeak à qui j'envoie toutes les 15s les datas mais je ne peux les lire que sur un intervalle de 15mn, moi je souhaiterai les lire sur 24H, 1 semaine, 1 mois par exemple. Savez-vous pourquoi est-ce parametrable ?

    RépondreSupprimer

Enregistrer un commentaire