3. Actuador/Sensor Binario ESP-01

Actuador Binario para controlar un elemento eléctrico AC de baja potencia como elemento complementario a un interruptor de control.

Por ejemplo, una luz iluminación y un interruptor de pared.

El actuador binario responde al interruptor de forma tradicional, sin embargo, al usar el Broker cambiará al estado deseado. El estado del interruptor físico puede volver a usarse para obtener el resultado deseado.

El límite de capacidad del dispositivo está dado por el Relé usado en el circuito.

Premisas para el desarrollo del prototipo, versión 1:

  • Supone que ya se ha implementado un Broker MQTT
  • Dispone de Arduino IDE para cargar las instrucciones en el ESP9266-01
  • Dispone de una base para el desarrollo de dispositivos, verificando funcionamiento de WIFI y MQTT, en formato DIY (Do It Yourself)
  • Identifica otros elementos de desarrollo e inconvenientes para la implementación.
  • Usa diseños abiertos tipo: Open hardware y Open software
  • Usa componentes disponibles en el mercado local.
  • Considera alternativas para los componentes que solo se puedan conseguir por internet
  • Conecta dispositivos por medios inalámbricos.

Para activar el Sensor Binario en la plataforma con Rasberry, consulte la sección de Broker, donde se detallan las instrucciones.


Esquema Propuesto

La alimentación de energía se realiza con 110V AC. La reducción al voltaje de operación del ESP8266-01 se realiza en dos pasos: 5VDC y luego 3.3V DC, considerando la disponibilidad de:

  • Relé con voltaje de operación de 5V DC
  • Regulador de voltaje de 110V a 5 V DC

Se podría simplificar el uso del reductor de voltaje de 5V a 3.3V en caso de disponer en el mercado local de un Relé de 3.3v y de disponer del componente HLK-PM03, que realiza la reducción completa hasta 3.3V.

Como el diseño está realizado en modo DiY (Do it Yourself) para armar, se usaron únicamente los componentes disponibles.

Para la operación del Relé se usó un optoacoplador que permite acoplar la salida digital del ESP8266 con la corriente demandada por la operación del Relé de aproximadamente 10mA.

El optoacoplador opera un transistor que controla la corriente que activa el Relé. La configuración permite acoplar otros Relés con otros voltajes de operación usados para aplicaciones de mayor carga, incluso con fuentes de alimentación se mayor voltaje y separadas del circuito.

Alternativas a componentes

Se comprobó el funcionamiento sustituyendo el regulador de 110VAC a 5V por un cargador USB a 5V de los usado para teléfonos celulares.
Considere que se midieron voltajes aproximados a 5V DC

No fue posible durante la semana de desarrollo obtener localmente un HLK-PM-01 y un regulador DC de 5V a 3.3 V. De se optó por usar diodos para disminuir el voltaje hasta lo requerido.

Otras opciones para 5V a 3.3V:

  • usar diodos Zener de 3.3V
  • conexión de diodos en modo de paso para caídas de 0.7V por cada diodo.

Protoboard

Para probar el circuito se puede armar en un protoboard.
Considere que solo por Esquema se incluye la parte de conexión AC, que se debe realizar separada y tomando las precauciones de aislamiento que correspondan.


Circuito impreso – PCB

Se adjunta la imagen de la placa del circuito impreso realizada con Fritzing en vista superior.

Para el archivo de producción de placa, escribir al email de contacto al final de la página.

Alternativas durante el proceso de desarrollo

Durante el desarrollo del prototipo se usó placas perforadas de circuito impreso de 5×9 cm.

Luego de algunas pruebas, se dispondrá del diseño mejorado y se actualizará la versión 1 del circuito impreso.


Instrucciones Arduino

En éste caso, como la versión del ESP8266-01 no dispone de muchos pines de trabajo, se usa como:

  • monitor de operación del dispositivo al LED interno (pin1 y TX)
  • sensor el pin 3 que también puede ser configurado como RX

Por el uso en operación de los pines de comunicación Serial (pines 1 y 3) se descartan las líneas Serial.print() convirtiéndolas en comentarios //.

A diferencia del modelo usado con el sensor binario, se requiere un pin adicional para la señal del actuador para controlar el Relé. Se seleccionó el PiN 2/GPIO_2 pues la configuración usada no presenta inconvenientes al momento del inicio del dispositivo en el modo requerido de trabajo: GPIO_0 y GPIO_2 en ALTO.

La carga del archivo.ino se la realiza fuera del circuito. Una vez cargado el script se inserta el ESP8266 en la placa.

Las instrucciones para iniciar WIFI y MQTT se realizaron de forma separada en funciones  como base para otros dispositivos.

Para procesar las instrucciones enviadas por el Broker en MQTT se amplía la función callback.

Para el control del Relé se usa la función ACTUADORactivaestado() que realiza acciones semejantes a la de activar el monitor LED, y permite en futuro mantener separadas las acciones sobre el ACTUADOR o Relé.

/*
 TOMACORRIENTE E INTERRUPTOR | AC outlet and wall switch
 Basic ESP8266 MQTT example with the ESP8266 board/library.
 Actuador/Sensor Binario, para control de estado de una Luz.
 Para usar, se debe actualizar las secciones de:
 - WIFI datos para conexión a Router
 - MQTT: Servidor MQTT 
 - MQTT: identificador de dispositivo y topics
 Al usar ESP8266-01 se toman los pines TX para LED y RX para el sensor, GPI02 actuador
 por lo que se no se usa Serial.print(), con mesajes usado para depuración.
*/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// WIFI datos para conexión a Router
const PROGMEM char* ssid = "----";
const PROGMEM char* password = "----";

// MQTT: Servidor MQTT 
const PROGMEM char* MQTT_SERVER_IP = "192.168.x.x";
const PROGMEM uint16_t MQTT_SERVER_PORT = 1883;
const PROGMEM char* MQTT_USER = "username";
const PROGMEM char* MQTT_PASSWORD = "password";

// MQTT: identificador de dispositivo y topics
const PROGMEM char* MQTT_CLIENT_ID = "luz1";
const PROGMEM char* MQTT_SENSOR_TOPIC = "oficina/luz1/contact";
const PROGMEM char* MQTT_SENSOR_COMMAND_TOPIC = "oficina/luz1/switch";
const PROGMEM char* SENSOR_ON  = "ON";
const PROGMEM char* SENSOR_OFF = "OFF";
char MQTT_SENSOR_STATE[10] = "OFF"; // inicializa

// Sensor Switch Luz
const PROGMEM uint8_t SENSOR_pin = 3;
volatile boolean SENSOR_estado = false;
volatile boolean SENSOR_bandera = false;

// Actuador Switch Luz
const PROGMEM uint8_t ACTUADOR_pin = 2;

// LED monitor interno
const PROGMEM uint8_t LED_pin = 1; //ESP01-pin=1

// Control de tiempos
unsigned long antes = 0; 
const long intervalo = 300;

WiFiClient wifiClient;
PubSubClient client(wifiClient);

void setup() {
    // Conexion serial
    // Serial.begin(115200);

    // SENSOR Binario
    pinMode(SENSOR_pin, INPUT);
    attachInterrupt(digitalPinToInterrupt(SENSOR_pin),SensorActivado,CHANGE);
    
    // ACTUADOR Binario
    pinMode(ACTUADOR_pin, OUTPUT);
    digitalWrite(ACTUADOR_pin, HIGH);
    ACTUADORactivaestado();
    
    // LED monitor
    pinMode(LED_pin, OUTPUT);
    LEDactivaestado();
    
    // conexión WIFI y MQTT
    inicia_wifi();
    inicia_mqtt();
}

void loop() {
    if(WiFi.status() != WL_CONNECTED){
        inicia_wifi();
        }
    if (!client.connected()){
        inicia_mqtt();
        }
    client.loop();
    if (SENSOR_bandera){
        SENSOR_estado = digitalRead(SENSOR_pin);
        
        // Serial.println("Actualiza LED");
        LEDactivaestado();
        ACTUADORactivaestado();
        
        // actualiza estado del Sensor en MQTT
        if (SENSOR_estado){
            snprintf (MQTT_SENSOR_STATE,10, SENSOR_ON);
        }else{
            snprintf (MQTT_SENSOR_STATE,10, SENSOR_OFF);
        }
        // Serial.print("Sensor, estado: ");
        // Serial.println(MQTT_SENSOR_STATE);
        
        client.publish(MQTT_SENSOR_TOPIC,MQTT_SENSOR_STATE);
        client.subscribe(MQTT_SENSOR_COMMAND_TOPIC);

        SENSOR_bandera=false;
    }
    delay(10);
}

void inicia_wifi() {
    // conexion WiFi
    //Serial.print("\n Conectando a ");
    //Serial.println(ssid);
    WiFi.begin(ssid, password);
    int cuenta = 0;
    while (WiFi.status() != WL_CONNECTED){
        //Serial.print(".");
        cuenta = cuenta+1;
        if (cuenta>=40){
            //Serial.println();
            cuenta = 0;}
        // LED interno enciende en LOW
        digitalWrite(LED_pin, LOW);
        delay(250);
        digitalWrite(LED_pin, HIGH);
        delay(250);
        }
    //Serial.print("\n WiFi conectado \n Dirección IP: ");
    //Serial.println(WiFi.localIP());
    delay(10);
}

void inicia_mqtt(){
    client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);
    client.setCallback(callback);
    while (!client.connected()) {
        //Serial.println("\n Conectando a MQTT ");
        if (client.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASSWORD)) {
            //Serial.println(" MQTT conectado");  
        } else {
            //Serial.print("Falló, estado: ");
            //Serial.print(client.state()); 
            //Serial.print(" , reintento en 5 segundos");
            // LED interno enciende en LOW
            for (int i=0;i<=5;i=i+1){
                digitalWrite(LED_pin, LOW);
                delay(600);
                digitalWrite(LED_pin, HIGH);
                delay(400);
            }
        }
    }
    client.publish(MQTT_SENSOR_TOPIC, MQTT_SENSOR_STATE);
    client.subscribe(MQTT_SENSOR_COMMAND_TOPIC);
}

// llega mensaje MQTT
void callback(char* p_topic, byte* p_payload, unsigned int p_length) {
    // convierte a cadena
    String payload;
    for (uint8_t i = 0; i ≪ p_length; i++) {
        payload.concat((char)p_payload[i]);
        }
    // analiza mensaje por topico
    if (String(MQTT_SENSOR_COMMAND_TOPIC).equals(p_topic)) {
        if (payload.equals(String(SENSOR_ON))) {
            if (SENSOR_estado != true) {
                SENSOR_estado = true;
                LEDactivaestado();
                ACTUADORactivaestado();
                SENSORpublicaestado();
                }
        } else if (payload.equals(String(SENSOR_OFF))) {
            if (SENSOR_estado != false) {
                SENSOR_estado = false;
                LEDactivaestado();
                ACTUADORactivaestado();
                SENSORpublicaestado();
                }
        }
    }
}

// Publicar el estado del dispositivo
void SENSORpublicaestado() {
    if (SENSOR_estado) {
        client.publish(MQTT_SENSOR_TOPIC, SENSOR_ON, true);
    }else{
        client.publish(MQTT_SENSOR_TOPIC, SENSOR_OFF, true);
    }
    client.subscribe(MQTT_SENSOR_COMMAND_TOPIC);
    
}

// establece estado LED monitor en ESP8266
void LEDactivaestado(){
    if (SENSOR_estado){
        // LED interno enciende en LOW
        digitalWrite(LED_pin, LOW);
    }else{
        digitalWrite(LED_pin, HIGH);
    }
}
// establece estado LED monitor en ESP8266
void ACTUADORactivaestado(){
    if (SENSOR_estado){
        // ACTURADOR ACTIVA EN LOW
        digitalWrite(ACTUADOR_pin, LOW);
    }else{
        digitalWrite(ACTUADOR_pin, HIGH);
    }
}

// ISR interrupción activada
void SensorActivado(){
    // Serial.println("ISR activada");
    unsigned long ahora = millis();
    if((ahora - antes)> intervalo) {
        antes = ahora;
        SENSOR_bandera = true;
    }
}

Temas para desarrollo posterior

Sensores Analógicos
Ampliar la forma de carga de scripts en el tablero, de forma alámbrica o inalámbrica.

Analizar consumos de corriente para uso con baterías.

Revisar el uso de los canales WIFI para evitar desconexiones por saturación de canal.


implementación versión 1

Usando placas perforadas para el prototipo, se controla un tomacorriente que tiene conectada una lámpara de escritorio. El interruptor opera normalmente, en conjunto con el dispositivo.

Todas las partes se integraron en una caja eléctrica sin inconvenientes de espacio.

De implementar la placa del circuito PCB, el espacio usado es menor.

Se usó un circuito de cargador de celular, por disponibilidad inmediata en lugar del HLK-PM-01.