Proyecto Temperatura y luces en salon problemas con ESP32+mqtt+node-red

Saludos Amigos, es un placer pertenecer a esta comunidad. Llevo meses dando vueltas a este proyecto y no soy capaz de solucionarlo, a ver si me podeis echar una mano.

Componentes:

  • ESP32 DEVKIT v1

  • DHT11 ( en espera de recibir un DHT22 )

  • Led Tricolor (RGB)

  • (Sensor PIR)

  • (Sensor de monoxido de carbono)

  • Alimentacion: YUROBOT 3,3-5 v.

La idea es saber la temperatura, humedad, y monoxido de carbono del salon, con un pequeño detector PIR ya que hay un pasillo que accede al salon y poder encerder la luz detectando el movimiento. Todo estos datos enviados a un servidor con mosquitto y con Node-Red poder visualizarlo en una Tablet que no utilizaba.

Parece facil pero me he quedado en el punto del RGB. El servidor mosquitto esta funcionando bien ( o eso creo ), y la visualizacion en Web esta bien. Fundamentalmente tengo dos problemas, el primero es la conexion con el servidor que tiene mosquitto ya que utilizo WPA2-Personal y suele perder la conexion. Si conecta, y sin tiempo determinado, deja de emitir los datos ( aunque permanece conectado ), y no actua por lo que tampoco puedo utilizar el encendido de luces ( mosquitto mal configurado ? ).

Como veis estoy bloqueado y necesito un empujon.....

Dejo el codigo que estoy utilizando y a ver que veis vosotros, os fijareis que estaba incorporando el PIR .....

Gracias por todo....

/*****

  Vincent Price @ 2018
  for all World

*****/

#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"

//Quitar las barras del sensor que corresponda
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

//Escribir los datos de conexion
const char* ssid = "XXX";
const char* password = "XXX";

//Incluir la direccion del servidor MQTT
const char* mqtt_server = "192.168.0.101";

// Conectamos como cliente al Servidor
WiFiClient espClient;
PubSubClient client(espClient);

// Pin de entrada para DHT
const int DHTPin = 14;

// Pin luces pasillo
const int lamp2 = 13;

// Pin luces comedor
const int lamp = 23;

//byte sensorPin = 27;
byte indicator = 26;

// Inicializamos DHT sensor.
DHT dht(DHTPin, DHTTYPE);

// Tiempo para las variables
long now = millis();
long lastMeasure = 0;

void setup_wifi() {

  delay(10);
  Serial.println();
  Serial.print("Conectando a: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi conectado - ESP IP : ");
  Serial.println(WiFi.localIP());
}

void callback(String topic, byte* message, unsigned int length) 
{
  //Serial.print("Mensajes llegado al topic: ");
  //Serial.print(topic);
  //Serial.print(". Mensaje: ");
  String messageTemp;

  for (int i = 0; i < length; i++) {
    //Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  //Serial.println();

  if (topic == "casa/luces") {
    //Serial.print("Comedor: ");
    if (messageTemp == "on") {
      digitalWrite(lamp, HIGH);
      //Serial.print("Encendido");
    }
    else if (messageTemp == "off") {
      digitalWrite(lamp, LOW);
      //Serial.print("Apagado");
    }
  }

  if (topic == "casa/luces2") {
    //Serial.print("Pasillo: ");
    if (messageTemp == "on2") {
      digitalWrite(lamp2, HIGH);
      //Serial.print("Encendido");
    }
    else if (messageTemp == "off2") {
      digitalWrite(lamp2, LOW);
      //Serial.print("Apagado");
    }
  }
  Serial.println();
}

void reconnect() {

  pinMode(2, OUTPUT);
  while (!client.connected()) {
    Serial.print("Intentando conectar a MQTT...");

    if (client.connect("ESP32Client")) {
      Serial.println("conectado");
      digitalWrite(2, HIGH);

      client.subscribe("casa/luces");
      client.subscribe("casa/luces2");
      client.subscribe("casa/magne");
      client.subscribe("casa/temp");
      client.subscribe("casa/humedad");
    } else {
      Serial.print("fallo, rc=");
      Serial.print(client.state());
      Serial.println(" volveremos a conectar en 5 segundos");
      digitalWrite(2, LOW);
      delay(5000);
    }
  }
}

void setup() {

  //pinMode(sensorPin, INPUT);
  pinMode(indicator, OUTPUT);
  pinMode(lamp, OUTPUT);
  pinMode(lamp2, OUTPUT);

  dht.begin();

  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

}

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  if (!client.loop())
    client.connect("ESP32Client");

  now = millis();
  if (now - lastMeasure > 5000) {
    lastMeasure = now;
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    float f = dht.readTemperature(true);

    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println("Fallo al leer el sensor DHT!");
      return;
    }

    float hic = dht.computeHeatIndex(t, h, false);
    static char temperatureTemp[7];
    dtostrf(hic, 6, 2, temperatureTemp);

    // float hif = dht.computeHeatIndex(f, h);
    // static char temperatureTemp[7];
    // dtostrf(hic, 6, 2, temperatureTemp);

    static char humidityTemp[7];
    dtostrf(h, 6, 2, humidityTemp);

    float magne = hallRead();
    static char magneTemp[7];
    dtostrf(magne, 6, 2, magneTemp);

    client.publish("casa/temp", temperatureTemp);
    client.publish("casa/humedad", humidityTemp);
    client.publish("casa/magne", magneTemp);

    //byte state = digitalRead(sensorPin);
    //digitalWrite(indicator, state);
    //if (state == 1)Serial.println("Movimiento");
    //else if (state == 0)Serial.println("Nada");
    //delay(500);

  }
}

Y mosquito donde esta corriendo? No lo dices, pero como tienes Node-Red supongo que por algun lado hay una Raspi o una PC corriendo Linux no es así? Has visto el log de mosquito?

Gracias por contestar...
Efectivamente es un PC que tengo aparte donde esta corriendo Mosquitto 1.5.4 y Node-red 0.19.5, por separado en un Windows 7.

Creo que no lo genera porque me imagino que arranca con la configuracion por defecto. Esa era una de mis preguntas la configuracion de mosquitto.

Si necesitais mas informacion, por favor no dudeis..., estoy sacando fotos y haciendo el circuito en fritzing
para mejorar la exposicion del problema.

Gracias por todo.....

Por favor si haces un esquema en Fritzzing no tires lineas de lado a lado haciendo diagonales.. a los electrónicos nos cuesta leer eso como un esquema. Espero me comprendas.

Busca en mosquitto si hay algun archivo log que indique fallas posibles.

Yo eso lo tengo con un Raspi 2 funcionando con 0 problemas desde hace 2 o 3 aÑos.

Lo he hecho lo mas simple posible...

Creo que no aparece, a no ser que se configure en mosquitto.conf, pero claro no he tocado nada, como te he comentado al principio.

Por cierto, temgo una simple Raspberry Pi, seria posible ?, y mas estable ?.

Veo que no leíste esto

Por favor si haces un esquema en Fritzzing no tires lineas de lado a lado haciendo diagonales.. a los electrónicos nos cuesta leer eso como un esquema. Espero me comprendas.

se dibuja en forma ortogonal. Para la próxima ta vez...

Voy al código y veo esto:

delay(5000);

Debes aprender a no usar esas cosas.. en un ambiente de red cosas como esas detienen el procesador y generan todo tipo de problemas.
usa millis() crea una máquina de estados.

Gracias querido amigo, dentro de un mundillo del que no me era totalmente desconocido, estudie electronica y experimente con AT90S8515, ATMEGA, pero era algo que tenia olvidado hace mucho tiempo.

Debido a un accidente que me tiene postrado y al largo tiempo que me llevara, decidi retomar y buscar una meta para pasar estos tristes dias alejado de la familia.

Como buen autodidacta empece a trastear y aqui estoy. Pero tengo que ser sincero este codigo en su mayoria es un corta y pega de otros proyectos que he visto en Internet. Y aunque entienda el codigo, (estructura y forma) en temas tecnicos soy un pececillo fuera del agua.

Se lo que es millis() y para que se utiliza, el problema es implementarlo y plasmarlo en un codigo.

Me imagino que te refieres a algo parecido a esto, verdad ?

  now = millis();
  if (now - lastMeasure > 5000) {
    lastMeasure = now;

Quiero aprender, lo que me sobra es tiempo, el problema es que cada maestrillo tiene su librillo, por lo que cada uno lo explica a su manera, y me estoy volviendo loco.

Gracias de nuevo por tu ayuda. Por cierto,....perdona por lo del diseño, no volvera a pasar.

Bueno, lamento tu accidente y espero que sigas en tu recuperación de la mejor manera posible y es cierto, una meta despeja la cabeza de las tonterias.

No es solo aprender a usar millis() sino también máquina de estados que es para hacerlo simple una secuencia lógica de estados digitales que se cumplen llendo de estado lógico a otro estado lógico, no necesariamente en orden. Ya lo verás que fácil es y de que modo se cambia un código que se detiene con delay() y ahora parece que tienes una máquina multitarea aunque no lo sea.
Por lo que veo en tu caso la máquina de estados no es necesaria pero veremos si crece el proyecto.

Acá tienes la teoría y algunos consejos prácticos.
Ve a Documentación => Indice de temas tutoriales => millis() y también lee máquina de estados.

Cuando uses variables relacionadas con millis() siempre asigna como unsigned long no solo long.
Ver Documentación tutorial de noter sobre desbordamiento de variables a los 47.x dias.

Te agradezco tu interes, voy a ponerme con ello, te comentare las dudas. Y el proyecto tiene qur ir para adelante, he puesto muchas esperanzas y he molestado mucho para poder llevarlo a cabo.

Gracias por todo....

Creo haber entendido el concepto, a ver si lo he plasmado bien....

Codigo Anterior

// Tiempo para las variables
long now = millis();
long lastMeasure = 0;

Codigo Nuevo

// Tiempo para las variables
unsigned long now = millis();
unsigned long lastMeasure = 0;
unsigned long intervalo = 2000;

Implementacion

Codigo Anterior

  while (!client.connected()) {
    Serial.print("Intentando conectar a MQTT...");

    if (client.connect("ESP32Client")) {
      Serial.println("conectado");
      digitalWrite(2, HIGH);

      client.subscribe("casa/luces");
      client.subscribe("casa/luces2");
      client.subscribe("casa/magne");
      client.subscribe("casa/temp");
      client.subscribe("casa/humedad");
    } else {
      Serial.print("fallo, rc=");
      Serial.print(client.state());
      Serial.println(" volveremos a conectar en 5 segundos");
      digitalWrite(2, LOW);
      delay(5000);

Codigo Nuevo

  while (!client.connected()) {
    Serial.print("Intentando conectar a MQTT...");

    if (client.connect("ESP32Client")) {
      Serial.println("conectado");
      digitalWrite(2, HIGH);

      client.subscribe("casa/luces");
      client.subscribe("casa/luces2");
      client.subscribe("casa/magne");
      client.subscribe("casa/temp");
      client.subscribe("casa/humedad");
    } else {
      if (millis() - now >= intervalo){
      Serial.print("fallo, rc=");
      Serial.print(client.state());
      Serial.println(" volveremos a conectar en 2 segundos");
      digitalWrite(2, LOW);
      }

Bueno creo que funcionará aunque arrancas con la situacion de tener que esperar 5 segundos.
Si en cambio now comienza con 0, la primera vez mostrará client.state() como en la versión delay()

Ahora bien, veo algo que no se donde actualizas.
Tu rutina debería cambiar now una vez cumplida la condición milli() - now > intervalo

} else {
      if (millis() - now >= intervalo){
      Serial.print("fallo, rc=");
      Serial.print(client.state());
      Serial.println(" volveremos a conectar en 2 segundos");
      digitalWrite(2, LOW);
      now = millis(); // esto asegura el proximo intervalo de X segundos.
      }

EDITO: me he dado cuenta de un consejo que considero INUTIL de mi parte.
El objetivo del dispositivo es estar conectado con el cliente, si no está conectado no tiene razón de ser y si no tiene razón de ser que demore 2 o 5 seg sin hacer nada da igual.
Asi que delay vs millis() no tiene sentido salvo que ahora chequeará 1999 mseg y veces si se permite la igualdad para ver si el cliente se ha conectado.