Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

IoT Made Easy avec UNO, ESP-01, ThingSpeak et MIT App Inventor

Composants et fournitures

Arduino UNO
× 1
Espressif ESP8266 ESP-01
× 1
Capteur de température DHT22
× 1
Capteur de température numérique à 1 fil DS18B20 pour utilisation sur le sol
× 1
LDR - Light Dependent Resistor
× 1
Module relais 2 canaux DC 5V
× 1

Applications et services en ligne

Arduino IDE
API ThingSpeak
MIT App Inventor

À propos de ce projet

Notre objectif sera essentiellement de collecter des informations auprès d'une unité locale et de les envoyer sur Internet. Un utilisateur n'importe où sur la planète regardant ces informations prendra des décisions en envoyant des commandes à distance aux actionneurs, qui seront également dans cette unité locale. N'importe quel capteur ou actionneur peut être utilisé.

La grande majorité de mon travail sur l'arène IoT utilisait NodeMCU et plus récemment, l'ESP32. Mais, je pense qu'il est important de ne pas oublier mes premiers pas, il y a quelques années, où j'ai commencé à apprendre l'IoT en utilisant un Arduino UNO et l'ancien et bon ESP8266-01.

Je décide donc ici de revenir à cette époque (avec un peu plus d'expérience maintenant) et d'explorer à nouveau ces excellents appareils, en les connectant au cloud, à l'aide du service Web ThingSpeak.com. Nous explorerons également pour contrôler les choses à distance, en utilisant une application Android développée à l'aide du MIT AppInventor.

Le "Centre de notre projet IoT" sera le ThingSpeak.com. L'unité locale (UNO/ESP-01) capturera les données des capteurs et de l'état de l'actionneur, envoyer sur Internet, en "écrivant" sur un ThingSpeak.com spécifique Canal d'état . L'unité locale recevra également données d'Internet, en les « lisant » à partir de canaux d'actionneurs ThingSpeak spécifiques .

Une application Android sera également en lecture ces données du ThingSpeak.com Status Channel et les afficher pour l'utilisateur. De la même manière, l'utilisateur, sur la base de ces informations d'état, peut envoyer des commandes aux actionneurs, écrivant les sur les canaux de l'actionneur ThingSpeak (voir le schéma fonctionnel ci-dessus pour mieux comprendre le flux de données).

Alors qu'allons-nous faire? Le schéma fonctionnel présenté à l'étape suivante nous donnera un aperçu du projet final :

Étape 1 :Présentation

À l'aide de capteurs communs, notre projet capturera plusieurs données, les envoyant vers le cloud, où tout le monde pourra les voir via Internet. Pour exploiter ces données, nous utiliserons le service fourni par ThingSpeak.com, une plate-forme IoT ouverte qui nous permettra de collecter, d'analyser et d'agir sur ces données.

Les données à collecter par les capteurs sera :

  • Température de l'air et humidité relative
  • Température et humidité du sol
  • Luminosité

Le projet aura 2 actionneurs :

  • Pompe électrique
  • Lampe électrique

L'état de ces actionneurs ("ON/OFF") doit également être envoyé au cloud.

Ainsi, l'idée sera de capturer ces données à partir des capteurs, par exemple, une plantation et de les envoyer dans le cloud. Sur la base de ces données, un utilisateur doit prendre une décision sur la base de ces déclarations :

  • Allumez la pompe si l'humidité du sol est trop faible
  • Allumez la lampe si la température du sol est trop basse

Pour commander à distance nos actionneurs, nous utiliserons une application Android.

Étape 2 :BoM - Nomenclature

Certains des composants les plus importants répertoriés ici ont un lien et un prix indicatif en USD associés. Ces liens sont à titre informatif seulement.

  • Arduino UNO (Microcontrôleur) - 10,00 $
  • ESP8266-01 (module de communication) - 3,50 $
  • DHT22 (capteur d'air et d'humidité relative) - 9,00 $
  • DS18B20 (capteur de température numérique à 1 fil pour utilisation sur le sol) - 6,00 $
  • YL-69 + LM393 (capteur d'humidité du sol) - 2,00 $
  • LDR (Capteur de luminosité) - 0,20 $
  • 2 LED (rouge et verte)
  • 1 module de relais CC 5 V à 2 canaux avec déclencheur de bas niveau optocoupleur - 7,00 $
  • Pompe 5 V CC - 3,00 $
  • Lampe 220V
  • Résistance 2 x 330 ohms (à utiliser avec les LED)
  • Résistance 2 x 10K ohm (à utiliser avec DHT22 et LDR)
  • 1 résistance 4K7 ohm (à utiliser avec DS18B20
  • Protoboard
  • Cavaliers
  • Alimentation externe 5 V CC pour les relais

Étape 3 :Le matériel

Assemblons le Project HW. L'idéal est d'installer et de tester notre projet par pièces. À titre de suggestion, nous pouvons suivre les étapes :

  • Installer et tester localement tous les capteurs
  • Installer et configurer l'ESP-01 (BareMinimum)
  • Modifier l'installation de l'ESP-01 pour sa configuration finale et la tester
  • Configurer le canal d'état ThingsPeak
  • Installez le code ThingsPeak dans votre Arduino et vérifiez l'état des capteurs sur le Cloud
  • Développer la première version de l'application Android pour afficher le statut et les messages
  • Installer les actionneurs (LED et relais)
  • Configurer les canaux des actionneurs ThingSpeak
  • Installer et tester le code Arduino avec des actionneurs
  • Développer la version finale de l'application Android

Étape 4 :Connexion des capteurs

Nous devons avoir des bibliothèques installées sur notre IDE pour lire correctement les capteurs. Vérifiez si toutes les bibliothèques sont installées. Leur configuration initiale doit être :

// DS18B20#include #include #define ONE_WIRE_BUS 5 // DS18B20 sur la broche D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int soilTemp =0; //DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Humidité du sol#define soilHumPIN 0int soilHum =0; 

Dans la configuration et la boucle, écrivons :

void setup(){ Serial.begin(9600); DS18B20.begin(); dht.begin();}boucle vide(){ readSensors(); afficherSensors(); retard (10000);} 

Et enfin, écrivons deux fonctions spécifiques, une pour lire nos capteurs et une autre pour afficher leurs valeurs sur Serial Monitor :

/********* Valeur des capteurs de lecture *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); solTemp =DS18B20.getTempCByIndex(0) ; // Le capteur 0 capturera la température du sol en degrés Celsius solHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% }/********* Valeur des capteurs d'affichage *************/void displaySensors(void){ Serial.print (" AirTemp (oC):"); Serial.println (airTemp); Serial.print ("airHum (%):"); Serial.println (airHum); Serial.print ("soilTemp (oC):"); Serial.println (solTemp); Serial.print ("soilHum (%):"); Serial.println (solHum); Serial.print ("light (%):"); Serial.println (léger); Serial.println ("");} 

L'image du moniteur série ci-dessous nous montre les valeurs du capteur.

Le code est téléchargeable sur mon GITHUB :Sens ors_Test.ino

Étape 5 :​ESP8266-01 Configuration initiale

L'ESP-01 sera utilisé comme Serial Bridge, ce qui signifie que nous le programmerons à l'aide de " commandes AT ". La première chose est de s'assurer que votre ESP-01 est sur la bonne vitesse de communication Baud Rate. Dans notre cas, 9 600 bauds. Habituellement, l'ESP-01 est programmé en usine avec 115 200 bauds et nous devons le changer à 9 600 bauds.

Tout d'abord, vous devez connecter l'ESP-01 comme indiqué ci-dessus.

Ensuite, connectez l'Arduino à votre ordinateur, ouvrez l'IDE et chargez l'exemple qui se trouve dans Fichier> Exemples> 01.Basics> BareMinimum. Ceci est un code vide, pour s'assurer qu'il n'y aura pas de conflit de communication entre Arduino et ESP.

Nous avons transféré ce code à l'Arduino avant de le connecter à l'ESP-01S pour nous assurer que l'Arduino n'utilisera pas de communication série (TX et RX). Ceci est important pour que l'ESP puisse communiquer correctement.

Ouvrez votre moniteur série IDE et modifiez la vitesse à 115 200 bauds. Commencez à envoyer une commande "AT" sur votre moniteur série IDE. L'ESP-01 devrait retourner "OK"

Ensuite, modifions la vitesse. Pour cela, vous pouvez utiliser la commande :

AT + CIOBAUD =9600 

Notez que l'ESP-01 peut revenir à la programmation d'usine (je ne sais pas si cela est dû à la version FW). Au moins dans mon cas, j'ai dû utiliser une commande différente pour changer définitivement BaudRate :

AT+ UART_DEF=,,,, 

Par exemple :9600 bauds / 8 bits de données / 1 bits d'arrêt et aucun contrôle de parité et de flux :

AT + UART_DEF =9600,8,1,0,0 

Dans la zone de sélection en bas de votre moniteur série, changez la vitesse en " 9600 bauds ". Testez la communication :en haut de la fenêtre tapez AT et voyez la réponse OK. Vous devez maintenant configurer le module en Mode Station agir en tant que Client de votre réseau Wi-Fi. Utilisez la commande :

 AT + CWMODE =1 

Nous devons maintenant connecter le module à votre réseau Wi-Fi.

Pour ce faire, utilisez les commandes ci-dessous, en remplaçant "network_name" par le nom de votre réseau Wi-Fi et "network_name" par votre mot de passe. Gardez les guillemets.

AT + CWJAP ="network_name", "network_name"  

Si vous voyez la réponse ci-dessous, votre connexion a été établie correctement :

WIFI CONNECTÉ WIFI GOT IP 

Pour trouver l'IP, exécutez la commande :

AT + CIFSR  

Et notez l'adresse IP qui apparaîtra dans votre moniteur série. Vous pourriez en avoir besoin à l'avenir.

Étape 6 :Tester l'ESP-01

Une fois que nous avons configuré l'ESP-01, nous devons l'installer sur son circuit final. Pour cela il faut CHANGER le cablage fait avant et brancher l'ESP-01 à notre UNO comme ci-dessous :

  • ESP-01 RX (jaune) vers UNO Pin D7
  • ESP-01 TX (Orange) vers UNO Pin D6
  • ESP-01 Ch-Pd (marron) à Vcc (3,3 V)
  • Réinitialisation ESP-01 (Bleu) à UNO Pin D8
  • ESP-01 Vcc (Rouge) à 3.3V
  • ESP-01 Gnd (noir) vers UNO GND

Faisons un test simple pour vérifier si notre ESP-01 est corrigé installé et testé. Entrez le code ci-dessous :

#include  SoftwareSerial esp8266(6,7); //Rx ==> Broche 6; TX ==> Pin7 #define speed8266 9600 void setup() { esp8266.begin (speed8266); Serial.begin(speed8266); Serial.println("ESP8266 Setup test - use AT coomands");}void loop() { while(esp8266.available()) { Serial.write(esp8266.read()); } while(Serial.available()) { esp8266.write(Serial.read()); }} 

Maintenant, essayez quelques commandes AT et voyez le résultat sur votre moniteur série :

* AT =====> ESP8266 renvoie OK* AT+RST =====> ESP8266 redémarre et renvoie OK* AT+GMR =====> ESP8266 renvoie AT Version ; Version SDK ; identifiant; OK* AT+CWMODE ? => L'ESP8266 renvoie le type de mode* AT+CWLAP ===> L'ESP8266 renvoie les points d'accès proches* AT+CIFSR ===> L'ESP8266 renvoie l'IP conçue 

Le code peut être téléchargé depuis mon GITHUB :ESP_AT_Config.ino

Si vous souhaitez vous connecter au réseau WiFi à chaque fois qu'une réinitialisation se produit (ou que votre Arduino est éteint / allumé) et en entrant vos informations d'identification, ajoutez un appel au connectWiFi () fonction à la fin de la fonction setup () :

setup(){ ... connectWiFi(); } 

Le connectWiFi() fonction devrait être à la fin de votre code principal .ino :

void connectWiFi(void){ sendData("AT+RST\r\n", 2000, 0); // réinitialiser sendData("AT+CWJAP=\"VOTRE NOM D'UTILISATEUR\",\"VOTRE MOT DE PASSE\"\r\n", 2000, 0); //Connecter le délai réseau (3000); sendData("AT+CWMODE=1\r\n", 1000, 0); sendData("AT+CIFSR\r\n", 1000, 0); // Afficher l'adresse IP Serial.println("8266 Connected");} 

Notez que la fonction ci-dessus appelle un autre sendData (données) fonction, qui devrait également se trouver dans votre code :

String sendData(String command, const int timeout, boolean debug){ String response ="" ; EspSerial.print(commande); long int temps =millis(); while ( (temps + délai d'attente)> millis()) { while (EspSerial.available()) { // L'esp a des données donc affiche sa sortie dans la fenêtre série char c =EspSerial.read(); // lit le caractère suivant. réponse +=c; } } if (debug) { Serial.print(response); } renvoyer la réponse ;}  

Étape 7 :Connecter les capteurs et l'ESP-01

Une fois que nous avons installé et testé tous les capteurs et que notre ESP-01 fonctionne correctement, voyons tous ensemble et préparez-vous à envoyer des données sur Internet.

Étape 8 :Le ThingSpeak

L'une des parties les plus importantes de notre projet est ThingSpeak, une plate-forme IoT ouverte qui nous permettra de collecter, d'analyser et d'agir sur les données collectées. Si vous ne l'avez pas encore fait, veuillez vous rendre sur ThingSpeak pour vous inscrire et créer votre compte.

Ensuite, créez un nouveau canal où nous aurons nos 2 actionneurs, 5 capteurs et un statut de champ de rechange :

  • Champ 1 :Actionneur 1
  • Champ 2 : actionneur 2
  • Champ 3 : Température de l'air en °C
  • Dépôt 4 :humidité relative de l'air en %
  • Champ 5 : Température du sol en °C
  • Champ 6 :Humidité du sol en %
  • Champ 7 :Luminosité en %
  • Champ 8 :Pièce de rechange

Le champ 8 sera laissé en réserve pour être utilisé pour une extension future ou à des fins de débogage. Par exemple, je l'utiliserai comme "compteur" pour chaque erreur de communication qui se produit lors de la négociation Arduino/ESP-01 avec ThingSpeak.com.

Une fois que vous avez créé votre chaîne (dans ce cas, ce sera notre chaîne de statut), il sera important de prendre note de vos clés, comme indiqué ci-dessous.

Étape 9 :Envoi du statut au cloud

À ce stade, nous avons notre service Cloud disponible et nos capteurs capturant les données localement. Prenons ces valeurs et envoyons-les à ThingSpeak.com. Nous allons écrire sur le canal ThingSpeak et pour cela, nous devrons envoyer une chaîne GET. Nous ferons en 3 parties :

Nous enverrons un "Start cmd":

AT+CIPSTART="TCP","184.106.153.149",80 

Suite à la "longueur" de la commande :

AT+CIPSEND=116 

Et la chaîne GET elle-même, qui écrira sur les champs appropriés sur le Status Channel :

GET /update?api_key=YOUR_WRITE_KEY_HERE&field1=pump&fieldlamp=0&field3=airTemp&field4=airHum&field5=soilTemp&field6=soilHum&field7=light&field8=spare

Le code ci-dessous fera le travail pour nous et l'écran d'impression ci-dessus montre le résultat sur Serial Monitor :

// Thingspeak String statusChWriteKey ="6SRPQQKIE6AJVQE6"; // ID du canal d'état :385184#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// DS18B20#include #include #define ONE_WIRE_BUS 5 // DS18B20 sur la broche D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int); =0;//DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Humidité du sol#define soilHumPIN 0int soilHum =0;// Variables à utiliser avec timerslong writeTimingSeconds =17; // ==> Définir le temps d'échantillonnage en secondes pour envoyer les données long startWriteTiming =0;long elapsedWriteTime =0;// Variables à utiliser avec Actuatorsboolean pump =0; lampe booléenne =0 ; int spare =0;erreur booléenne;void setup(){ Serial.begin(9600); pinMode (HARDWARE_RESET, SORTIE); digitalWrite(HARDWARE_RESET, HAUT); DS18B20.begin(); dht.begin(); EspSerial.begin(9600); // Communication avec Modulo WiFi EspHardwareReset(); //Réinitialiser le module WiFi startWriteTiming =millis(); // démarrage de l'"horloge du programme"}boucle void(){ start ://label error=0; elapsedWriteTime =millis()-startWriteTiming ; if (elapsedWriteTime> (writeTimingSeconds*1000)) { readSensors(); écrireThingSpeak(); startWriteTiming =millis(); } if (error==1) //Renvoi si la transmission n'est pas terminée { Serial.println(" <<<>>>"); retard (2000); aller au début ; //aller à l'étiquette "start" }}/********* Lire la valeur des capteurs *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); solTemp =DS18B20.getTempCByIndex(0) ; // Le capteur 0 capturera la température du sol en Celcius light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% SoilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); }/********* Conexao avec TCP avec Thingspeak *******/void writeThingSpeak(void){ startThingSpeakCmd(); // préparation d'une chaîne GET String getStr ="GET /update?api_key="; getStr +=statusChWriteKey; getStr +="&field1="; getStr +=String(pompe); getStr +="&field2="; getStr +=String(lampe); getStr +="&field3="; getStr +=String(airTemp); getStr +="&field4="; getStr +=String(airHum); getStr +="&field5="; getStr +=String(solTemp); getStr +="&field6="; getStr +=String(solHum); getStr +="&field7="; getStr +=String(lumière); getStr +="&field8="; getStr +=String(spare); getStr +="\r\n\r\n" ; sendThingSpeakGetCmd(getStr); }/********* Réinitialiser ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); retard (500); digitalWrite(HARDWARE_RESET, HAUT); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********** Démarre la communication avec ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error"); retourner; }}/********* envoie une commande GET à ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> longueur cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //le contenu réel commence après une ligne vide (qui a une longueur de 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody a reçu :"); Serial.println(messageBody); renvoyer le messageCorps ; } else { EspSerial.println("AT+CIPCLOSE"); // alerter l'utilisateur Serial.println("ESP8266 CIPSEND ERROR:RENENDING"); //Renvoyer... spare =spare + 1; erreur=1; renvoie "erreur" ; } }  

Le code peut être téléchargé depuis mon GITHUB :SendingStatusTS_EXT.ino

Étape 10 : Première partie de l'application Android – Contrôle de l'état

Créons notre 1ère partie de l'application Android.

Tout d'abord, nous concevons l'interface utilisateur. L'écran d'impression ci-dessus montre les principaux éléments visibles et non visibles. Après cela, nous devons concevoir les blocs (les numéros ci-dessous correspondent aux chiffres ci-dessus) :

Toutes les 2 secondes (définies par Clock1), nous appellerons une procédure nommée :"readArduino".

  • Le retour d'une telle procédure sera la valeur de chacune des variables d'état qui devrait être affichée à l'écran.
  • Notez que nous allons "convertir" les valeurs "0" et "1" de l'état des actionneurs pour "OFF" et "ON" pour une meilleure compréhension.
  • Ces valeurs ("Status") seront affichées sur les "étiquettes" correspondantes
  • Les variables d'état doivent être déclarées comme Global.
  • La procédure "readArduino" va, en fait, lire le Status Channel à ThingSpeak. Il faut donc définir l'URL à envoyer à Thingspeak. Pour cela, 3 variables globales doivent être déclarées et jointes pour créer l'URL à envoyer à TS. Un GET doit être envoyé au composant Web nommé "ArduFarmBotStatusCh"
  • Le texte obtenu de la commande précédente arrivera au format JSon. Ce texte doit être traité en ayant chaque champ à lire et à stocker sur la variable globale correspondante.
  • La dernière chose à faire est d'appeler la procédure "Alarme", qui analysera l'état de deux capteurs de sol. Si la température est trop basse (dans notre cas 10oC), un message doit s'afficher. Idem pour l'humidité, si elle est inférieure à 60%. Notez que nous avons défini une autre minuterie (Clock2), programmée pour être déclenchée toutes les 1 seconde. C'est uniquement pour "basculer" la couleur du texte du message (du blanc au rouge). Cela fera « cligner » le message.

La dernière photo ci-dessus montre le fonctionnement final de l'application.

Le code de l'application peut être téléchargé depuis mon GITHUB :ArduFarmBot_Status_App_EXT.aia

Étape 11 :Installation des actionneurs (LED et relais)

Complétons notre HW.

Pour cela, nous devons installer nos Actionneurs. Comme vous vous en souvenez, nous recevrons à distance des commandes pour allumer et éteindre une pompe et une lampe. La sortie Arduino activera un relais (et une LED) pour obtenir ces actions.

Nous utiliserons un module de relais doté d'un déclencheur de bas niveau optocoupleur. De plus, nous lui fournirons 5 V via une broche séparée, nous n'avons donc pas à fournir le courant requis sur la broche d'entrée. Le module le fait pour nous.

La figure ci-dessus montre comment les actionneurs doivent être connectés. Notez que le Realy GND n'est PAS CONNECTÉ à Arduino GND. Cela aidera à ne pas introduire de bruit lorsque le relais fonctionne.

Pour simplifier, j'ai sorti du schéma, les capteurs. Mais vous pouvez ajouter les circuits des actionneurs à votre projet sans retirer les capteurs que vous avez déjà installés et testés.

Étape 12 :Configuration des canaux des actionneurs ThingSpeak

De la même manière que nous l'avons fait pour le Status, nous allons créer 2 nouveaux canaux, un pour chaque actionneur. Sur chacun d'eux, notez les touches Channel ID, Read et Write. Nous écrirons uniquement sur le champ 1 de chacun de ces canaux. Donc, dans mon cas par exemple :

ID de canal 375598 ==> LED rouge (pompe)

  • Champ1 =0 ==> Pompe OFF
  • Champ1 =1 ==> Pompe ON

ID de canal 375599 ==> LED verte (lampe)

  • Champ1 =0 ==> Lampe éteinte
  • Champ1 =1 ==> Lampe allumée

Étape 13 :Installer et tester le code Arduino avec des actionneurs

Lorsque nous envoyions des données sur le Web, nous écrivions sur un canal ThingSpeak (état du canal) pour « transmettre » (télécharger) des données. Maintenant, nous devrions LIRE à partir d'un canal ThingSpeak (canal d'actionneur) pour "recevoir" (télécharger) des données.

Nous allons LIRE à partir d'un canal ThingSpeak et pour cela, nous devrons envoyer une chaîne GET. Nous ferons en 3 parties :

Nous enverrons un "Start cmd":

AT+CIPSTART="TCP","184.106.153.149",80 

Suite à la "longueur" de la commande :

AT+CIPSEND=36 

Et la chaîne GET elle-même, qui sera lue à partir du champ 1 sur chacun des canaux de l'actionneur :

GET /channels/375598/fields/1/last 

Nous lirons les canaux ThingSpeak à des intervalles de 10 secondes. Après avoir envoyé la commande GET ci-dessus, qui appelle la "DERNIÈRE VALEUR STOCKÉE SUR LE CHAMP 1, nous recevrons une réponse de ThingSpeak qui devrait être "1" ou "0" sur une position spécifique de la réponse. Si quelque chose est différent de cela arrivé, il faut l'ignorer.

La principale différence entre cette partie du code et la précédente (pour envoyer les données d'état), est la fonction :

readThingSpeak(String channelID) 

Le code ci-dessous fera le travail pour nous et l'écran d'impression ci-dessus montre le résultat sur Serial Monitor :

// Thingspeak String canalID1 ="375598"; //Actuator1String canalID2 ="375599"; //Actuator2#include SoftwareSerial EspSerial (6, 7); // Rx, Tx#define HARDWARE_RESET 8// Variables à utiliser avec timerslong readTimingSeconds =10; // ==> Définir le temps d'échantillonnage en secondes pour recevoir les données long startReadTiming =0;long elapsedReadTime =0;//Relays#define ACTUATOR1 10 // LED ROUGE ==> Pump#define ACTUATOR2 12 // LED VERTE ==> Lampboolean pump =0 ; lampe booléenne =0 ; int spare =0;erreur booléenne;void setup(){ Serial.begin(9600); pinMode(ACTIONNEUR1, SORTIE); pinMode(ACTIONNEUR2,SORTIE); pinMode (HARDWARE_RESET, SORTIE); digitalWrite(ACTIONNEUR1, HAUT); //o modulo relé é ativo em LOW digitalWrite(ACTUATOR2, HIGH); // sur le module lié à l'état LOW digitalWrite(HARDWARE_RESET, HIGH); EspSerial.begin(9600); // Communication avec Modulo WiFi EspHardwareReset(); //Réinitialiser le module WiFi startReadTiming =millis(); // démarrage de l'"horloge du programme"}boucle void(){ start ://label error=0; elapsedReadTime =millis()-startReadTiming ; if (elapsedReadTime> (readTimingSeconds*1000)) { int command =readThingSpeak(canalID1) ; if (commande !=9) pompe =commande ; retard (5000); command =readThingSpeak(canalID2) ; if (commande !=9) lampe =commande; prendre des mesures(); startReadTiming =millis(); } if (error==1) //Renvoi si la transmission n'est pas terminée { Serial.println(" <<<>>>"); retard (2000); aller au début ; //Allez à l'étiquette "start" }}/********* Effectuez des actions basées sur les commandes ThingSpeak *************/void takeActions(void){ Serial.print( « Pompe : » ); Serial.println(pompe); Serial.print("Lampe :"); Serial.println(lampe); if (pompe ==1) digitalWrite(ACTUATOR1, LOW); else digitalWrite(ACTIONNEUR1, HAUT); if (lampe ==1) digitalWrite(ACTUATOR2, LOW); else digitalWrite(ACTUATOR2, HIGH);}/************ Lire la commande des actionneurs à partir de ThingSpeak *************/int readThingSpeak(String channelID){ startThingSpeakCmd(); commande int; // preparacao da string GET String getStr ="GET /channels/"; getStr +=channelID; getStr +="/fields/1/last" ; getStr +="\r\n" ; Chaîne messageDown =sendThingSpeakGetCmd(getStr); if (messageDown[5] ==49) { command =messageDown[7]-48; Serial.print("Commande reçue :"); Serial.println(commande); } commande else =9; return command;}/********* Réinitialiser ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......." ); digitalWrite(HARDWARE_RESET, LOW); retard (500); digitalWrite(HARDWARE_RESET, HAUT); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********** Démarre la communication avec ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error"); retourner; }}/********* envoie une commande GET à ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> longueur cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; } } 

The code can be downloaded from my GITHUB:ReadingCommandTS_EXT.ino

Step 14:Sending Commands to Actuators

At this point, we have the actuators channels configured on ThingSpeak and changing the value of Field 1 on each channel, we must see the actuators changing accordingly. On our final project we will do this task, using the Android App, but for testing proposes we can also do it using a normal browser. Let's do it.

The commands are:

Turn ON Pump (RED LED):

https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=1 

Turn OFF Pump (RED LED):

https://api.thingspeak.com/update?api_key=ACT1_WRITE_KEY&field1=0 

Turn ON Lamp (GREEN LED):

https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=1 

Turn OFF Lamp (GREEN LED):

https://api.thingspeak.com/update?api_key=ACT2_WRITE_KEY&field1=0 

Above you can see a print screen of a command to TurnOn the Pump sent from a browser and how it will appear at Serial Monitor. Obviously, the LED Red and relay will be also be turned on.

Step 15:Completing the Android APP

Let's complete the APP. Previously we have developed a simple App that gets the status from ThingSpeak (READ from Staus Channel). Now we must WRITE on Actuator channels, so those commands could be read by Arduino and act on Pump and Lamp accordingly.

For a user to pass the commands to the App, we will use "buttons". A pair of buttons (ON and OFF) for each one of the Actuators.

When a button is pressed, the color of its text changes.

  • If ON ==> Blue
  • if OFF ==> Red

Above you can see the set of blocks for each one of the pairs of buttons.

Test the App, sending commands to turn ON and OFF the actuators. Check on Serial Monitor, the messages exchanged between ESP-01 and ThingSpeak.

The complete App code can be downloaded from my GITHUB:ArduFarmBot_V1_EXT.aia

Step 16:Putting All Together

Parfait! At this point, you have a full Android APP, a complete HW but you still do not have a code that will continuously read and write on ThingSpeak. Let's combine all that we have developed previously.

On the final code, you will find additional portions to verify for example if the ESP-01 is not freezing. We will do it, sending an AT command to it before any read or write. As we saw at the very beginning of this tutorial, sending an AT command should return from ESP-01 an OK. If this does not happen, we will proceed with an HW reset, commanded by SW (as we do once during setup phase).

The complete code for our project can be downloaded from my GITHUB:ArduFarmBot_Light_EXT.ino

Step 17:Conclusion

There is a lot to be explored in IoT arena with those great little devices, the Arduino Uno, and the ESP8266-01. We will return soon with new tutorials! Keep following MJRoBot tutorials!

As always, I hope this project can help others find their way in the exciting world of electronics, robotics, and IoT!

Please visit my GitHub for updated files:ArduFarmBot_Light

For more projects, please visit my blog:MJRoBot.org

Saludos from the south of the world!

See you at my next tutorial!

Thank you,

Marcelo

Code

  • Extrait de code n° 1
  • Code snippet #2
  • Extrait de code 3
  • Code snippet #11
  • Code snippet #12
  • Code snippet #16
  • Code snippet #20
Extrait de code n°1Texte brut
// DS18B20#include #include #define ONE_WIRE_BUS 5 // DS18B20 on pin D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int soilTemp =0;//DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;
Code snippet #2Plain text
void setup(){ Serial.begin(9600); DS18B20.begin(); dht.begin();}void loop(){ readSensors(); displaySensors(); delay (10000);}
Extrait de code n°3Texte brut
/********* Read Sensors value *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soilTemp =DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius soilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% }/********* Display Sensors value *************/void displaySensors(void){ Serial.print ("airTemp (oC):"); Serial.println (airTemp); Serial.print ("airHum (%):"); Serial.println (airHum); Serial.print ("soilTemp (oC):"); Serial.println (soilTemp); Serial.print ("soilHum (%):"); Serial.println (soilHum); Serial.print ("light (%):"); Serial.println (light); Serial.println ("");}
Code snippet #11Plain text
#include  SoftwareSerial esp8266(6,7); //Rx ==> Pin 6; TX ==> Pin7 #define speed8266 9600 void setup() { esp8266.begin (speed8266); Serial.begin(speed8266); Serial.println("ESP8266 Setup test - use AT coomands");}void loop() { while(esp8266.available()) { Serial.write(esp8266.read()); } while(Serial.available()) { esp8266.write(Serial.read()); }}
Code snippet #12Plain text
* AT =====> ESP8266 returns OK* AT+RST =====> ESP8266 restart and returns OK* AT+GMR =====> ESP8266 returns AT Version; SDK version; id; OK* AT+CWMODE? => ESP8266 returns mode type* AT+CWLAP ===> ESP8266 returs close access points* AT+CIFSR ===> ESP8266 returs designided IP
Code snippet #16Plain text
// Thingspeak String statusChWriteKey ="6SRPQQKIE6AJVQE6"; // Status Channel id:385184#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// DS18B20#include #include #define ONE_WIRE_BUS 5 // DS18B20 on pin D5 OneWire oneWire(ONE_WIRE_BUS);DallasTemperature DS18B20(&oneWire);int soilTemp =0;//DHT#include "DHT.h"#include int pinoDHT =11;int tipoDHT =DHT22;DHT dht(pinoDHT, tipoDHT); int airTemp =0;int airHum =0;// LDR (Light)#define ldrPIN 1int light =0;// Soil humidity#define soilHumPIN 0int soilHum =0;// Variables to be used with timerslong writeTimingSeconds =17; // ==> Define Sample time in seconds to send datalong startWriteTiming =0;long elapsedWriteTime =0;// Variables to be used with Actuatorsboolean pump =0; boolean lamp =0; int spare =0;boolean error;void setup(){ Serial.begin(9600); pinMode(HARDWARE_RESET,OUTPUT); digitalWrite(HARDWARE_RESET, HIGH); DS18B20.begin(); dht.begin(); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); //Reset do Modulo WiFi startWriteTiming =millis(); // starting the "program clock"}void loop(){ start://label error=0; elapsedWriteTime =millis()-startWriteTiming; if (elapsedWriteTime> (writeTimingSeconds*1000)) { readSensors(); writeThingSpeak(); startWriteTiming =millis(); } if (error==1) //Resend if transmission is not completed { Serial.println(" <<<>>>"); delay (2000); goto start; //go to label "start" }}/********* Read Sensors value *************/void readSensors(void){ airTemp =dht.readTemperature(); airHum =dht.readHumidity(); DS18B20.requestTemperatures(); soilTemp =DS18B20.getTempCByIndex(0); // Sensor 0 will capture Soil Temp in Celcius light =map(analogRead(ldrPIN), 1023, 0, 0, 100); //LDRDark:0 ==> light 100% soilHum =map(analogRead(soilHumPIN), 1023, 0, 0, 100); }/********* Conexao com TCP com Thingspeak *******/void writeThingSpeak(void){ startThingSpeakCmd(); // preparacao da string GET String getStr ="GET /update?api_key="; getStr +=statusChWriteKey; getStr +="&field1="; getStr +=String(pump); getStr +="&field2="; getStr +=String(lamp); getStr +="&field3="; getStr +=String(airTemp); getStr +="&field4="; getStr +=String(airHum); getStr +="&field5="; getStr +=String(soilTemp); getStr +="&field6="; getStr +=String(soilHum); getStr +="&field7="; getStr +=String(light); getStr +="&field8="; getStr +=String(spare); getStr +="\r\n\r\n"; sendThingSpeakGetCmd(getStr); }/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); retard (500); digitalWrite(HARDWARE_RESET, HIGH); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********* Start communication with ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error"); retourner; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; } }
Code snippet #20Plain text
// Thingspeak String canalID1 ="375598"; //Actuator1String canalID2 ="375599"; //Actuator2#include SoftwareSerial EspSerial(6, 7); // Rx, Tx#define HARDWARE_RESET 8// Variables to be used with timerslong readTimingSeconds =10; // ==> Define Sample time in seconds to receive datalong startReadTiming =0;long elapsedReadTime =0;//Relays#define ACTUATOR1 10 // RED LED ==> Pump#define ACTUATOR2 12 // GREEN LED ==> Lampboolean pump =0; boolean lamp =0; int spare =0;boolean error;void setup(){ Serial.begin(9600); pinMode(ACTUATOR1,OUTPUT); pinMode(ACTUATOR2,OUTPUT); pinMode(HARDWARE_RESET,OUTPUT); digitalWrite(ACTUATOR1, HIGH); //o módulo relé é ativo em LOW digitalWrite(ACTUATOR2, HIGH); //o módulo relé é ativo em LOW digitalWrite(HARDWARE_RESET, HIGH); EspSerial.begin(9600); // Comunicacao com Modulo WiFi EspHardwareReset(); //Reset do Modulo WiFi startReadTiming =millis(); // starting the "program clock"}void loop(){ start://label error=0; elapsedReadTime =millis()-startReadTiming; if (elapsedReadTime> (readTimingSeconds*1000)) { int command =readThingSpeak(canalID1); if (command !=9) pump =command; delay (5000); command =readThingSpeak(canalID2); if (command !=9) lamp =command; takeActions(); startReadTiming =millis(); } if (error==1) //Resend if transmission is not completed { Serial.println(" <<<>>>"); delay (2000); goto start; //go to label "start" }}/********* Take actions based on ThingSpeak Commands *************/void takeActions(void){ Serial.print("Pump:"); Serial.println(pump); Serial.print("Lamp:"); Serial.println(lamp); if (pump ==1) digitalWrite(ACTUATOR1, LOW); else digitalWrite(ACTUATOR1, HIGH); if (lamp ==1) digitalWrite(ACTUATOR2, LOW); else digitalWrite(ACTUATOR2, HIGH);}/********* Read Actuators command from ThingSpeak *************/int readThingSpeak(String channelID){ startThingSpeakCmd(); int command; // preparacao da string GET String getStr ="GET /channels/"; getStr +=channelID; getStr +="/fields/1/last"; getStr +="\r\n"; String messageDown =sendThingSpeakGetCmd(getStr); if (messageDown[5] ==49) { command =messageDown[7]-48; Serial.print("Command received:"); Serial.println(command); } else command =9; return command;}/********* Reset ESP *************/void EspHardwareReset(void){ Serial.println("Reseting......."); digitalWrite(HARDWARE_RESET, LOW); retard (500); digitalWrite(HARDWARE_RESET, HIGH); delay(8000);//Tempo necessário para começar a ler Serial.println("RESET"); }/********* Start communication with ThingSpeak*************/void startThingSpeakCmd(void){ EspSerial.flush();//limpa o buffer antes de começar a gravar String cmd ="AT+CIPSTART=\"TCP\",\""; cmd +="184.106.153.149"; // Endereco IP de api.thingspeak.com cmd +="\",80"; EspSerial.println(cmd); Serial.print("enviado ==> Start cmd:"); Serial.println(cmd); if(EspSerial.find("Error")) { Serial.println("AT+CIPSTART error"); retourner; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd +=String(getStr.length()); EspSerial.println(cmd); Serial.print("enviado ==> lenght cmd:"); Serial.println(cmd); if(EspSerial.find((char *)">")) { EspSerial.print(getStr); Serial.print("enviado ==> getStr:"); Serial.println(getStr); delay(500);//tempo para processar o GET, sem este delay apresenta busy no próximo comando String messageBody =""; while (EspSerial.available()) { String line =EspSerial.readStringUntil('\n'); if (line.length() ==1) { //actual content starts after empty line (that has length 1) messageBody =EspSerial.readStringUntil('\n'); } } Serial.print("MessageBody received:"); Serial.println(messageBody); return messageBody; } else { EspSerial.println("AT+CIPCLOSE"); // alert user Serial.println("ESP8266 CIPSEND ERROR:RESENDING"); //Resend... spare =spare + 1; error=1; return "error"; } }
Github
https://github.com/Mjrovai/ArduFarmBot_Light

Schémas

Electrical diagram
https://github.com/Mjrovai/ArduFarmBot_Light/blob/master/ArduFarmBot_Light/ArduFarmBot%20Light.fzz

Processus de fabrication

  1. Le calcul parallèle sur les cartes IoT Raspberry Pi 4B+ en toute simplicité
  2. Moniteur de fréquence cardiaque utilisant l'IoT
  3. WebServerBlink avec Arduino Uno WiFi
  4. Calculatrice UNO simple
  5. Persistance de la vision
  6. Portail de surveillance de la température sans contact
  7. Arduino - Envoyer la température au Web via série
  8. Est-il facile d'utiliser une thermistance ? !
  9. Piscine Azure IoT