Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

IoT simplificado con UNO, ESP-01, ThingSpeak y MIT App Inventor

Componentes y suministros

Arduino UNO
× 1
Espressif ESP8266 ESP-01
× 1
Sensor de temperatura DHT22
× 1
DS18B20 Sensor de temperatura digital de 1 cable para uso en el suelo
× 1
LDR - Resistencia dependiente de la luz
× 1
Módulo de relé de 5 V CC de 2 canales
× 1

Aplicaciones y servicios en línea

Arduino IDE
API ThingSpeak
MIT App Inventor

Acerca de este proyecto

Nuestro objetivo será básicamente recopilar información de una unidad local y enviarla a Internet. Un usuario en cualquier parte del planeta que mire esta información tomará decisiones enviando comandos remotos a los actuadores, que también estarán en esta unidad local. Se puede utilizar cualquier sensor o actuador.

La gran mayoría de mi trabajo en el campo de IoT fue utilizando NodeMCU y, más recientemente, el ESP32. Pero, creo que es importante no olvidar mis primeros pasos, hace un par de años donde comencé a aprender IoT usando un Arduino UNO y el viejo y bueno ESP8266-01.

Entonces, decido aquí volver a esa época (con un poco más de experiencia ahora) y explorar nuevamente esos grandiosos dispositivos, conectándolos a la nube, usando el servicio web ThingSpeak.com. También exploraremos para controlar las cosas de forma remota, utilizando una aplicación de Android desarrollada con MIT AppInventor.

El "Centro de nuestro proyecto de IoT" será ThingSpeak.com. La unidad local (UNO / ESP-01) capturará datos de los sensores y el estado del actuador, enviar a Internet, "escribiendo" en un ThingSpeak.com específico Canal de estado . La unidad local también recibirá datos de Internet, "leyéndolos" de Canales del actuador ThingSpeak específicos .

Una aplicación de Android también estará leyendo esos datos del canal de estado de ThingSpeak.com y mostrándolos al usuario. De la misma manera, el usuario, basándose en esa información de estado, puede enviar comandos a los actuadores, escribiendo en los canales del actuador ThingSpeak (consulte el diagrama de bloques anterior para comprender mejor el flujo de datos).

¿Entonces que haremos? El diagrama de bloques que se muestra en el siguiente paso nos dará una descripción general del proyecto final:

Paso 1:Introducción

Usando sensores comunes, nuestro proyecto capturará varios datos, enviándolos a la nube, donde todos pueden verlos a través de Internet. Para trabajar esos datos, utilizaremos el servicio proporcionado por ThingSpeak.com, una plataforma abierta de IoT que nos permitirá recopilar, analizar y actuar sobre esos datos.

Los datos que recopilarán los sensores será:

  • Temperatura del aire y humedad relativa
  • Temperatura y humedad del suelo
  • Luminosidad

El proyecto tendrá 2 actuadores :

  • Bomba eléctrica
  • Lámpara eléctrica

El estado de esos actuadores ("ON / OFF"), también debe enviarse a la nube.

Entonces, la idea será capturar esos datos de los sensores, por ejemplo, una plantación y enviarlos a la nube. Con base en esos datos, un usuario debe tomar la decisión basándose en esas declaraciones:

  • Encienda la bomba si la humedad del suelo es demasiado baja
  • Encienda la lámpara si la temperatura del suelo es demasiado baja

Para controlar de forma remota nuestros actuadores, usaremos una aplicación de Android.

Paso 2:BoM - Lista de materiales

Algunos de los componentes más importantes enumerados aquí, tienen un enlace y un precio indicativo en USD asociado. Esos enlaces son solo para información.

  • Arduino UNO (microcontrolador) - $ 10.00
  • ESP8266-01 (módulo de comunicación) - $ 3.50
  • DHT22 (Sensor de aire y humedad relativa) - $ 9.00
  • DS18B20 (sensor de temperatura digital de 1 cable para usar en el suelo) - $ 6.00
  • YL-69 + LM393 (sensor de humedad del suelo) - $ 2.00
  • LDR (sensor de luminosidad) - $ 0.20
  • 2 x LED (rojo y verde)
  • Módulo de relé de 5 V CC de 1 x 2 canales con disparador de nivel bajo optoacoplador - $ 7.00
  • Bomba de 5 V CC - $ 3.00
  • Lámpara 220V
  • Resistencia de 2 x 330 ohmios (para usar con LED)
  • Resistencia de 2 x 10K ohmios (para usar con DHT22 y LDR)
  • 1 resistencia de 4K7 ohmios (para usar con DS18B20
  • Protoboard
  • Jerséis
  • Alimentación externa de 5 V CC para relés

Paso 3:el hardware

Vamos a montar el Proyecto HW. Lo ideal es instalar y probar nuestro proyecto por partes. Como sugerencia, podemos seguir los pasos:

  • Instale y pruebe localmente todos los sensores
  • Instale y configure el ESP-01 (BareMinimum)
  • Cambie la instalación de ESP-01 por su configuración final y pruébela
  • Configure el canal de estado de ThingsPeak
  • Instale el código ThingsPeak en su Arduino y verifique el estado de los sensores en la nube
  • Desarrolle la primera versión de la aplicación de Android para mostrar el estado y los mensajes
  • Instale actuadores (LED y relés)
  • Configurar canales de actuadores ThingSpeak
  • Instale y pruebe el código Arduino con actuadores
  • Desarrolle la versión final de la aplicación de Android

Paso 4:Conexión de sensores

Debemos tener algunas bibliotecas instaladas en nuestro IDE para leer los sensores correctamente. Compruebe si tiene todas las bibliotecas instaladas. Su configuración inicial debe ser:

  // DS18B20 # include  #include  #define ONE_WIRE_BUS 5 // DS18B20 en el pin D5 OneWire oneWire (ONE_WIRE_BUS); DallasTemperature DS18B20 (&oneWire); int FloorTemp =0; // DHT # incluye "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; // Humedad del suelo # define groundHumPIN 0int sueloHum =0;  

En Configuración y bucle, escribamos:

  void setup () {Serial.begin (9600); DS18B20.begin (); dht.begin ();} bucle vacío () {readSensors (); displaySensors (); retraso (10000);}  

Y por último, escribamos dos funciones específicas, una para leer nuestros sensores y otra para mostrar sus valores en Serial Monitor:

  / ********* Valor de lectura de sensores ************* / void readSensors (void) {airTemp =dht.readTemperature (); airHum =dht.readHumidity (); DS18B20.requestTemperatures (); SueloTemp =DS18B20.getTempCByIndex (0); // El sensor 0 capturará la temperatura del suelo en grados centígrados. luz =mapa (analogRead (ldrPIN), 1023, 0, 0, 100); // LDRDark:0 ==> light 100%} / ********* Mostrar valor de sensores ************* / void displaySensors (void) {Serial.print (" airTemp (oC):"); Serial.println (airTemp); Serial.print ("airHum (%):"); Serial.println (airHum); Serial.print ("SueloTemp (oC):"); Serial.println (sueloTemp); Serial.print ("sueloHum (%):"); Serial.println (sueloHum); Serial.print ("claro (%):"); Serial.println (ligero); Serial.println ("");}  

La siguiente imagen del monitor serial nos muestra los valores del sensor.

El código se puede descargar desde mi GITHUB:Sens ors_Test.ino

Paso 5:Configuración inicial de ESP8266-01

El ESP-01 se utilizará como Serial Bridge, lo que significa que lo programaremos mediante "comandos AT". Lo primero es asegurarse de que su ESP-01 tenga la velocidad de comunicación correcta en baudios. En nuestro caso, 9.600 baudios. Normalmente, los ESP-01 vienen programados de fábrica con 115.200 baudios y debemos cambiarlo a 9.600 baudios.

Primero, debe conectar el ESP-01 como se muestra arriba.

Luego conecte el Arduino a su computadora, abra el IDE y cargue el ejemplo que está en Archivo> Ejemplos> 01.Basics> BareMinimum. Este es un código vacío, para asegurar que no habrá conflicto de comunicación entre Arduino y ESP.

Hemos transferido este código al Arduino antes de conectarlo al ESP-01S para asegurarnos de que el Arduino no utilizará comunicación en serie (TX y RX). Esto es importante para que ESP pueda comunicarse correctamente.

Abra su monitor serie IDE y cambie la velocidad a 115.200 baudios. Empiece a enviar un comando "AT" en su monitor serie IDE. El ESP-01 debería devolver "OK"

A continuación, cambiemos la velocidad. Para eso, puede usar el comando:

  AT + CIOBAUD =9600  

Tenga en cuenta que el ESP-01 puede volver a la programación de fábrica (no sé si esto se debe a la versión FW). Al menos en mi caso, tuve que usar un comando diferente para cambiar BaudRate definitivamente:

  AT + UART_DEF =, , , ,   

Por ejemplo:9600 baudios / 8 bits de datos / 1 bit de parada y sin control de paridad y flujo:

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

En el cuadro de selección en la parte inferior de su monitor serial, cambie la velocidad a "9600 baudios". Pruebe la comunicación:en la parte superior de la ventana escriba AT y vea la respuesta OK. Ahora debe configurar el módulo en Modo de estación para actuar como Cliente de su red Wi-Fi. Utilice el comando:

  AT + CWMODE =1  

Ahora debemos conectar el módulo a su red Wi-Fi.

Para hacer esto, use los siguientes comandos, reemplazando "network_name" con el nombre de su red Wi-Fi y "network_name" con su contraseña. Mantenga las comillas.

  AT + CWJAP ="nombre_red", "nombre_red"  

Si ve la respuesta a continuación, su conexión se ha establecido correctamente:

  WIFI CONECTADO WIFI GOT IP  

Para encontrar la IP, ejecute el comando:

  AT + CIFSR  

Y tome nota de la dirección IP que aparecerá en su Serial Monitor. Puede que lo necesite en el futuro.

Paso 6:prueba del ESP-01

Una vez tenemos configurado el ESP-01, debemos instalarlo en su circuito final. Para eso debemos CAMBIAR el cableado realizado anteriormente y conectar el ESP-01 a nuestro UNO como se muestra a continuación:

  • ESP-01 RX (amarillo) a UNO Pin D7
  • ESP-01 TX (naranja) a UNO Pin D6
  • ESP-01 Ch-Pd (marrón) a Vcc (3.3V)
  • Reinicio de ESP-01 (azul) a UNO Pin D8
  • ESP-01 Vcc (rojo) a 3.3V
  • ESP-01 Gnd (negro) a UNO GND

Hagamos una prueba sencilla para comprobar si nuestro ESP-01 está corregido instalado y probado. Ingrese el siguiente código:

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

Ahora, pruebe algunos comandos AT y vea el resultado en su monitor serial:

  * AT =====> ESP8266 devuelve OK * AT + RST =====> ESP8266 reinicia y devuelve OK * AT + GMR =====> ESP8266 devuelve AT Version; Versión SDK; identificación; OK * AT + CWMODE? => ESP8266 devuelve el tipo de modo * AT + CWLAP ===> ESP8266 devuelve puntos de acceso cercanos * AT + CIFSR ===> ESP8266 devuelve IP designada  

El código se puede descargar desde mi GITHUB:ESP_AT_Config.ino

Si desea conectarse a la red WiFi cada vez que se produce un reinicio (o su Arduino se apaga / enciende) e ingresa sus credenciales, agregue una llamada al connectWiFi () función al final de la función setup ():

  configuración () {... connectWiFi (); }  

El connectWiFi () La función debe estar al final de su código principal .ino:

  void connectWiFi (void) {sendData ("AT + RST \ r \ n", 2000, 0); // restablecer sendData ("AT + CWJAP =\" SU NOMBRE DE USUARIO \ ", \" SU CONTRASEÑA \ "\ r \ n", 2000, 0); // Retardo de conexión de red (3000); sendData ("AT + CWMODE =1 \ r \ n", 1000, 0); sendData ("AT + CIFSR \ r \ n", 1000, 0); // Mostrar dirección IP Serial.println ("8266 conectado");}  

Tenga en cuenta que la función anterior llama a otro sendData (datos) función, que también debe estar ubicada en su código:

  String sendData (String command, const int timeout, boolean debug) {String response =""; EspSerial.print (comando); tiempo int largo =millis (); while ((tiempo + tiempo de espera)> millis ()) {while (EspSerial.available ()) {// El esp tiene datos, así que muestra su salida en la ventana serial char c =EspSerial.read (); // lee el siguiente carácter. respuesta + =c; }} if (debug) {Serial.print (respuesta); } respuesta de retorno;}  

Paso 7:Conexión de sensores y ESP-01

Una vez que tengamos todos los sensores instalados y probados y también nuestro ESP-01 funcionando correctamente, veamos todos juntos y preparados para enviar datos a Internet.

Paso 8:ThingSpeak

Una de las partes más importantes de nuestro proyecto es ThingSpeak, una plataforma abierta de IoT que nos permitirá recopilar, analizar y actuar sobre los datos recopilados. Si aún no lo ha hecho, vaya a ThingSpeak, regístrese y cree su cuenta.

A continuación, cree un nuevo Canal donde tendremos nuestros 2 actuadores, 5 sensores y un estado de campo de repuesto:

  • Campo 1:Actuador 1
  • Campo 2:Actuador 2
  • Campo 3:Temperatura del aire en oC
  • Archivado 4:Humedad relativa del aire en%
  • Campo 5:Temperatura del suelo en oC
  • Campo 6:Humedad del suelo en%
  • Campo 7:Luminosidad en%
  • Campo 8:Repuesto

El campo 8 se dejará como repuesto para utilizarlo en futuras ampliaciones o con fines de depuración. Por ejemplo, lo usaré como un "contador" para cada error de comunicación que ocurra durante el apretón de manos de Arduino / ESP-01 con ThingSpeak.com.

Una vez que cree su canal (en este caso será nuestro Canal de Estado), será importante que tome nota de sus claves, como se muestra a continuación.

Paso 9:Envío de estado a la nube

En este punto, tenemos nuestro Servicio en la Nube disponible y nuestros sensores capturan datos localmente. Tomemos esos valores y enviemoslos a ThingSpeak.com. Escribiremos en el canal ThingSpeak y para eso, necesitaremos enviar una cadena GET. Lo haremos en 3 partes:

Enviaremos un "cmd de inicio":

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

Siguiendo la "longitud" del comando:

  AT + CIPSEND =116  

Y la cadena GET en sí, que escribirá en los campos correspondientes en el canal de estado:

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

El siguiente código hará el trabajo por nosotros y el PrintScreen anterior muestra el resultado en Serial Monitor:

  // Thingspeak String statusChWriteKey ="6SRPQQKIE6AJVQE6"; // ID de canal de estado:385184 # include  SoftwareSerial EspSerial (6, 7); // Rx, Tx # define HARDWARE_RESET 8 // DS18B20 # incluye  #include  #define ONE_WIRE_BUS 5 // DS18B20 en el pin D5 OneWire oneWire (ONE_WIRE_BUS); DallasTemperature DS18B20 (&oneTempire) =0; // DHT # incluye "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; // Humedad del suelo # define groundHumPIN 0int groundHum =0; // Variables que se utilizarán con timerslong writeTimingSeconds =17; // ==> Definir el tiempo de muestra en segundos para enviar datos a lo largo de startWriteTiming =0; long elapsedWriteTime =0; // Variables que se utilizarán con Actuatorsboolean pump =0; lámpara booleana =0; int spare =0; error booleano; void setup () {Serial.begin (9600); pinMode (HARDWARE_RESET, SALIDA); digitalWrite (HARDWARE_RESET, HIGH); DS18B20.begin (); dht.begin (); EspSerial.begin (9600); // Comunicacao com Modulo WiFi EspHardwareReset (); // Restablecer el módulo WiFi startWriteTiming =millis (); // iniciando el "reloj del programa"} void loop () {inicio:// error de etiqueta =0; elapsedWriteTime =millis () - startWriteTiming; if (elapsedWriteTime> (writeTimingSeconds * 1000)) {readSensors (); writeThingSpeak (); startWriteTiming =millis (); } if (error ==1) // Reenviar si la transmisión no se completa {Serial.println ("<<<>>>"); retraso (2000); ir a empezar; // ir a la etiqueta "start"}} / ********* Leer el valor de los sensores ************* / void readSensors (void) {airTemp =dht.readTemperature (); airHum =dht.readHumidity (); DS18B20.requestTemperatures (); SueloTemp =DS18B20.getTempCByIndex (0); // El sensor 0 capturará la temperatura del suelo en Celsius light =map (analogRead (ldrPIN), 1023, 0, 0, 100); // LDRDark:0 ==> luz 100% sueloHum =mapa (analogRead (sueloHumPIN), 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 + ="&campo1 ="; getStr + =String (bomba); getStr + ="&campo2 ="; getStr + =String (lámpara); getStr + ="&campo3 ="; getStr + =String (airTemp); getStr + ="&campo4 ="; getStr + =String (airHum); getStr + ="&field5 ="; getStr + =String (sueloTemp); getStr + ="&field6 ="; getStr + =String (sueloHum); getStr + ="&field7 ="; getStr + =String (ligero); getStr + ="&field8 ="; getStr + =String (repuesto); getStr + ="\ r \ n \ r \ n"; sendThingSpeakGetCmd (getStr); } / ********* Restablecer ESP ************* / void EspHardwareReset (void) {Serial.println ("Restableciendo ......."); digitalWrite (HARDWARE_RESET, LOW); retraso (500); digitalWrite (HARDWARE_RESET, HIGH); delay (8000); // Tempo required para começar a ler Serial.println ("RESET"); } / ********* Iniciar comunicación con 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 ==> Inicio cmd:"); Serial.println (cmd); if (EspSerial.find ("Error")) {Serial.println ("Error AT + CIPSTART"); regreso; }} / ********* envía un cmd GET a ThingSpeak ************* / String sendThingSpeakGetCmd (String getStr) {String cmd ="AT + CIPSEND ="; cmd + =Cadena (getStr.length ()); EspSerial.println (cmd); Serial.print ("enviado ==> longitud 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) {// el contenido real comienza después de una línea vacía (que tiene una longitud de 1) messageBody =EspSerial.readStringUntil ('\ n'); }} Serial.print ("MessageBody recibido:"); Serial.println (messageBody); return messageBody; } else {EspSerial.println ("AT + CIPCLOSE"); // alertar al usuario Serial.println ("ESP8266 CIPSEND ERROR:RESENDING"); // Reenviar ... repuesto =repuesto + 1; error =1; devolver "error"; }}  

El código se puede descargar desde mi GITHUB:SendingStatusTS_EXT.ino

Paso 10:Primera parte de la aplicación de Android:supervisión del estado

Creemos nuestra primera parte de la aplicación de Android.

Primero, diseñamos la interfaz de usuario. La pantalla de impresión anterior muestra los principales elementos visibles y no visibles. Después de eso, debemos diseñar los bloques (los números a continuación corresponden a las figuras anteriores):

Cada 2 segundos (definido por Clock1), llamaremos a un procedimiento llamado:"readArduino".

  • El retorno de dicho procedimiento será el valor para cada una de las variables de Estado que deben mostrarse en la pantalla.
  • Tenga en cuenta que "convertiremos" los valores "0" y "1" del estado de los actuadores a "APAGADO" y "ENCENDIDO" para una mejor comprensión.
  • Esos valores ("Estado") se mostrarán en las "etiquetas" correspondientes
  • Las variables de estado deben declararse como globales.
  • El procedimiento "readArduino" leerá, de hecho, el canal de estado en ThingSpeak. Entonces, debemos definir la URL que se enviará a Thingspeak. Para eso, se deben declarar y unir 3 variables globales para crear la URL que se enviará a TS. Se debe enviar un GET al componente web llamado "ArduFarmBotStatusCh"
  • El texto obtenido del comando anterior llegará como formato JSon. Este texto debe procesarse teniendo cada campo para ser leído y almacenado en la variable global correspondiente.
  • Lo último que se debe hacer es llamar al procedimiento de "Alarma", que analizará el estado de dos sensores de suelo. Si la temperatura es demasiado baja (en nuestro caso 10oC), se debe mostrar un mensaje. Lo mismo ocurre con la humedad, si es inferior al 60%. Tenga en cuenta que hemos definido otro temporizador (Reloj2), programado para ser disparado cada 1 segundo. Esto es solo para "alternar" el color del texto del mensaje (de blanco a rojo). Esto hará que el mensaje "parpadee".

La última foto de arriba muestra la aplicación final funcionando.

El código de la aplicación se puede descargar desde mi GITHUB:ArduFarmBot_Status_App_EXT.aia

Paso 11:Instalación de actuadores (LED y relés)

Completemos nuestro HW.

Para eso, debemos instalar nuestros Actuadores. Como recordará, recibiremos de forma remota comandos para ENCENDER y APAGAR una bomba y una lámpara. La salida de Arduino activará un relé (y un LED) para obtener esas acciones.

Usaremos un módulo de relé que tiene un disparador de bajo nivel de optoacoplador. Además, le suministraremos 5 V a través de un pin separado, por lo que no tenemos que proporcionar la corriente requerida en el pin de entrada. El módulo lo hace por nosotros.

La figura anterior muestra cómo se deben conectar los actuadores. Tenga en cuenta que Realy GND NO ESTÁ CONECTADO a Arduino GND. Esto ayudará a no introducir ruido cuando el relé funcione.

Por simplicidad, saqué del diagrama, los sensores. Pero puede agregar los circuitos de los actuadores a su proyecto sin quitar los sensores que ya instaló y probó.

Paso 12:Configuración de los canales de los actuadores ThingSpeak

De la misma forma que hicimos para el Estado, crearemos 2 nuevos canales uno para cada actuador. De cada uno de ellos, tome nota de ID de canal, teclas de lectura y escritura. Escribiremos solo en el campo 1 de cada uno de esos canales. Entonces, en mi caso, por ejemplo:

ID de canal 375598 ==> LED rojo (bomba)

  • Field1 =0 ==> Bomba APAGADA
  • Field1 =1 ==> Bomba encendida

ID de canal 375599 ==> LED verde (lámpara)

  • Field1 =0 ==> Lámpara apagada
  • Field1 =1 ==> Lámpara encendida

Paso 13:Instalación y prueba del código Arduino con actuadores

Cuando enviamos datos a la web, lo que hicimos fue ESCRIBIR en un canal ThingSpeak (estado del canal) para "transmitir" (cargar) datos. Ahora deberíamos LEER de un canal ThingSpeak (Canal Actuator) para "recibir" (descargar) datos.

Leeremos de un canal ThingSpeak y para eso, necesitaremos enviar una cadena GET. Lo haremos en 3 partes:

Enviaremos un "cmd de inicio":

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

Siguiendo la "longitud" del comando:

  AT + CIPSEND =36  

Y la cadena GET en sí, que se leerá del campo 1 en cada uno de los canales del actuador:

  GET / channels / 375598 / fields / 1 / last  

Leeremos de los canales ThingSpeak en intervalos de 10 segundos. Después de enviar el comando GET anterior, que pide el "ÚLTIMO VALOR ALMACENADO EN EL CAMPO 1, recibiremos una respuesta de ThingSpeak que debería ser" 1 "o" 0 "en una posición específica de la respuesta. Si hay algo diferente a eso llegó, debemos ignorarlo.

La principal diferencia entre esta parte del código y la anterior (para enviar datos de estado), es la función:

  readThingSpeak (String channelID)  

El siguiente código hará el trabajo por nosotros y el PrintScreen anterior muestra el resultado en Serial Monitor:

  // Thingspeak String canalID1 ="375598"; // Actuator1String canalID2 ="375599"; // Actuator2 # include  SoftwareSerial EspSerial (6, 7); // Rx, Tx # define HARDWARE_RESET 8 // Variables que se utilizarán con timerslong readTimingSeconds =10; // ==> Definir el tiempo de muestra en segundos para recibir los datos startReadTiming =0; long elapsedReadTime =0; // Relés # define ACTUATOR1 10 // LED ROJO ==> Bomba # define ACTUATOR2 12 // VERDE LED ==> Bomba de lámpara booleana =0; lámpara booleana =0; int spare =0; error booleano; void setup () {Serial.begin (9600); pinMode (ACTUADOR1, SALIDA); pinMode (ACTUATOR2, SALIDA); pinMode (HARDWARE_RESET, SALIDA); 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 (); // Restablecer el módulo WiFi startReadTiming =millis (); // iniciando el "reloj del programa"} void loop () {inicio:// error de etiqueta =0; elapsedReadTime =millis () - startReadTiming; if (elapsedReadTime> (readTimingSeconds * 1000)) {int comando =readThingSpeak (canalID1); if (comando! =9) bomba =comando; retraso (5000); comando =readThingSpeak (canalID2); if (comando! =9) lámpara =comando; toma acciones(); startReadTiming =millis (); } if (error ==1) // Reenviar si la transmisión no se completa {Serial.println ("<<<>>>"); retraso (2000); ir a empezar; // ir a la etiqueta "inicio"}} / ********* Realizar acciones basadas en los comandos ThingSpeak ************* / void takeActions (void) {Serial.print ( "Bomba:"); Serial.println (bomba); Serial.print ("Lámpara:"); Serial.println (lámpara); if (bomba ==1) digitalWrite (ACTUATOR1, LOW); de lo contrario digitalWrite (ACTUATOR1, HIGH); if (lámpara ==1) digitalWrite (ACTUATOR2, LOW); else digitalWrite (ACTUATOR2, HIGH);} / ********* Leer comando de actuadores de ThingSpeak ************** / int readThingSpeak (String channelID) {startThingSpeakCmd (); comando int; // preparacao da string GET String getStr ="GET / channels /"; getStr + =channelID; getStr + ="/ campos / 1 / último"; getStr + ="\ r \ n"; Cadena messageDown =sendThingSpeakGetCmd (getStr); if (messageDown [5] ==49) {comando =messageDown [7] -48; Serial.print ("Comando recibido:"); Serial.println (comando); } comando else =9; comando return;} / ********* Restablecer ESP ************* / void EspHardwareReset (void) {Serial.println ("Restableciendo ......." ); digitalWrite (HARDWARE_RESET, LOW); retraso (500); digitalWrite (HARDWARE_RESET, HIGH); delay (8000); // Tempo required para começar a ler Serial.println ("RESET"); } / ********* Iniciar comunicación con 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 ==> Inicio cmd:"); Serial.println (cmd); if (EspSerial.find ("Error")) {Serial.println ("Error AT + CIPSTART"); regreso; }} / ********* envía un cmd GET a ThingSpeak ************* / String sendThingSpeakGetCmd (String getStr) {String cmd ="AT + CIPSEND ="; cmd + =Cadena (getStr.length ()); EspSerial.println (cmd); Serial.print ("enviado ==> longitud 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) {// el contenido real comienza después de una línea vacía (que tiene una longitud de 1) messageBody =EspSerial.readStringUntil ('\ n'); }} Serial.print ("MessageBody recibido:"); Serial.println (messageBody); return messageBody; } else {EspSerial.println ("AT + CIPCLOSE"); // alertar al usuario Serial.println ("ESP8266 CIPSEND ERROR:RESENDING"); // Reenviar ... repuesto =repuesto + 1; error =1; devolver "error"; }}  

El código se puede descargar desde mi GITHUB:ReadingCommandTS_EXT.ino

Paso 14:Envío de comandos a los actuadores

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

¡Perfecto! 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

Código

  • Fragmento de código n. ° 1
  • Code snippet #2
  • Fragmento de código n. ° 3
  • Fragmento de código n. ° 11
  • Code snippet #12
  • Code snippet #16
  • Code snippet #20
Fragmento de código n. ° 1 Texto sin formato
// 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);}
Fragmento de código n. ° 3 Texto sin formato
/********* 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 ("");}
Fragmento de código n. ° 11 Texto sin formato
#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; identificación; 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(" <<<>>>"); retraso (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 + ="&campo1 ="; getStr +=String(pump); getStr + ="&campo2 ="; 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); retraso (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"); return; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd + =Cadena (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 recibido:"); 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(" <<<>>>"); retraso (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); retraso (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"); return; }}/********* send a GET cmd to ThingSpeak *************/String sendThingSpeakGetCmd(String getStr){ String cmd ="AT+CIPSEND="; cmd + =Cadena (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 recibido:"); 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

Esquemas

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

Proceso de manufactura

  1. Computación en paralelo en placas Raspberry Pi 4B + IoT simplificada
  2. Monitor de frecuencia cardíaca con IoT
  3. WebServerBlink usando Arduino Uno WiFi
  4. Calculadora UNO simple
  5. Persistencia de la visión
  6. Puerta de control de temperatura sin contacto
  7. Arduino - Enviar temperatura a la web a través de serie
  8. Estación meteorológica ThingSpeak Arduino
  9. Monitoreo SMART de temperatura para escuelas
  10. ¡¿Qué tan fácil es usar un termistor ?!
  11. Piscina de Azure IoT