La versión del módulo ESP-07 ofrece más puntos de conexión que la versión ESP-01. Para la implementación básica ser recomienda usar la versión con antena incorporada y una placa para adaptar el módulo.
La placa permite conectarlo a un protoboard, pues la separación entre conectores del módulo es pequeña (2 mm).
Una de las ventajas del ESP-01 es convertidor Analógico-Digital (pin ADC), que tiene un rango de trabajo entre 0 y 1 voltio con pasos valorados entre 0-1023 (10 bits).
El pin ADC permite por ejemplo obtener lecturas de estado de voltaje de las baterías, obtenido con un divisor de voltaje para asegurar que el voltaje máximo no supere 1V .
IDE Arduino
Para incorporar la tarjeta al programa IDE Arduino se se realizan los mismos que para la versión ESP-01, seleccionando la placa ESP8285.
Para usa el módulo, se requiere además de alimentación en VCC a 3.3V y GND conectar los pines de configuración de modo de operación.
Estados de pines de configuración
Los estados de los pines de configuración son ALTO (HIGH) o BAJO(LOW).
El estado ALTO se establece conectar el pin a VCC de 3.3VDC mediante una resistencia de 10KΩ (pullup) para una corriente de activación de 0.033 mA.
El estado Bajo se realiza conectando el pin a GND con 0VDC.
Modo de Operación
Cargar o Ejecutar un programa se establece con estados de voltaje en los pines GPIO0 y GPI02.
GPIO0
GPIO2
CH_PD
RESET
Cargar programa
LOW
HIGH
HIGH
HIGH
Ejecutar Programa
HIGH
HIGH
HIGH
HIGH
Observe que, el módulo ESP-01S, tiene incorporadas las resistencias a estado ALTO (HIGH,pull up), por lo que no es necesario añadirlas en éste caso.
Conexión a 3.3V
La alimentación de energía para el dispositivo es de 3.3V, preferible con una fuente o módulo de 3.3v .
Considere que puede resultar insuficiente si alimenta desde la salida de 3.3V de un módulo USB-Serial con salida de 3.3V o desde el pin Arduino 3.3V.
La falta de energía en el dispositivo se presenta como error en la conexión al intentar subir instrucciones desde el IDE Arduino: "sincronizar la memoria del dispositivo."
Si no dispone de la fuente externa, puede al usar dos dispositivos USB-TTL para:
1. Alimentación (Vcc y GND) 2. Carga de datos (Tx y Rx)
Recuerde unir las referencias de cada dispositivo USB-Serial GND.
Esta es la última sección a realizar, pues se supone que tiene listo el dispositivo, construido y operativas las partes: Dispositivo y Broker.
El objetivo es incorporar dispositivo Interruptor-Tomacorriente en el broker MQTT y observar los resultados.
Se plantea observar los estados del dispositivo en dos formas:
Desde un navegador en la página local de Home-Assistant
Desde una consola conectando al servidor MQTT
1. Incorporar el dispositivo en Home Assistant
Se requiere modificar el archivo configuration.yaml en el raspberry.
Se puede realizar en forma local desde el raspberry que tiene monitor, teclado y mouse conectado, y editar el archivo que se encuentra en el directorio:
La otra forma es conectarse via remota por medio de una sesión ssh. Requiere dirección, usuario y password. Los detalles se dan en la sección Raspberry.
En el archivo se añade los datos del dispositivo interruptor-tomacorriente, que en el caso actual para pruebas se identifica como una luminaria (light).
El sensor trabaja con MQTT, se le asigna un nombre más sencillo de reconocer como «oficina luz 1» y se complementa con la instrucción de identificación en el formato: lugar/cosa/acción.
En el caso de control del actuador, se utiliza una intruccion semejante para publicar:
mosquitto_pub -h 192.168.10.100 -t oficina/luz1/cambia -m on
Dispositivo como interruptor
Se aplica el mismo concepto del dispositivo para el caso de un interruptor, no necesariamente de luz. Para el caso de interruptor, hay que observar la capacidad máxima de manejo de corriente del Relay usado, para evitar sobrecargas.
Como ejemplo, se presenta el formato para interruptor en Home-Assistant, lo que requiere también realizar un cambio en el archivo.ino en la sección MQTT. Sin embargo no afecta al resto de las instrucciones.
Como la versión del ESP8266-01 no dispone de muchos pines de trabajo, se define el uso de los pines como:
Lectura del sensor interruptor en GPIO1, que también es TXD configurado (setup) como entrada (INPUT).
Control actuador con relay en GPIO3, que también es RXD configurado en modo de salida (OUTPUT).
Monitor de operación del dispositivo: LED actuador GPIO2
Monitor de conexión a la red: LED conexión GPIO0
Por el uso en operación de los pines de comunicación Serial (GPIO1 y GPIO3) se descartan las lineas Serial.print().
Si la subida del archivo.ino al módulo ESP01 se realiza fuera de la placa PCB. Si el diseño realizado permite conectar un módulo USB-TTL a la placa PCB. Revise la configuración de las botoneras Reset, PROG o DIP-switch para realizar la carga del archivo.ino.
2. Funciones repetitivas
La conexión a WIFI y comunicación por MQTT al ser repetitivas entre algoritmos se separan en funciones, simplificando la configuración inicial (setup) y el bloque 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 la sección "Broker".
2.1 función para actuador
Para procesar las instrucciones enviadas por el broker MQTT se dispne de la función callback().
Para el control del Relé se usa la función ACTUADORactivaestado().
2.2 Función para sensor
Para monitorear sensor se usa una interrupción para sensar cambios de estado. Por el control de rebotes, se considera los intervalos entre cambios implementado en la función SensorActivado(). De confirmarse el cambio se pasa a publicar el estado en el broker MQTT con SENSORpublicaestado()
/* ESP8266 Interruptor AC.
* edelros@espol.edu.ec
* Sensor-Actuador Binario,
* control de un Relay con Tomacorriente o foco.
* 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_luz1";
char* MQTT_TOPIC = "oficina/luz1/estado";
char* MQTT_COMMAND = "oficina/luz1/cambia";
char MQTT_SensorEstado[10] = "OFF";
char MQTT_ActuadorEstado[10] = "OFF";
volatile boolean mqtt_desconectado = true;
char* sensor_ON = "ON";
char* sensor_OFF = "OFF";
// Actuador Tomacorriente-Luz
const uint8_t actuador_pin = 3;
volatile boolean actuador_estado = false;
// Sensor Interruptor
const uint8_t sensor_pin = 1;
volatile boolean sensor_estado = false;
volatile boolean sensor_bandera = true;
// LED monitor //interno: ESP01-pin=1, ESP07-pin=2
const uint8_t LED_pin=0;
const uint8_t LED_actuador = 2;
// Clientes WiFi y MQTT
WiFiClient wifiClient;
PubSubClient mqttclient(wifiClient);
void setup() {
// SENSOR Interruptor
pinMode(sensor_pin, INPUT);
attachInterrupt(digitalPinToInterrupt(sensor_pin),sensorActivado,CHANGE);
// ACTUADOR Tomacorriente
pinMode(actuador_pin, OUTPUT);
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){
// ACTUADOR ACTIVA EN LOW
// LED actuador ilumina en apagado
digitalWrite(actuador_pin, LOW);
digitalWrite(LED_actuador, HIGH);
}else{
digitalWrite(actuador_pin, HIGH);
digitalWrite(LED_actuador, LOW);
}
}
// Publicar el estado del dispositivo
void publica_estado() {
if (actuador_estado){
snprintf (MQTT_ActuadorEstado,10, sensor_ON);
}else{
snprintf (MQTT_ActuadorEstado,10, sensor_OFF);
}
if (mqttclient.connected()==true){
mqttclient.publish(MQTT_TOPIC,MQTT_ActuadorEstado,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);
mqttclient.setCallback(callback);
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();
mqttclient.subscribe(MQTT_COMMAND);
}
// llega mensaje MQTT
void callback(char* p_topic, byte* p_payload, unsigned int p_length) {
// convierte a texto
String payload;
for (uint8_t i = 0; i < p_length; i++) {
payload.concat((char)p_payload[i]);
}
// revisa mensaje por topico
if (String(MQTT_COMMAND).equals(p_topic)) {
if (payload.equals(String(sensor_ON))) {
if (actuador_estado != true) {
actuador_estado = true;
}
}
if (payload.equals(String(sensor_OFF))) {
if (actuador_estado != false) {
actuador_estado = false;
}
}
ACTUADORactivaestado();
publica_estado();
}
}
El dispositivo inalámbrico se usa para controlar el estado encendido o apagado (actuador) de un aparato eléctrico AC (lámpara) de baja potencia.
El control se lo puede realizar físicamente al pulsar un interruptor tradicional (sensor) o por medio de una instrucción MQTT.
El sensor de interruptor y el actuador de control AC trabajan en conjunto desde el mismo dispositivo. Éste dispositivo es la integración de los dos dispositivos anteriores: Sensor Puerta-Ventana y Actuador tomacorriente, ambos de estado binario (ON/OFF).
implementación versión 1
La versión 1 mostrada en la imagen se ha instalado en una caja sobrepuesta plástica. Para pruebas, se ha conectado una lámpara al tomacorriente.
El control se realiza tanto por el interruptor como por la página en la computadora, ambos marcados en rojo en la imagen.
La carga máxima AC de control depende del Relé seleccionado.
Se ha usado una placa perforada para ensamblar el prototipo, sin embargo al final del tema en Placas PCB se presenta el diseño de la placa de circuito.
Premisas para desarrollo en la versión 1
Diseño de dispositivos con conexión inalámbrica WIFI
Conoce los datos para conexión a la red a WIFI y broker MQTT
Dispone de acceso a un broker MQTT local
Dispone de Arduino IDE para cargar las instrucciones en el ESP8266
Emplea diseños abiertos tipo: Open Hardware y Open Software
Dispone de los componentes en el mercado local
Considera componentes alternos a los no disponibles en el mercado local
Identifica las etapas de desarrollo e inconvenientes en la implementación
Temas para desarrollo posterior
Incorporar Sensor para medir consumo de energía.
Sensores Analógicos Ampliar la forma de carga de scripts en el tablero, de forma alámbrica o inalámbrica.
Revisar el uso de los canales WIFI para evitar desconexiones por saturación de canal.
2. Esquemático con ESP01
El esquemático se divide en varias secciones mostradas en la figura y descritas a continuación.
2.1 Sensor
El sensor es un interruptor eléctrico de pared ensamblado en conjunto con un toma corriente controlado por el actuador.
Se puede sensar el estado de encendido o apagado, o los cambios de estado de subida (0 a 1) o bajada (1 a 0).
El interruptor se usa como sensor, por lo que no va conectado a la energía AC.
Considere cambiar a un pulsador que podría resultar más económico, pero habría que adaptarlo al conjunto de caja y tapa eléctrica usada.
2.2 Actuador
Para controlar el estado de un toma-corriente y la carga conectada se usa un relé. El actuador es muy semejante a lo usado en el dispositivo de solo toma-corriente.
La capacidad de carga del relé determina la capacidad de carga en Amperios del dispositivo, para el prototipo se usa el más básico de los relés controlados por 5 VDC y contactor a 110VAC nominalmente a 10A. No se usará la capacidad máxima del relé.
Para la operación del Relé se usa 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.
2.3 Controlador
El pin para el actuador es GPIO3, RXD, que también se usó con el sensor magnético de puerta -ventana, configurado como salida (OUTPUT).
El pin para el sensor es GIPO1, TXD, configurado como entrada (INPUT).
Centrado en ESP8266-01 se requiere un conector para el sensor y otro para el actuador.
Se usa un LED monitor para el estado del interruptor/actuador en GPIO2 y un LED monitor para mostrar el estado durante conexión a la red en GIPO0. El diseño considera mantener GPIO0 y GPIO2 en el estado ALTO al inicio del dispositivo, luego establecer el modo de salida (OUTPUT, INPUT) en las instrucciones de configuración (setup()).
La activación del módulo se realiza de acuerdo a lo descrito en el manual del módulo. Revisar en la sección «Módulos» ESP8266 versión ESP-01.
La placa del circuito permite solo el estado de operación del ESP-01, la programación del módulo ESP-01 se debe realizar fuera del tablero. Revise la opción de programar con la "Conexión USB-TTL".
2.4 Fuente DC
Conformada por el Regulador d 110VAC a 5VDC, y el Regulador de 5VDC a 3.3VDC usando el módulo AMS1117.
Los componentes usados o sus sus componentes alternos se describen en la sección de Fuentes de Alimentación para Módulos.
2.5. Ensamble en Protoboard
Para probar el circuito se ensambla en un protoboard teniendo como guía el diagrama del circuito del punto anterior
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.
2.6. Circuito impreso – PCB
El diseño se ha realizado en dos placas por flexibilidad de ensamble. La placa de fuente de alimentación se puede reemplazar por un cargador USB, conectando a la primera placa del dispositivo a los conectores +5VDC-.
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 5x7 cm.
2. WiFi Tomacorriente: Esquemático ESP01-Config
También posible construir una placa con los elementos necesarios para controlar el modo de operación del Módulo ESP-01 por medio de un DIP-Switch:
Modo Operación: DIP-switch en 0111
Modo Programación: DIP-Switch en 1000
La operación es semejante al presentado en ésta sección, la diferencia es que no se requiere retirar el ESP01 de la placa. De ésta manera no se requiere retirar el módulo ESP-01 de la placa para realizar la carga del archivo.ino con la programación con un USB-TTL.
2.1 Esquemático con ESP01
2.2 Ensamble en Protoboard
2.3 Circuito impreso – PCB
2.4 Implementación en Placa perforada
Realizado para verificar las dimensiones y espacio usados en el diseño de la PCB. La versión es previa a la mostrada en la sección 3.
En el esquema abierto, los mensajes de estado/acción con MQTT se administran (pub/sub) bastante bien con Mosquitto.
Cada mensaje genera un dato de estado, que con el transcurrir el tiempo podría ser revisado mediante las estadísticas de uso o pretender realizar acciones sobre los artefactos ante una secuencia de estados predeterminados, realizar una presentación en una página web. Estos nuevos requerimientos implican una mayor integración en software.
Entre las versiones de software abierto para la gestión de los mensajes de estado/acción se encuentra Home Assistant, que junto a Mosquitto presentan una solución bastante aceptable de operar y personalizar.
Home-Assistant se suscribe a MQTT- Mosquitto y realiza la gestión de datos, para por ejemplo presentarla en una página web. La presentación puede ser como texto o de forma gráfica.
El acceso web se basa en la dirección IP del broker en el puerto 8123, también es valida el nombre de la maquina en la red (ej: miComputadorIoT:8123),
El proceso de instalación y configuración de Home-Assistant se detalla en la sección de Broker/Gestión, donde se detalla la conexión a MQTT de forma abierta, con validación de usuario y password, finalmente con SSL/TLS.
Esta sección se centra en la conexión de un dispositivo y la configuración de los parámetros del mensaje MQTT. Se supondrá que tiene ya configurado el servicio en algún "servidor/broker" con Raspberry Pi o en PC.
La configuración básica de un dispositivo se realiza en el archivo configuration.yaml que se puede editar desde una consola ssh con la instrucción:
donde se añaden los parámetros de cada dispositivo, sus propiedades, formas de presentación, etc.
Por ejemplo, para observar el estado o valor del mensaje MQTT del tema "oficina/mensaje" es necesaria una suscripción al mosquitto. Se asume que ya se han realizado las pruebas de conectividad, por lo que para añadir el dispositivo y sus propiedades al archivo se añade:
Reinicie Home Assistant en el menú de Configuración/Controles del Servidor. Recuerde siempre validar el cambio de configuración antes de reiniciar Home-Assistant. En la pagina de resumen de Home Assistant se obtendrá el estado del dispositivo.
Los certificados a usar corresponden al certificado de la autoridad y del servidor mqtt.
Para el certificado de la autoridad mqtt-ca.crt se usa el contenido del archivo abierto como texto.
El certificado del servidor mqtt-srv se usa en formato reducido de fingerprint, obtenido con la instruccion descrita anteriormente en la sección mosquitto TLS.
Para usar los componentes de WifiClient y PubsubClient se requiere añadir los detallas de los certificados, por lo que se sustituyen las línea como se muestra:
En la sección de inicio de MQTT se añaden las partes para que tome en cuenta los certificados al momento de realizar la conexión por Wifi
// Configura cliente TLS
// añade CA cert en los sitios de confianza
wificlient.setTrustAnchors(&caCertX509);
// Habilita self-signed cert
wificlient.allowSelfSignedCerts();
// añade fingerprint para validar conexión
wificlient.setFingerprint(mqttCertFingerprint);
El resto de las instrucciones se mantienen iguales al proceso anterior.
Ejemplo: Parpadea LED
/* ESP8266 Sensor Parpadea. edelros@espol.edu.ec * con SSL/TLS, 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<WiFiClientSecure.h>#include<PubSubClient.h>// WIFI: conexión a Routerchar* ssid = "miRouter";
char* password = "miRouterclave";
// MQTT: Servidorchar* MQTT_IP = "192.168.10.40";
uint16_tMQTT_puerto = 8883;
char* MQTT_usuario = "usuarioprueba";
char* MQTT_contrasena = "usuarioclave";
// MQTT: Dispositivochar* MQTT_ID = "sensor01";
char* MQTT_TOPIC = "oficina/mensaje";
charMQTT_SensorEstado[10] = "OFF";
// Certificados TLS: Certificate AuthorityconstcharcaCert[] PROGMEM = R"EOF(-----BEGIN CERTIFICATE-----MIIDRzCCAi+gAwIBAgIUMtlZSXzSZfHpBI0vrnxdLrQuNgwwDQYJKoZIhvcNAQEL
.......// ........
OpA6IPNIHmDSSPxgejZq4booviVKro2/M++iOUuGj1jkjR6XSQ6x1JgK0DVyiBtD4od+M4mYk7gz/CHgl1JEsTVPyUZK4OO/oxC7-----ENDCERTIFICATE-----
)EOF";// MQTT: cert SHA1 fingerprintconstuint8_tmqttCertFingerprint[] = {0x19,0x50,0x25,0x2C,0xD8,0x6A,0x54,0xE6,0xBC,0x8B,0xA4,0x5F,0x76,0x3F,0xD0,0x7D,0xE0,0x5F,0x7C,0x6C};
// Sensor constuint8_tsensor_pin = 1;
volatilebooleansensor_estado = false;
// LED monitor interno: ESP01-pin=1, ESP07-pin=2constuint8_tLED_pin = 2;
// Mensajes por Puerto Serialvolatilebooleanserial_msg = true;
// Clientes WiFi y MQTT//WiFiClient wificlient;// PubSubClient mqttclient(wificlient);// X.509 parsed CA Cert X509ListcaCertX509(caCert);
// Secure client connection classWiFiClientSecurewificlient;
// MQTT: Client connectionPubSubClient mqttclient(wificlient);
voidsetup() {
if (serial_msg){
Serial.begin(74880);//74880, 115200while (!Serial){delay(50);}
Serial.println("inicia setup");
}
// LED monitor, Enciende en LOWpinMode(LED_pin,OUTPUT);
// conexión WIFI y MQTTinicia_wifi();
if (WiFi.status() == WL_CONNECTED){
inicia_mqtt();
}
}
voidloop() {
// Parpadea estado de sensorif (sensor_estado==true){
sensor_estado = false;
}else{
sensor_estado = true;
}
// LED Monitor Parpadea, enciende en LOWif (sensor_estado ==true) {
digitalWrite(LED_pin,LOW);
delay(1000); // un segundo
}
if (sensor_estado ==false) {
digitalWrite(LED_pin,HIGH);
delay(1000);
}
if (WiFi.status()==WL_CONNECTED) {
publica_estado();
}
//Revisa estado de Wifi o reintenta conexión if (WiFi.status() != WL_CONNECTED){
inicia_wifi();
}else{
if (mqttclient.connected()==false){
inicia_mqtt(); // reintento
}
if (mqttclient.connected()==true){
mqttclient.loop();
}
}
yield(); // procesa wifi
}
sección de inicio MQTT completa:
void inicia_mqtt() {
int intentos = 5;
int cuenta = 0;
// Configura cliente TLS
// añade CA cert en los sitios de confianza
wificlient.setTrustAnchors(&caCertX509);
// Habilita self-signed cert
wificlient.allowSelfSignedCerts();
// añade fingerprint para validar conexión
wificlient.setFingerprint(mqttCertFingerprint);
mqttclient.setServer(MQTT_IP, MQTT_puerto);
mqttclient.connect(MQTT_ID, MQTT_usuario, MQTT_contrasena);
//mqttclient.setCallback(callback);
if (serial_msg){
Serial.print(" MQTT Conectando a ");
Serial.println(MQTT_IP);
}
while (!mqttclient.connected()&&(cuenta<=intentos)){
cuenta = cuenta+1;
// LED Monitor parpadeo MQTT, enciende LOW
digitalWrite(LED_pin, LOW);
delay(600);
digitalWrite(LED_pin, HIGH);
delay(400);
if (serial_msg){
Serial.print(".");
}
}
// Si conectado, inicializa estado
if (mqttclient.connected()){
publica_estado();
}
if (serial_msg){
//Fin de "...."
Serial.println();
Serial.print("; MQTT Conectado: ";);
Serial.println(mqttclient.connected());
Serial.print("; MQTT Estado: ";);
Serial.println(mqttclient.state());
}
}
sección de publicación MQTT es igual que en el ejercicio que le precede
// Publicar el estados del dispositivo
void publica_estado() {
// formato para envio (Texto)
if (sensor_estado == true ){
snprintf(MQTT_SensorEstado,10, "ON");
}else{
snprintf(MQTT_SensorEstado,10, "OFF");
}
// publicar estados
if (mqttclient.connected()==true) {
mqttclient.publish(MQTT_TOPIC,MQTT_SensorEstado,true);
}
if (serial_msg){
if (mqttclient.connected()==true) {
Serial.println(MQTT_SensorEstado);
}
if (mqttclient.connected()==false) {
Serial.println("MQTT desconectado");
}
}
}
sección de inicio de Wifi es igual que en el ejercicio que le precede.
void inicia_wifi(){
int intentos = 10;
int cuenta = 0;
if (serial_msg){
Serial.print(" WIFI Conectando a ");
Serial.println(ssid);
}
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while ((WiFi.status() != WL_CONNECTED) && (cuenta < intentos)){
if (serial_msg){
Serial.print(".");
}
cuenta = cuenta+1;
// Parpadeo de Monitor enciende en LOW
digitalWrite(LED_pin, LOW);
delay(300);
digitalWrite(LED_pin, HIGH);
delay(200);
}
if (serial_msg){
Serial.println(); //Fin de "..."if (WiFi.status() == WL_CONNECTED){
Serial.print(" Estado: ");
Serial.println(WiFi.status());
Serial.print(" MAC: ");
Serial.println(WiFi.macAddress());
Serial.print(" IP: ");
Serial.println(WiFi.localIP());
Serial.print(" RSSI: ");
Serial.println(WiFi.RSSI());
Serial.println();
}
if (WiFi.status() != WL_CONNECTED){
WiFi.printDiag(Serial);
Serial.println();
}
}
}
Para esta sección se supone que ha establecido la conexión a la red WiFi y dispone de un un servidor/broker MQTT de pruebas, semejante a lo realizado en las secciones anteriores.
1. Bloque de inicio
Para MQTT se incluye la libreria PubSubClient.h para la activación de un cliente sobre WiFi. como se indica en las intrucciones siguientes:
Para el bloque de configuración setup() se verifica el estado de la conexión WiFi antes del intento de conexión al broker MQTT-Mosquitto.
// conexión WIFI y MQTT
inicia_wifi();
if (WiFi.status() == WL_CONNECTED){
inicia_mqtt();
}
El proceso inicia_mqtt() se establecen los párámetros de servidor, identificación de usario, conexión y la primera actualización de estado con pub/sub que corresponda.
3. Procedimientos MQTT
Se usa el procedimiento de inicio de conexión y de publicación de estados con sensores. En el caso de actuador se añade el proceso de recepción de mensajes en el dispositivo (callback)
3.1 Procedimiento inicia_mqtt()
Con los parámetros del broker y dispositivo se establece la conexión con el servidor (setServer(), connect()).
Se tiene un periodo de espera mientras se parpadea el led y se presenta un punto en el puerto serial. En caso de que se verifica conexión se publica el estado inicial del sensor antes de volver al bucle de operación.
voidinicia_mqtt(){intespera=5;intcuenta=0;mqttclient.setServer(MQTT_IP,MQTT_puerto);mqttclient.connect(MQTT_ID,MQTT_usuario,MQTT_contrasena);//mqttclient.setCallback(callback);if(serial_msg){Serial.print(" MQTT Conectando a ");Serial.println(MQTT_IP);}while(!mqttclient.connected()&&(cuenta<=espera)){cuenta=cuenta+1;// LED Monitor parpadeo MQTT, enciende LOWdigitalWrite(LED_pin,LOW);delay(600);digitalWrite(LED_pin,HIGH);delay(400);if(serial_msg){Serial.print(".");}}// Si conectado, inicializa estadoif(mqttclient.connected()){publica_mqtt();}if(serial_msg){//Fin de "...."Serial.println();Serial.print(" MQTT Conectado: ");Serial.println(mqttclient.connected());Serial.print(" MQTT Estado: ");Serial.println(mqttclient.state());}}
Se añaden algunos mensajes de estado hacia el computador como parte del proceso de depuración en la etapa de desarrollo y programación.
El resultado de esta subrutina en la pantalla "monitor_serie" es;
inicia setup
WIFI Conectando a miRouter
.......
Estado: 3
MAC: 2C:3A:E8:0A:98:66
IP: 192.168.10.11
RSSI: -56
MQTT Conectando a 192.168.10.50
OFF
MQTT Conectado: 1
MQTT Estado: 0
ON
OFF
ON
OFF
ON
OFF
....
OFF
ON
MQTT desconectado
MQTT Conectando a 192.168.10.50
.....
Como una prueba de funcionamiento, al final se muestra el resultado al desconectar el cable del servidor MQTT.
Estos parámetros se deben actualizar para cada dispositivo específico a desarrolar.
Los valores para mqttclient.state() que se pueden obtener son:
-4 : MQTT_CONNECTION_TIMEOUT - the server didn't respond within the keepalive time
-3 : MQTT_CONNECTION_LOST - the network connection was broken
-2 : MQTT_CONNECT_FAILED - the network connection failed
-1 : MQTT_DISCONNECTED - the client is disconnected cleanly
0 : MQTT_CONNECTED - the client is connected
1 : MQTT_CONNECT_BAD_PROTOCOL - the server doesn't support the requested version of MQTT
2 : MQTT_CONNECT_BAD_CLIENT_ID - the server rejected the client identifier
3 : MQTT_CONNECT_UNAVAILABLE - the server was unable to accept the connection
4 : MQTT_CONNECT_BAD_CREDENTIALS - the username/password were rejected
5 : MQTT_CONNECT_UNAUTHORIZED - the client was not authorized to connect
La publicación de estados se realiza como una subrutina, en el ejemplo es solo encendido y apagado de un LED
// Publicar el estados del dispositivovoidpublica_mqtt(){// formato para envio (Texto)if(sensor_estado==true){snprintf(MQTT_SensorEstado,10,"ON");}else{snprintf(MQTT_SensorEstado,10,"OFF");}// publicar estadosif(mqttclient.connected()==true){mqttclient.publish(MQTT_TOPIC,MQTT_SensorEstado,true);}if(serial_msg){if(mqttclient.connected()==true){Serial.println(MQTT_SensorEstado);}if(mqttclient.connected()==false){Serial.println("MQTT desconectado");}}}
4. Instrucciones Arduino
Las instrucciones usadas para que el estado del parpadeo de un LED se transmita al broker MQTT se incluyen en para la parte principal en la pestaña principal.
/* ESP8266/ESP32 Sensor LED Parpadea. * edelros@espol.edu.ec * Actualice: WIFI:Router, MQTT:Servidor, MQTT:Dispositivo * ESP-01, NO USE Serial.print()*/// detectar placa al compilar# ifdefdefined(ESP8266)#include<ESP8266WiFi.h># elifdefined(ESP32)#include<WiFi.h># endif#include<PubSubClient.h>// Clientes WiFi y MQTTWiFiClientwificlient;PubSubClientmqttclient(wificlient);// WIFI: conexión a Routerchar*ssid="miRouter";char*password="miRouterClave";// MQTT: Servidorchar*MQTT_IP="192.168.10.50";uint16_tMQTT_puerto=1883;char*MQTT_usuario="usuarioprueba";char*MQTT_contrasena="usuarioclave";// MQTT: Dispositivochar*MQTT_ID="Dispositivo";char*MQTT_TOPIC="oficina/mensaje";charMQTT_SensorEstado[10]="OFF";booleanmqtt_desconectado=true;// Sensor constuint8_tsensor_pin=1;volatilebooleansensor_estado=false;// LED monitor interno: ESP01-pin=1, ESP07-pin=2constuint8_tLED_pin=2;// Mensajes por Puerto Serialvolatilebooleanserial_msg=true;voidsetup(){if(serial_msg){Serial.begin(115200);//74880, 115200while(!Serial){delay(50);}Serial.println("inicia setup");}// LED monitor, Enciende en LOWpinMode(LED_pin,OUTPUT);// conexión WIFI y MQTTinicia_wifi();if(WiFi.status()==WL_CONNECTED){inicia_mqtt();}}voidloop(){// Parpadea estado de sensorif(sensor_estado==true){sensor_estado=false;}else{sensor_estado=true;}// LED Monitor Parpadea, enciende en LOWif(sensor_estado==true){digitalWrite(LED_pin,LOW);delay(1000);// un segundo}#ifdefdefined(ESP8266)yield();// procesa wifi#endifif(sensor_estado==false){digitalWrite(LED_pin,HIGH);delay(1000);}if(mqttclient.connected()==true){publica_mqtt();}//Revisa estado de Wifi o reintenta conexión if(WiFi.status()!=WL_CONNECTED){inicia_wifi();}else{if(mqttclient.connected()==false){inicia_mqtt();// reintento}if(mqttclient.connected()==true){mqttclient.loop();}}#ifdefdefined(ESP8266)yield();// procesa wifi#endif}
Si no se ha implementado el broker MQTT solo obtendrá mensajes de "MQTT desconectado".
Al final, recuerde añadir los otros procedimientos inicia_wifi(), inicia_mqtt(), publica_mqtt().
voidinicia_wifi(){intespera=10;// >=10 para conectarintcuenta=0;// mensajes por serial activadoif(serial_msg){Serial.print(" WIFI Conectando a ");Serial.println(ssid);}WiFi.mode(WIFI_STA);WiFi.begin(ssid,password);while((WiFi.status()!=WL_CONNECTED)&&(cuenta<espera)){cuenta=cuenta+1;// Parpadeo de Monitor enciende en LOWdigitalWrite(LED_pin,LOW);delay(300);digitalWrite(LED_pin,HIGH);delay(200);if(serial_msg){Serial.print(".");}}//activado mensajes por serialif(serial_msg){Serial.println();//Fin de "..."if(WiFi.status()==WL_CONNECTED){Serial.print(" Estado: ");Serial.println(WiFi.status());Serial.print(" MAC: ");Serial.println(WiFi.macAddress());Serial.print(" IP: ");Serial.println(WiFi.localIP());Serial.print(" RSSI: ");Serial.println(WiFi.RSSI());Serial.print(" Canal: ");Serial.println(WiFi.channel());Serial.println();}if(WiFi.status()!=WL_CONNECTED){WiFi.printDiag(Serial);Serial.println();}}}
Para probar el funcionamiento de un dispositivo con mensajes MQTT se requiere disponer de un broker MQTT.
El ejercicio de Parpadeo LED, con validación de usuario y contraseña, presenta la recepción de los mensajes MQTT de la siguiente forma:
pi@raspberry:~ $ mosquitto_sub -d -t "oficina/mensaje" -u "usuarioprueba" -P "usuarioclave"
oficina/mensaje ON
oficina/mensaje OFF
oficina/mensaje ON
oficina/mensaje OFF
oficina/mensaje ON
oficina/mensaje OFF
oficina/mensaje ON
oficina/mensaje OFF
oficina/mensaje ON
Se propone disponer de uno usando Mosquitto instalado en un Raspberry Pi para todo lo que se presenta en el Blog.
Sin embargo, si se está iniciando y no se dispone de todo o el acceso a un laboratorio, también es posible tener uno instalado en una pc.
Mosquitto es open source y se puede descargar para instalarlo en varias plataformas.
La descripción en detalle para Raspberry Pi se encuentra en la sección:
Para que el servicio MQTT-Mosquitto esté activo se utiliza la aplicación "Servicios" de "Windows.
busque la aplicación con el botón de búsqueda de Windows:
Con la aplicación de servicios, localice el servicio "Mosquitto-Broker". Para establecer el estado puede usar las propiedades, con "click derecho" del mouse.
Establezca el inicio en modo "manual", solo si va a utilizar el programa como pruebas, sino en "automático" para que siempre esté activo. Luego proceda con el botón de "iniciar"
1.2 Verificar el servicio "Mosquitto-Broker"
Las instrucciones anteriores habilitan y permiten observar que el servicio "Mosquitto-Broker" se encuentra "En ejecución".
También se puede comprobar el funcionamiento usando una ventana "Símbolo de sistema" y la instrucción:
netstat -an
Observando que el puerto 1883 se encuentra en modo "LISTENING", esperando que lleguen los mensajes al broker.
1.3 Pruebas de operación
Para probar la mensajería, se requieren dos ventanas de "símbolo de sistema". La primera para "escuchar" los mensajes (sub) y la segunda para "enviar" los mensajes (pub).
En una ventana de comando, se suscribirse a un tópico ejemplo, para recibir los mensajes:
mosquitto_sub -v -t "oficina/mensaje"
en otra ventana publicar un nuevo estado en el tópico:
Si el resultado es semejante al mostrado en la imagen del ejemplo, MQTT se encuentra funcionando correctamente y listo para enviar y recibir mensajes desde un dispositivo.
1.4 archivo de configuración en Windows
La configuración de MQTT se realiza en el archivo mosquitto.conf que se encuentra en c:\program files\mosquitto\
Recuerde que al cambiar la configuración debe reiniciar el servicio para que se apliquen los cambios.
Puede proceder con otras acciones dadas en la sección "Broker/Gestión"/MQTT-Mosquito, semejante lo mostrado en el siguiente tema
MQTT (Message Queing Telemetry Transport) es un protocolo de comunicación entre máquinas (M2M) ligero y simplificado que sirve para comunicar estados o acciones de los dispositivos.
Una vez conectado el dispositivo a la red WiFi (sección anterior), el siguiente paso consiste en enviar los mensajes de estado, o recibir las instrucciones de acción que son llamados los mensajes MQTT.
Estado
Acción
encendido/apagado
encender/apagar
ON / OFF
1/0
26° C
bajar a 26° C
Para administrar los mensajes de requiere servidor que opere como oficina de correos, también llamado "broker".
El 'broker' recibe los mensajes publicados por los dispositivos (pub) y los re-envía a los destinatarios o suscriptores (sub) conectados al servicio de mensajería.
El broker MQTT seleccionado para el ejercicio es Mosquittopor ser de tipo "open source". El broker se puede implementar en un equipo servidor e incluso en una laptop con objetivos de pruebas básicas.
2. MQTT - Protocolo
Los mensajes MQTT en los dispositivos tienen dos tipos de procesos:
Publicación o envío de mensajes de estado (pub)
Suscripción o recepción de mensajes de estado (sub)
Por ejemplo, para anunciar el cambio de estado de una puerta como abierta o cerrada usando un sensor se realiza la acción de publicación hacia un broker.
3. MQTT - Parámetros de comunicación
Un mensaje MQTT tiene elementos semejantes a un correo electrónico. Para mostrar la semejanza, se usa como ejemplo un mensaje con la acción de apagar una lámpara de la oficina en la siguiente tabla.
correo electrónico
MQTT
De:
Juan
Dispositivo/MQTT_ID:
lampara01
Para:
María
Broker/puerto:
192.168.10.50:1883
Asunto:
lámpara de oficina
tópico:
'oficina/lampara'
Mensaje:
Apagar por favor, la dejé encendida
estado/acción:
'OFF'
Los elementos del mensaje en el esquema IoT y MQTT se muestran sobre el esquema IoT para el caso del sensor en una puerta. Se observa la forma de identificar cada elemento en cada componente o capa del modelo IoT.
Semejante a la conexión de WiFi hacia el Router, en MQTT se requiere disponer de los datos de un "administrador de mensajes" o "broker MQTT", que lo identifiquen en la red y a la vez también algún medio de control de uso como usuario y contraseña.
Parámetro
valor
dirección IP
192.168.10.50
puerto
1883
usuario
usuarioprueba
contraseña
usuarioclave
El broker MQTT además de identificarse por la dirección IP y usa un número de puerto para identificar también el servicio, pues pueden existir otros procesos en el mismo "servidor". El puerto básico es 1883, en el caso que se use encriptación de mensajes por TLS/SSL el puerto cambia a 8883.
En el ejemplo, se presentan valores que deben ser actualizados con los datos correspondientes a la configuración del broker que esté usando.
El dispositivo también debe ser identificado para el mensaje, teniendo como parámetros complementarios el identificador MQTT_ID.
Otro parámetro es el tema o tópico (MQTT_TOPIC) que también se usa para ubicar el dispositivo en un entorno o área y una variable de estado o acción separada mediante una barra de división "/".
El estado del dispositivo o valor de sensor se establece en una variable MQTT_Estado.
Para el proceso también se puede usar una bandera de conectado o desconectado, para determinar si es posible enviar el mensaje sobre la red de datos.
En la práctica un dispositivo podría disponer de uno o mas sensores y/o actuador. Por ejemplo el sensor DHT11 entrega valores de temperatura y humedad, y disponer de un interruptor relé para encender o apagar un foco. En estos casos sería necesario distinguir varios tópicos o estados para el dispositivo.
4. Esquema de instrucciones por Bloques
En el esquema de instrucciones por bloques para el dispositivo se requiere añadir algunas partes para operar con MQTT. El mensaje MQTT viaja sobre una red de datos como WiFi, por lo que es necesario haber completado la parte de conexión a Wifi descrita en la sección anterior.
4.1 Bloque de inicio
Los procesos para mensajería con MQTT se pueden manejar con la librería es PubSubClient.h que se añade en el gestor de librerías del IDE.
Revise que se encuentre disponible en el menú de programa/incluir librería/gestor de librerías, de no ser así, aparece el botón de instalar en la ventana de la figura.
Con lo que se puede incluir la librería y los proceso para establecer un cliente en el broker MQTT.
#include<PubSubClient.h>// Clientes WiFi y MQTTWiFiClientwificlient;PubSubClientmqttclient(wificlient);
4.2 Bloque de configuración setup()
Se requiere realizar una conexión con el broker MQTT, se forma semejante a la conexión al router, por lo que se crea un proceso denominado inicia_mqtt() solamente si se ha establecido una conexión WiFi.
4.3 Blucle o lazo de operación Loop()
Una vez realizada la lectura del sensor, de tener disponible una conexión WiFi y una conexión a un broker MQTT se realiza la publicación del valor del sensor en el tópico correspondiente.
publica_estado();
4.4 Bloques de procedimiento inicia_mqtt() y publica_estado()
El procedimiento inicia_mqtt() se encarga de establecer los parámetros del broker y la conexión, que de completarse inicializa el estado del dispositivo publicando el valor del sensor o actuador.
mqttclient.setServer(MQTT_IP,MQTT_puerto);mqttclient.connect(MQTT_ID,MQTT_usuario,MQTT_contrasena);//mqttclient.setCallback(callback);// Si conectado, inicializa estadoif(mqttclient.connected()){publica_estado();}
El procedimiento de publicación de estado tiene dos partes, la conformación del mensaje y el envío del mensaje.
// formato para envio (Texto)if(sensor_estado==true){snprintf(MQTT_SensorEstado,10,"ON");}else{snprintf(MQTT_SensorEstado,10,"OFF");}// publicar estadosif(mqttclient.connected()==true){mqttclient.publish(MQTT_TOPIC,MQTT_SensorEstado,true);}
La siguiente página presenta el archivo con las instrucciones completas para la operación de un dispositivo.