1.3 IoT WiFi Sensor Puerta-Ventana: Archivo.ino

1. Instrucciones en Arduino IDE

Como la versión del ESP8266-01 no dispone de muchos pines de trabajo, se define el uso de los pines como:

  • monitor de operación del dispositivo: LED interno, GPIO1 (TXD)
  • lectura de sensor en GPIO3, pin 7, mismo que es configurado como RXD en modo PROG.

Por el uso en operación de los pines de comunicación Serial (GPIO1 y GPIO3) se descartan las lineas Serial.print() convirtiendolas en comentarios //. La instrucción para encender el LED de monitor también activa para TXD, por lo que de tener conectado la comunicación serial podría mostrar caracteres ilegibles.

El diseño realizado permite conectar un módulo USB-TTL a la placa PCB. Revise la configuración de las botoneras Reset, PROG y los Jumpers para realizar la carga del archivo.ino. Si la subida del archivo.ino al módulo ESP01  se realiza fuera de la placa PCB revise nuevamente la configuración de PCB para que trabaje en modo «Ejecutar» luego de insertar el módulo ESP01.

2. Funciones repetitivas

Para las acciones repetitivas como la conexión a WIFI y comunicación por MQTT se realizan en funciones para simplificar las instrucciones en la configuración inicial (setup) y la ejecución principal (loop).

Al inicio se definen las librerías y los valores para la conexión WIFI y los datos para comunicarse con el servidor MQTT-Mosquitto implementado en el Raspberry. Revisar de ser necesario al sección Broker.

/* ESP8266 Sensor de Puerta. edelros@espol.edu.ec
 *  Para usar, actualice las secciones de:
 *  - WIFI:Router, MQTT:Servidor, MQTT:Dispositivo
 *  ESP-01 al usar GPIO1 y GPIO3,(Tx,Rx), NO USE Serial.print()
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// WIFI: conexión a Router
char* ssid = "xxxx";
char* password = "xxxx";

// MQTT: Servidor
char* MQTT_IP = "192.168.xx.xx";
uint16_t MQTT_puerto = 1883;
char* MQTT_usuario = "usuarioprueba";
char* MQTT_contrasena = "usuarioclave";

// MQTT: Dispositivo Interruptor
char* MQTT_ID = "oficina_puerta1";
char* MQTT_TOPIC = "oficina/puerta1/estado";
char MQTT_SensorEstado[10] = "OFF";
volatile boolean mqtt_desconectado = true;
char* sensor_ON  = "ON";
char* sensor_OFF = "OFF";

// Sensor Interruptor
const uint8_t sensor_pin = 1;
volatile boolean sensor_estado = false;
volatile boolean sensor_bandera = true;

// Actuador LED
volatile boolean actuador_estado = false;
const uint8_t LED_actuador = 2;

// LED monitor //interno: ESP01-pin=1, ESP07-pin=2
const uint8_t LED_pin=0;

// Clientes WiFi y MQTT
WiFiClient wifiClient;
PubSubClient mqttclient(wifiClient);

void setup() {
  // SENSOR Interruptor
  pinMode(sensor_pin, INPUT);
  attachInterrupt(digitalPinToInterrupt(sensor_pin),sensorActivado,CHANGE);
  
  // ACTUADOR LED
  pinMode(LED_actuador, OUTPUT);
  // LED monitor, Enciende en LOW
  pinMode(LED_pin, OUTPUT);

  // conexión WIFI y MQTT
  inicia_wifi();
  if (WiFi.status() == WL_CONNECTED){
    inicia_mqtt();
    }
  }

void loop() {
  // Revisa cambios en interruptor
  if (sensor_bandera){
      delay(10);
      sensor_estado = digitalRead(sensor_pin);
    if (sensor_estado==LOW){
      actuador_estado = true;
      }
    if (sensor_estado ==HIGH){
      actuador_estado = false;
      }
    ACTUADORactivaestado();
    publica_estado();
    sensor_bandera = false;
    }
  yield(); // procesa wifi
  
  if (WiFi.status() != WL_CONNECTED){
    inicia_wifi();
    }else{
    if (mqttclient.connected()==false){
        mqtt_desconectado = true;
        inicia_mqtt(); // reintento
      }
    if (mqttclient.connected()==true){
      if (mqtt_desconectado==true){
        publica_estado();
        mqtt_desconectado=false;
        }
      mqttclient.loop();
      }
    }
  yield(); // procesa wifi
}

// ISR interrupción activada
ICACHE_RAM_ATTR void sensorActivado(){
  sensor_bandera = true;
  }

// Actuador activar estado
void ACTUADORactivaestado(){
  if (actuador_estado){
      // LED actuador ilumina en apagado
      digitalWrite(LED_actuador, HIGH);
    }else{
      digitalWrite(LED_actuador, LOW);
    }

  }

// Publicar el estado del dispositivo
void publica_estado() {
    if (actuador_estado){
      snprintf (MQTT_SensorEstado,10, sensor_ON);
    }else{
      snprintf (MQTT_SensorEstado,10, sensor_OFF);
    }
    if (mqttclient.connected()==true){
      mqttclient.publish(MQTT_TOPIC,MQTT_SensorEstado,true);
    }else{
      mqtt_desconectado = true;
    }
}

void inicia_wifi(){
  int intentos = 10;
  int cuenta = 0;
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  
  while ((WiFi.status() != WL_CONNECTED) && (cuenta<intentos)){
    cuenta = cuenta+1;
    // Parpadeo de Monitor enciende en LOW
    digitalWrite(LED_pin, LOW);
    delay(300);
    digitalWrite(LED_pin, HIGH);
    delay(200);
    }
  }

void inicia_mqtt(){
  int intentos = 2;
  int cuenta = 0;
  
  mqttclient.setServer(MQTT_IP, MQTT_puerto);
  mqttclient.connect(MQTT_ID, MQTT_usuario, MQTT_contrasena);
  
  while (!mqttclient.connected() && (cuenta<intentos)) {
    cuenta = cuenta + 1;
    // Parpadeo de Monitor enciende en LOW
    digitalWrite(LED_pin, LOW);
    delay(200);
    digitalWrite(LED_pin, HIGH);
    delay(200);
    }
  publica_estado();
  }