Skip to main content

Arduino IDE con IoT: ESP32 + Sensores externos + IoT

OBJETIVO

Ahora vamos a utilizar el ESP32 SIN EL ARDUINO ALVIK podemos sacar la placa microcontroladora y ponerlo en una placa protoboard y experimentar con sensores y actuadores estándares en el mercado :

2024-07-15 13_08_38-esp32 nano arduino at DuckDuckGo.png  + 2024-07-15 13_09_30-placa protoboard at DuckDuckGo.png

Para ver varias posibilidades, vamos a ver estos sensores y actuadores (recomendamos ver estas páginas actuadores y sensores)

  • Un led de salida simple, para practicar salida digital en mi caso voy a elegir este gracioso semáforo
  • Un sensor LDR pero para practicar los dos tipos de señal,
    • con salida analógica
    • con salida digital.
  • Un sensor CO2  CCS811 con protocolo I2C

+2024-07-15 13_11_03-semaforo arduino at DuckDuckGo.png+sensorluzarduino.jpg+CCS811-KEYSTUDUUDIO.png

ESQUEMA DE CONEXIONES
  • SEMAFORO
    • LED ROJO al D1 del ESP32
    • GND a GND
  • MODULO SENSOR LDR
    • SEÑAL DIGITAL al D0 del ESP32
    • SEÑAL ANALÓGICA al A0 del ESP32
    • VCC a 3V3
    • GND A GND
  • MODULO SENSOR CO2
    • SCL  al pin A5 del ESP32
    • SDA al pin A4 del ESP32
    • PIN WAKE a GND
    • VCC a 3V3
    • GND A GND

2024-07-07 20_14_06-Alvik User Manual _ Arduino Documentation.png

2024-07-15 14_47_48-New ESP32 Project - Wokwi Simulator.png

2024-07-15 14_08_38-(1) Exploring the Arduino Nano ESP32 _ MicroPython & IoT Cloud - YouTube.png

DEVICES 

Nos vamos a Arduino Cloud, y en DEVICES añadimos el ESP32 y obtenemos el TOKEN o palabra secreta (si has hecho la práctica anterior, no es necesario pues ya tenemos el TOKEN o palabra secreta) como es similar al caso anterior, no lo desarrollamos. (Nos pedirá también el SSID y la contraseña de la red wifi)

VARIABLES

Añadimos las siguientes variables :

  • CO2 tipo int y Read
  • luz  tipo int y Read
  • luzdigital tipo bool y Read
  • rojo tipo bool y Read&Write
EL SCKETCH -LIBRERIA CCS811

Primero añadiríamos la librería de keystudio https://fs.keyestudio.com/KS0457 pero no lo permite Arduino Cloud, viendo las instrucciones, vemos que son las mismas que en los ejemplos de esta librería la de DF que es la que instalamos :

2024-07-15 13_41_58-DETECTOR CO2 Thing _ Arduino Cloud.png

esto provoca la incorporación de la línea 1 #include <DFRobot_CCS811.h>

EL SCKETCH -EL CÓDIGO
  • Tenemos las variables definidas en las líneas 10-13 : 
    • int cO2;
    •  int luz;
    •  bool luzdigital;
    •  bool rojo;
  • Definimos una variable de tipo el sensor CCS811 en la línea 23 DFRobot_CCS811 CCS811;
  • En Setup en las líneas 48-21 arrancamos ese sensor:
    •  while(CCS811.begin() != 0){
              Serial.println("failed to init chip, please check if the chip connection is fine");
              delay(1000);
        }
  • Definimos los pines digitales 0 y 1  como entrada y salida respectivamente:  
    • pinMode(1,OUTPUT);
        pinMode(0,INPUT);
  • En las líneas 60-70 que lea el CCS811 y la parte de CO2 que lo meta en la variable CO2 (línea 63)
    • if(CCS811.checkDataReady() == true){
              Serial.print("CO2: ");
              Serial.print(CCS811.getCO2PPM());
              cO2=CCS811.getCO2PPM();
              Serial.print("ppm, TVOC: ");
              Serial.print(CCS811.getTVOCPPB());
              Serial.println("ppb");
              
          } else {
              Serial.println("Data is not ready!");
          }
  • En las línea 71 que luz sea la lectura del pin A0  luz = analogRead(A0);
  • En las líneas 72-76 que según rojo se encienda o no el led
    • if (rojo){
            digitalWrite(1,HIGH);
          }else{
            digitalWrite(1,LOW);
          }
  • En la línea 77 que luzdigital sea la lectura de la salida digital del sensor LDR
    •  luzdigital=digitalRead(0);

#include <DFRobot_CCS811.h>
/* 
  Sketch generated by the Arduino IoT Cloud Thing "Untitled"
  https://create.arduino.cc/cloud/things/17c10209-3874-430a-877c-c082ff7dd38d 

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  int cO2;
  int luz;
  bool luzdigital;
  bool rojo;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"

//DFRobot_CCS811 CCS811(&Wire, /*IIC_ADDRESS=*/0x5A);
DFRobot_CCS811 CCS811;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500); 

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
 */
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();


  while(CCS811.begin() != 0){
        Serial.println("failed to init chip, please check if the chip connection is fine");
        delay(1000);
    }
  pinMode(1,OUTPUT);
  pinMode(0,INPUT);
  
}

void loop() {
  ArduinoCloud.update();
  // Your code here 
   if(CCS811.checkDataReady() == true){
        Serial.print("CO2: ");
        Serial.print(CCS811.getCO2PPM());
        cO2=CCS811.getCO2PPM();
        Serial.print("ppm, TVOC: ");
        Serial.print(CCS811.getTVOCPPB());
        Serial.println("ppb");
        
    } else {
        Serial.println("Data is not ready!");
    }
    luz = analogRead(A0);
    if (rojo){
      digitalWrite(1,HIGH);
    }else{
      digitalWrite(1,LOW);
    }
    luzdigital=digitalRead(0);
  
  
}





/*
  Since Rojo is READ_WRITE variable, onRojoChange() is
  executed every time a new value is received from IoT Cloud.
*/
void onRojoChange()  {
  // Add your code here to act upon Rojo change
}
DASHBOARD
  • Un gauge ligado a CO2 desde 0 a 2000
  • Un gauge ligado a Luz de 0 a 2.200
  • Un Switch ligado a rojo
  • Un led de oscuridad ligado a luzdigital

2024-07-15 14_16_36-CO2 Dashboard _ Arduino Cloud.png

Alternativa : en vez de luz tendría que llamarse "oscuridad" que sea luz pero que vaya al revés

RESULTADO

ALTERNATIVA:  Que el semáforo visualice los niveles peligrosos de CO2, por ejemplo el umbral del amarillo 600-1.000

¿Te atreves a poner un servomotor?

Predictor meteorológico

Autor Mario Monteagudo Asesor digital Centro de Profesorado de Ejea de los Caballeros

Usando IDE Arduino y el sensor Bosch BME280 se puede medir la presión atmosférica, temperatura y humedad y usando un código predictivo Algoritmo de Zambretti que usa las diferencias de presiones cada 3 horas, puede hacer pronóscticos. Para ello mide la presión cada 5 minutos y tienen en cuenta la altitud del lugar y la temperatura.

El ESP32 tendría que estar en el exterior y como hemos explicado, necesita 3 horas para hacer su primera predicción.

Este es el resultado

Y este es el código

#include "arduino_secrets.h"
//Predictor del tiempo mediante el algoritmo de Zambretti************************
//2024*Mario Monteagudo Alda*****mario.monteagudo@cpejea.es**********************

#include "arduino_secrets.h"

#include <SimpleBME280.h>  //Biblioteca usada para el sensor

const float ALTURA = 497.0; //Altitud del lugar

SimpleBME280 bme280; //Declaración de la instancia del sensor

float presiones[37]; //Presiones corregidas cincominutales de las 3 últimas horas
int zambretti;       //Número de Zambretti
float temperatura;   //ºC
float humedad;       //Humedad relativa en %
float presion;       //Presión atmosférica en mbar
int contador = 0;    //Contador de número de medidas de presión cincominutales tomadas
bool encendido = false; //Bandera para intermitencia del LED

/* 
  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  String boletin;
  float fiabilidad;
  float tendencia;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/

#include "thingProperties.h"

void setup() {

  pinMode(LED_BUILTIN,OUTPUT);
  digitalWrite(LED_BUILTIN,HIGH);
  
  // Inicialización de la comunicación serie y espera 
  Serial.begin(19200);
  delay(2000);

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud and wait
  ArduinoCloud.begin(ArduinoIoTPreferredConnection, false);
  delay(2000);
  /*
     The following function allows you to obtain more information
     related to the state of network and IoT Cloud connection and errors
     the higher number the more granular information you’ll get.
     The default is 0 (only errors).
     Maximum is 4
 */
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();

  bme280.begin();  //Inicialización del sensor y espera
  delay(2000);     

  //Primera lectura del sensor
  bme280.update();
  presion = bme280.getP();
  temperatura = bme280.getT();
  
  //Corrección de la presión según la altitud y temperatura y paso de Pa a mbar
  presion = (presion * pow(1 - (0.0065 * ALTURA) / (temperatura + (0.0065 * ALTURA) + 273.15),-5.257 ))/100.0;
  for (int i=0; i<=36; i++) { presiones[i]=presion;}

  fiabilidad = 0;
}

void loop() {

  bme280.update();
  presion = bme280.getP();
  temperatura = bme280.getT();
  humedad = bme280.getH();
  presion = (presion * pow(1 - (0.0065 * ALTURA) / (temperatura + (0.0065 * ALTURA) + 273.15),-5.257 ))/100.0;

  tendencia=presion-presiones[0];

  for (int i=0; i<36; i++) { presiones[i]=presiones[i+1];}
  presiones[36] = presion;

  //Cálculo del número de Zambretti
  if ((tendencia <= -1.6) & (presion > 985.0) & (presion < 1050.0)) {zambretti = round(127-0.12*presion);}
    
  else if ((tendencia >= 1.6) & (presion > 947.0) & (presion < 1030.0)) {zambretti = round(185-0.16*presion);}
    
  else if ((abs(tendencia) < 1.6) & (presion > 960.0) & (presion < 1033.0)) {zambretti = round(144-0.13*presion);}
       
  else {zambretti = 0;}

  //Boletín con el pronóstico
  boletin = "Temperatura: " +      String(temperatura,1)  + " ºC" + "\n" + 
            "Humedad relativa: " + String(humedad,1)  + " %" + "\n" + 
            "Presión: " +          String(presion,0)  + " mbar" + "\n" + 
            "Tendencia: " +        String(tendencia,2)  + " mbar" + "\n" + 
             pronostico(zambretti);
  
  Serial.println(boletin + "\n");
    
  //Espera de cinco minutos para la actualización 
  unsigned long tiempo = millis();
  while ((millis()-tiempo) < 5*60*1000 )
    {
      ArduinoCloud.update();
      delay(1000);
      encendido = !encendido;
      digitalWrite(LED_BUILTIN,encendido);
    }
  
  contador = min(36, contador + 1);

  //Después de tres horas de medidas, la fiabilidad es del 100%
  fiabilidad = map(contador, 0, 36, 0, 100);
  
}

//Cadena de texto con el pronóstico meteorológico***********************

String pronostico(int z)
{
  switch (z)
  {
  case 1:
    return "Tiempo estable"; break;
  case 2:
    return "Buen tiempo"; break;
  case 3: 
    return "Buen tiempo con ligera inestabilidad"; break;
  case 4:
    return "Buen tiempo evolucionando a chubascos";  break;
  case 5:
    return "Chubascos evolucionando a tiempo inestable";  break;
  case 6:
    return "Inestable evolucionando a lluvioso";   break;
  case 7:
    return "Intervalos de lluvia con empeoramiento";  break;
  case 8:
    return "Intervalos de lluvia evolucionando a gran inestabilidad"; break;
  case 9:
    return "Muy inestable con lluvia"; break;
  case 10 : 
    return "Tiempo estable"; break;
  case 11:
    return "Buen tiempo";  break;   
  case 12:
    return "Buen tiempo con posibles chubascos";  break;   
  case 13:
    return "Buen tiempo con probables chubascos"; break;
  case 14:
    return "Chubascos con intervalos despejados"; break;
  case 15:
    return "Variable con algo de lluvia";  break;
  case 16:
    return "Inestable con intervalos de lluvia"; break; 
  case 17:
    return "Lluvia a intervalos frecuentes"; break;
  case 18:
    return "Muy inestable con lluvia"; break;    
  case 19:
    return "Tormentoso con lluvia abundante";  break;
  case 20 : 
    return "Tiempo estable"; break;
  case 21:
    return "Buen tiempo"; break;   
  case 22:
    return "Evolucionando a buen tiempo"; break;
  case 23:
    return "Buen tiempo evolucionando a mejor"; break;
  case 24:
    return "Buen tiempo con posibles chubascos a primeras horas"; break;
  case 25:
    return "Chubascos a primeras horas evolucionando a mejor";  break;
  case 26:
    return "Variable evolucionando a mejor"; break;
  case 27:
    return "Inestable a primeras horas evolucionando a estable";  break;  
  case 28:
    return "Inestable con probable mejoría";  break;
  case 29:
    return "Inestable con breves intervalos de buen tiempo"; break;
  case 30:
    return "Muy inestable con intervalos de buen tiempo"; break;
  case 31:
    return "Tormentoso con probable mejoría"; break; 
  case 32:
    return "Tormentoso con mucha lluvia";  break;     
  default:
    return "Tiempo indeterminado";
  }
}