Instrucciones
Las instrucciones enfocadas en cada sensor o actividad se resumen en funciones, tratando de mantener la simplicidad del lazo principal.
Las instrucciones incorporan las siguientes características:
- el botón config_IR, una vez presionado espera hasta recibir una señal infraroja que se lee, y graba.
- el Envío de la señal se realiza con la instrucción MQTT o desde Home Assistant
- Usa el LED_LeeIR como indicador de estado de lectura o activación de control remoto.
- Se emite la señal de control mediante la variable senal_ONOFF
- Se controla el estado de lectura del sensor/decodificador infrarojo mediante MQTT, y la respuesta se emite a la conexión serial.
- La temperatura y humedad se actualizan con el parametro "intervalo" cuyo primer número es minutos
/* ESP8266 IRremoteESP8266: Receptor Infrarojo
* edelros@espol.edu.ec
* Debe usar un sensor detector/demodulador conectado al Receptor_Pin.
* Based on Mark Szabo's Version 0.2 June, 2017 and
* Ken Shirriff's IrsendDemo Version 0.1 July, 2009
* https://github.com/markszabo/IRremoteESP8266
* 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>
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
#include <IRsend.h>
#include <EEPROM.h>
#include <DHT.h>
// WIFI: conexión a Router
char* ssid = "giotirni20";
char* password = "Anera2020@";
// MQTT: Servidor
char* MQTT_IP = "192.168.10.50";
uint16_t MQTT_puerto = 1883;
char* MQTT_usuario = "usuarioprueba";
char* MQTT_contrasena = "usuarioclave";
// MQTT: Dispositivo Interruptor
char* MQTT_ID = "oficina_CtrlIR01";
char* MQTT_TOPIC = "oficina/CtrlIR01/estado";
char* MQTT_COMMAND = "oficina/CtrlIR01/cambia";
char* MQTT_TOPIC_T = "oficina/CtrlIR01/temperatura";
char* MQTT_TOPIC_H = "oficina/CtrlIR01/humedad";
char* MQTT_COMMAND_DHT = "oficina/CtrlIR01/actualiza";
char* MQTT_TOPIC_LeeIR = "oficina/CtrlIR01/leer";
char* MQTT_COMMAND_LeeIR = "oficina/CtrlIR01/grabar";
char MQTT_SensorEstado[10] = "OFF";
char MQTT_ActuadorEstado[10] = "OFF";
char MQTT_DHT_T[6] = "25"; // inicializa
char MQTT_DHT_H[6] = "50"; // inicializa
char MQTT_LeeIR[6] = "0"; // inicializa
volatile boolean mqtt_desconectado = true;
char* sensor_ON = "ON";
char* sensor_OFF = "OFF";
// Actuador Control Remoto Emisor LED-IR en GPIO14
const uint8_t emisorIR_pin = 14;
uint32_t senal_ONOFF = 0xFF5AA5; // código de control
volatile boolean actuador_estado = false;
volatile boolean actuador_bandera = false;
// Sensor IR en GPIO05
const uint8_t receptorIR_pin = 5;
volatile boolean LeerIR_estado = false;
volatile boolean LeerIR_bandera = false;
// Boton de lectura y emitir IR
const uint8_t config_pin = 12;
const uint8_t emitir_pin = 0;
// LED monitor //interno: ESP01-pin=1, ESP07-pin=2
const uint8_t LED_pin=13;
const uint8_t LED_LeerIR = 2;
// Mensajes por Puerto Serial
volatile boolean serial_msg = true;
// Control de tiempo transcurrido entre lecturas temperatura
unsigned long ahora = millis();
const long intervalo = 5*60*1000;//minutos*60s*1000ms
unsigned long antes = ahora-intervalo-1; //leer al inicio
// Clientes WiFi y MQTT
WiFiClient wifiClient;
PubSubClient mqttclient(wifiClient);
// Receptor y Emisor Infrarojos
IRrecv irrecv(receptorIR_pin);
decode_results lecturaIR;
IRsend irsend(emisorIR_pin);
// Sensor de Temperatura&Humedad
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
void setup() {
Serial.begin(74880);//74880, 115200
while (!Serial){delay(50);}
// SENSOR IR // inicia receptor IR
irrecv.enableIRIn();
pinMode(LED_LeerIR, OUTPUT);
Leer_Activaestado();
// ACTUADOR IR // inicia emisor IR
pinMode(emisorIR_pin, OUTPUT);
irsend.begin();
// SENSOR Temperatura&Humedad
dht.begin();
// LED monitor, Enciende en LOW
pinMode(LED_pin, OUTPUT);
// Memoria lectura y escritura
EEPROM.begin(64); //eeprom maximo 512 posiciones
codigo_leermem();
// Boton de lectura de código IR
pinMode(config_pin, INPUT);
attachInterrupt(digitalPinToInterrupt(config_pin),LeerActivado,CHANGE);
// Boton de Emisor de código IR
pinMode(emitir_pin, INPUT);
attachInterrupt(digitalPinToInterrupt(emitir_pin),IR_Activado,CHANGE);
// conexión WIFI y MQTT
inicia_wifi();
if (WiFi.status() == WL_CONNECTED){
inicia_mqtt();
}
}
void loop() {
// enviar señal IR
if (actuador_bandera){
irsend.sendNEC(senal_ONOFF ,32);
// parpadeo
digitalWrite(LED_LeerIR, LOW);
delay(300);
digitalWrite(LED_LeerIR, HIGH);
delay(200);
digitalWrite(LED_LeerIR, LOW);
delay(300);
digitalWrite(LED_LeerIR, HIGH);
delay(200);
// deja en estado anterior el LED Leer_IR
Leer_Activaestado();
publica_estado();
actuador_bandera = false;
if (serial_msg==true){
Serial.print("\n Señal IR enviada: ");
serialPrintUint64(senal_ONOFF, HEX);
Serial.println("");
}
}
yield(); // procesa wifi
// Sensor IR, leer código
if(LeerIR_bandera){
if (irrecv.decode(&lecturaIR)) {
// conversión a texto
uint64_t numero = lecturaIR.value;
unsigned long parte1 = (unsigned long)((numero & 0xFFFF0000) >> 16 );
unsigned long parte2 = (unsigned long)((numero & 0x0000FFFF));
String texto = String(parte1, HEX) + String(parte2, HEX);
texto.toUpperCase();
senal_ONOFF = lecturaIR.value;
// Escribe a memoria EEPROM
// escribe a eeprom
texto = texto+";"; //marca fin de texto
int n = texto.length();
int posicion = 0;
int i = posicion;
while(i<n){
EEPROM.write(i,texto[i]);
i=i+1;
}
EEPROM.commit();
irrecv.resume();
LeerIR_bandera = false;
LeerIR_estado = false;
publica_estado();
Leer_Activaestado();
if (serial_msg==true){
Serial.print("\n lecturaIR: ");
// print() & println() no maneja enteros largos(uint64_t)
serialPrintUint64(lecturaIR.value, HEX);
Serial.println("");
Serial.print(" grabado en memoria: ");
Serial.println(texto);
}
}
}
yield(); // procesa wifi
// lectura Temperatura,Humedad
unsigned long ahora = millis();
unsigned long transcurre = ahora-antes;
if (transcurre>=intervalo){
antes = ahora;
delay(50);
// calibrar con una referencia más precisa
// modo simple: resta factor de corrección=5
float temperatura = dht.readTemperature();
float humedad = dht.readHumidity();
// convierte a texto mqtt; a 4 dígitos, 2 decimales
dtostrf(temperatura, 4, 2, MQTT_DHT_T);
dtostrf(humedad, 4, 2, MQTT_DHT_H);
publica_estado();
if (serial_msg==true){
Serial.print("\n tiempo: ");
Serial.println(transcurre);
Serial.print(" Temperatura,Humedad: ");
Serial.print(MQTT_DHT_T);
Serial.print(" , ");
Serial.println(MQTT_DHT_H);
Serial.println();
}
}
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
}
void codigo_leermem(){
// lectura desde eeprom, codigo on/off
int posicion = 0;
int n = posicion+10;
String codigotxt = "";
char simbolo;
int i = posicion;
while(i<n){
simbolo = char(EEPROM.read(i));
if (simbolo!=';'){
codigotxt = codigotxt+String(simbolo);
}else{
i=n; // terminar lectura antes
}
i=i+1;
}
// conversión de codigotxt a HEX
char codigochar[64];
codigotxt.toCharArray(codigochar, n);
uint32_t codigoIRhex = strtoul(codigochar, 0, 16);
// actualiza variable
senal_ONOFF = codigoIRhex;
if (serial_msg==true){
Serial.print("texto leido: ");
Serial.println(codigotxt);
Serial.print("codigo IR eprom: ");
// print() & println() no maneja enteros largos(uint64_t)
serialPrintUint64(senal_ONOFF, HEX);
Serial.println("\n");
}
}
// ISR interrupción activada
ICACHE_RAM_ATTR void LeerActivado(){
// evita repeticiones por rebotes del botonera
if (LeerIR_bandera==false){
LeerIR_bandera = true;
LeerIR_estado = true;
Leer_Activaestado();
publica_estado();
if (serial_msg){
Serial.println(" Leer IR activado...");
}
}
}
ICACHE_RAM_ATTR void IR_Activado(){
// evita repeticionese por rebotes del botonera
if (actuador_bandera ==false){
actuador_bandera = true;
if (actuador_estado == true) {
actuador_estado = false;
}else{
actuador_estado = true;
}
publica_estado();
if (serial_msg){
Serial.println(" IR_envío activado...");
}
}
}
// Actuador activar estado
void Leer_Activaestado(){
if (LeerIR_estado){
// ACTUADOR ACTIVA EN LOW
// LED actuador ilumina en apagado
digitalWrite(LED_LeerIR, LOW);
}else{
digitalWrite(LED_LeerIR, HIGH);
}
}
// 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 (LeerIR_estado){
snprintf (MQTT_LeeIR,10, sensor_ON);
}else{
snprintf (MQTT_LeeIR,10, sensor_OFF);
}
if (mqttclient.connected()==true){
mqttclient.publish(MQTT_TOPIC,MQTT_ActuadorEstado,true);
mqttclient.publish(MQTT_TOPIC_LeeIR,MQTT_LeeIR,true);
mqttclient.publish(MQTT_TOPIC_T,MQTT_DHT_T,true);
mqttclient.publish(MQTT_TOPIC_H,MQTT_DHT_H,true);
}else{
mqtt_desconectado = true;
}
}
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){
//Fin de "..."
Serial.println();
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();
}
}
}
void inicia_mqtt(){
int intentos = 2;
int cuenta = 0;
if (serial_msg){
Serial.print(" MQTT Conectando a ");
Serial.println(MQTT_IP);
}
mqttclient.setServer(MQTT_IP, MQTT_puerto);
mqttclient.connect(MQTT_ID, MQTT_usuario, MQTT_contrasena);
mqttclient.setCallback(callback);
while (!mqttclient.connected() && (cuenta<intentos)) {
if (serial_msg){
Serial.print(".");
}
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);
mqttclient.subscribe(MQTT_COMMAND_LeeIR);
mqttclient.subscribe(MQTT_COMMAND_DHT);
if (serial_msg){
//Fin de "..."
Serial.println();
Serial.print(" MQTT Conectado: ");
Serial.println(mqttclient.connected());
Serial.print(" MQTT Estado: ");
Serial.println(mqttclient.state());
}
}
// 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;
}
}
Leer_Activaestado();
publica_estado();
actuador_bandera = true;
}
if (String(MQTT_COMMAND_LeeIR).equals(p_topic)) {
if (payload.equals(String(sensor_ON))) {
if (LeerIR_estado != true) {
LeerIR_estado = true;
}
}
if (payload.equals(String(sensor_OFF))) {
if (LeerIR_estado != false) {
LeerIR_estado = false;
}
}
LeerIR_bandera = true;
Leer_Activaestado();
publica_estado();
}
if (String(MQTT_COMMAND_DHT).equals(p_topic)) {
antes = antes-(intervalo+2);
}
}









