Calificación:
  • 0 voto(s) - 0 Media
  • 1
  • 2
  • 3
  • 4
  • 5
ESP8266 callback + deepSleep
#1
Buenas tardes a todos,

llevo un par de días atascado con este problema y no veo solución, incluso he seguido el github de @grafisoft, pero a mí no me funciona Github IOT

Estoy intentando implementar en un ESP8266 la función deepSleep junto con un Callback para recibir un mensaje de MQTT. Este callback lleva el nuevo valor que obtendrá el nodo para el deepSleep.

El funcionamiento sería el siguiente:

Nodo despierto -> lee callback -> realiza mediciones -> envía mediciones -> sleep(valor callback)

Sin emabrgo, la función callback no la realiza:

Nodo despierto -> realiza mediciones -> envía mediciones -> sleep(valor porDefecto)

Como dato curioso, si modifico el deepSleep por delay, si consigue entrar en la función Callback.

Dejo aquí el código que estoy empleando a ver si alguien consigue saber que puedo estar haciendo mal.

Gracias de antemano.

Código:
#include <ESP8266WiFi.h>  //WIFI ESP8266
#include <PubSubClient.h>  // MQTT

// Update these with values suitable for your network.
const char* ssid = "linksys";
const char* password = "";
const char* mqtt_server = "192.168.1.3";

//----------------------- CONFIG PARAMETERS------------------------
//Con este parametro se construye todos los topics para el protocolo MQTT.
// Nombre del nodo.
String NodeName = "Testing";
String TopicMQTT; //Variable para construir el Topic de MQTT.
//El tiempo de sueño se especifica en el fichero funciones.h (sleeptime).
//-----------------------------------------------------------------

WiFiClient espClient;
PubSubClient client(espClient);

const int sleeptime = 60 * 10e5; // En segundos //20 * 60 * 1000000;
int rate = 100000;


//----------------------- WIFI CONNECTION ------------------------
void setup_wifi() {
 delay(10);
 // We start by connecting to a WiFi network
 Serial.println();
 Serial.print("Connecting to ");
 Serial.println(ssid);

 WiFi.begin(ssid, password);

 while (WiFi.status() != WL_CONNECTED) {
   delay(500);
   Serial.print(".");
 }

 Serial.println("");
 Serial.println("WiFi connected");
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());
}
//-----------------------------------------------------------------

//----------------------- WIFI RE-CONNECTION ------------------------
void reconnect() {
 // Loop until we're reconnected
 while (!client.connected()) {
   Serial.print("Attempting MQTT connection...");
   // Attempt to connect
   if (client.connect("ESP8266Client")) {
     Serial.println("connected");
     // Once connected, publish an announcement...
     client.publish("arboles/naranjo/info", "Conectado");
     // ... and resubscribe
     //client.subscribe("arboles/configuracion/rate");
     client.subscribe("arboles/configuracion/rate");
     //client.subscribe("despacho/luz");
   } else {
     Serial.print("failed, rc=");
     Serial.print(client.state());
     Serial.println(" try again in 5 seconds");
     // Wait 5 seconds before retrying
     delay(5000);
   }
 }
}
//-----------------------------------------------------------------

//----------------------- CALLBACK ------------------------
void callback(char* topic, byte* payload, unsigned int length) {
 Serial.print("Message arrived [");
 Serial.print(topic);
 Serial.print("] ");
 for (int i = 0; i < length; i++) {
   Serial.print((char)payload[i]);
 }
 Serial.println();
 Serial.print("El valor entero es: ");
 payload[length] = '\0';
 rate = atoi((char*)payload); //Char to int
 rate = rate * 1000;
 Serial.println(rate);
 //EEPROM.put(rate_address, rate);
}
//-----------------------------------------------------------------


void setup() {
 pinMode(LED_BUILTIN, OUTPUT);
 digitalWrite(LED_BUILTIN, LOW);
 Serial.begin(9600); //Velocidad del UART.
 setup_wifi();
 //Configuracion conexion a MQTT.
 client.setServer(mqtt_server, 1883);
 client.setCallback(callback);
}

void loop() {

  //Conexión con el broker MQTT.
 if (!client.connected()) {
   reconnect();
 }
 client.loop();

 //delay(1000);
 // Tiempo de deepSleep especificado en 'sleeptime'.
 //ESP.deepSleep(rate);
 ESP.deepSleep(sleeptime); //, WAKE_RF_DEFAULT);
}
Citar
#2
Esta mañana he estado probando también a poner el nodo en LightSleep

Código:
// Required for LIGHT_SLEEP_T delay mode
extern "C" {
#include "user_interface.h"
}

Código:
void sleep_function()
{
/* LIGHT SLEEP */
//WiFi.disconnect(); // DO NOT DISCONNECT WIFI IF YOU WANT TO LOWER YOUR POWER DURING LIGHT_SLEEP_T DELLAY !
//Serial.println(WiFi.status());  
digitalWrite(LED_BUILTIN, HIGH);
wifi_set_sleep_type(LIGHT_SLEEP_T);
delay(6000*300-800); // loop every 3 minutes

/* DEEP SLEEP */
//ESP.deepSleep(9e8);
}

Pero aunque si se "duerme" correctamente, tampoco consigue entrar de nuevo en la función Callback.
Citar
#3
Quizas no le de tiempo a recibir el topic del MQTT al que esta subscrito y por eso no te pilla el valor. Guardas el valor en mqtt con modo persistente? (para que siempre este el dato en el servidor y no se borre una vez entregado). Si el valor ha sido entregado una vez, ya no lo vuelve a enviar de forma automatica.
---> Actualmente construyendo mi siguiente CNC de escritorio. Puedes participar o apuntarte a una tirada inicial. Mas info en: https://www.spainlabs.com/foros/tema-Fre...op-CNC-500
Citar
#4
Posiblemente pueda ser que no le da tiempo a recibir el mensaje. No sé muy bien como funciona el evento del callback, pero ahora mismo estoy inyectando un mensaje cada 0.1segundos y no lo recibe. Sin embargo, por la terminal si puedo leerlo:

Código:
pi@raspberrypi:~ $ mosquitto_sub -t "arboles/configuracion/melocotonero/rate/#" -v
arboles/configuracion/melocotonero/rate 62
arboles/configuracion/melocotonero/rate 3000
arboles/configuracion/melocotonero/rate 3000
arboles/configuracion/melocotonero/rate 3000
arboles/configuracion/melocotonero/rate 3000
arboles/configuracion/melocotonero/rate 3000

Entonces no sé cuanto tiempo necesita el micro para procesar un callback, aunque entiendo también que si recibe un callback no debería entrar en sleep. Más bien es como una interrupción, si recibe un mensaje en el tópico, para el proceso que esté realizando, ejecuta las acciones y vuelve a donde estaba. Obviamente si está en sleep no hará caso.

Ahora mismo estoy probando con QoS = 1 y retention = true en el nodo de nodered.

resim

resim

resim

Sin embargo, nunca recibe ningun mensaje en el tópico: 
Código:
 client.subscribe("arboles/configuracion/melocotonero/rate");

Ni tan si quiera hace un amago de entrar en la función callback.
Código:
Connecting to linksys
......
WiFi connected
IP address:
192.168.1.50
Attempting MQTT connection...connected
Temperatura = 612.80
Humedad = -6216.69
Bateria = 100
Go to sleep
INFO: Closing the Wifi connection
Waiting for shutdown before sleeping
tx�CGH,@>h�␐␡�
Connecting to linksys
......
WiFi connected
IP address:
192.168.1.50
Attempting MQTT connection...connected
Temperatura = 612.80
Humedad = -6216.69
Bateria = 100
Go to sleep
INFO: Closing the Wifi connection
Waiting for shutdown before sleeping
�H�l�h���␄xH�!��
Connecting to linksys
......
WiFi connected
IP address:
192.168.1.50
Attempting MQTT connection...connected
Temperatura = 612.80
Humedad = -6216.69
Bateria = 100
Go to sleep
INFO: Closing the Wifi connection
Waiting for shutdown before sleeping
Ȥl���l$��$:h��
Connecting to linksys
......
WiFi connected
IP address:
192.168.1.50
Attempting MQTT connection...connected
Temperatura = 612.80
Humedad = -6216.69
Bateria = 100
Go to sleep
INFO: Closing the Wifi connection
Waiting for shutdown before sleeping
Ȥl���l$�␇␚:h��
Connecting to linksys
......
WiFi connected
IP address:
192.168.1.50
Attempting MQTT connection...connected
Temperatura = 612.80
Humedad = -6216.69
Bateria = 100
Go to sleep
INFO: Closing the Wifi connection
Waiting for shutdown before sleeping
␎HpY�CGH�@>h�␐␡�

Otra posibilidad sería la existencia de algún servicio o request, que cuando se despertase el nodo pidiera al servidor el valor de una variable. Pero no he encontrado nada respecto a esta funcionalidad por la web.

En caso de que no exista esa función, ¿cómo puedo forzar al nodo a que espere a recibir algún callback? Porque supongo que añadir un gran delay no servirá.

Otra duda que me viene es que cuando yo desde la terminal me conecto al tópico, siempre me devuelve un valor que tengo guardado en el servidor nodered. Pero en el nodomcu ese mensaje tampoco aparece.

He estado revisando y la gente solo se suscribe al tópico en la función reconnect.

Código:
void reconnect() {
 // Loop until we're reconnected
 while (!client.connected()) {
   Serial.print("Attempting MQTT connection...");
   // Attempt to connect
   if (client.connect("ESP8266Client")) {
     Serial.println("connected");
     // Once connected, publish an announcement...
     client.publish("arboles/melocotonero/info", "Conectado");
     // ... and resubscribe
     //client.subscribe("arboles/configuracion/rate");
     client.subscribe("arboles/configuracion/melocotonero/rate");
     //client.subscribe("despacho/luz");
   } else {
     Serial.print("failed, rc=");
     Serial.print(client.state());
     Serial.println(" try again in 5 seconds");
     // Wait 5 seconds before retrying
     delay(5000);
   }
 }
}

Yo incluso la he añadido en el setup pero tampoco ha funcionado.

A ver si podemos dar con alguna estrategia para poder entrar en el callback.

Gracias de nuevo y feliz Navidad!
Citar
#5
No he probado nunca el tema de subcribir con el esp, pero en algun lado tendras la info del topic subscrito, o igual no la estas guardando.

Prueba añadir algun delay de varios segundos antes de irte a dormir.
---> Actualmente construyendo mi siguiente CNC de escritorio. Puedes participar o apuntarte a una tirada inicial. Mas info en: https://www.spainlabs.com/foros/tema-Fre...op-CNC-500
Citar
#6
(24-12-2019, 05:25 PM)grafisoft escribió: No he probado nunca el tema de subcribir con el esp, pero en algun lado tendras la info del topic subscrito, o igual no la estas guardando.
Vaya... pensaba que sí al verlo en tu Github. ¿A qué te refieres con la info del topic suscrito?

(24-12-2019, 05:25 PM)grafisoft escribió: Prueba añadir algun delay de varios segundos antes de irte a dormir.
Acabo de probar con varios valores entre 5 y 10 segundos y no reacciona. De todas formas no sé si ahí afectan en el comportamiento para leer, ya que creo que comprueba los callback en la función "client.loop()"
Citar
#7
Lo he podido solucionar haciendo un loop temporal en la conexión.

Código:
//TRANSFER CODE FROM LOOP TO HERE
uint32_t loopStart = millis();
while (millis() - loopStart < 15000) {
if (!client.connected()) {
reconnect();
} else client.loop();
} //END OF LOOP CODE

La solución la saqué de una consulta abierta en el git de la librería: https://github.com/knolleary/pubsubclient/issues/634
Citar
#8
Lo que hace el codigo ese es estar continuamente comprobando dursnte un tiempo.
---> Actualmente construyendo mi siguiente CNC de escritorio. Puedes participar o apuntarte a una tirada inicial. Mas info en: https://www.spainlabs.com/foros/tema-Fre...op-CNC-500
Citar
#9
Exacto, pero sobre todo fuerza a reentrar en la función callback que está en el client loop
Citar
#10
Si, de la otra forma pasa una vez y fin.

Me alegra que hayas encontrado la solución Sonrisa
---> Actualmente construyendo mi siguiente CNC de escritorio. Puedes participar o apuntarte a una tirada inicial. Mas info en: https://www.spainlabs.com/foros/tema-Fre...op-CNC-500
Citar


Temas similares...
Tema Autor Respuestas Vistas Último mensaje
  [SpainLabsIoT2018] Caso real: Nodos ESP8266 grafisoft 76 12,626 17-07-2019, 11:25 AM
Último mensaje: Kurama
  APORTE [SpainLabsIoT2018] ESP8266 NodeMCU - Ajustando su consumo (hack) grafisoft 10 3,923 24-04-2019, 04:49 PM
Último mensaje: grafisoft
  Sonoff de itead (basado en ESP8266) linesguapo 7 7,707 29-03-2019, 12:45 PM
Último mensaje: pmovando
  [Guia] ESP8266 (NodeMCU) + sensor BME280 + MQTT grafisoft 17 7,575 09-10-2018, 09:49 PM
Último mensaje: grafisoft
  [SpainLabsIoT2018] Nodo ESP8266 - Smart Sensors Shield grafisoft 16 3,652 02-07-2018, 08:55 PM
Último mensaje: grafisoft