Cliente Arduino Mqtt no recibe todos los mensajes

Hola a todos, estoy realizando un proyecto personal en el cual la comunicación la realizo mediante el protocolo MQTT entre un cliente en mi Arduino UNO y el borker mosquitto instalado en mi ordenador. Para ello hago uso de un modulo wifi ESP8266- ESP01

El problema que me he encontrado es que el cliente Arduino si únicamente se encarga de recibir mensajes, en ocasiones recibe solamente algunos y no todos o no recibe ningún mensaje a pesar de que mi modulo ESP8266-01 parpadea el led de comunicación.

Y si el cliente se encarga de enviar y recibir, si realiza bien el envió de los datos pero no es capaz de recibir ningún dato.

Aquí os dejo la parte de código encargada de la comunicación:

#include <WiFiEsp.h>
#include <WiFiEspClient.h>
#include "SoftwareSerial.h"
#include <PubSubClient.h>

IPAddress server(192, 168, 1, 131);     // Direccion IP del Broker
char ssid[] = "....";           // your network SSID (name)
char pass[] = "...";           // your network password
int status = WL_IDLE_STATUS;            // the Wifi radio's status

// Initialize the Ethernet client object
WiFiEspClient espClient;

PubSubClient client(espClient);
;

SoftwareSerial soft(3, 2); // RX, TX

void setup() {

  Serial.begin(9600);  // initialize serial for debugging
  Serial.println("Se inicia la configuracion de componentes");

  soft.begin(9600);    // initialize serial for ESP module
  WiFi.init(&soft);    // initialize ESP module


  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("Modulo WiFi no encontrado");
    // don't continue
    while (true);
  }

  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    Serial.print("Intentando conectar con el AP: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);
  }

  // you're connected now, so print out the data
  Serial.println("Conectado !");

  //connect to MQTT server
  client.setServer(server, 1883);
  client.setCallback(callback);

  client.subscribe("robot"); // Para las funciones de conexion y Start/Stop
  client.subscribe("robot/velocidad"); // Para la recepcion de la velocidad a aplicar
  
  Serial.println("Finalización de la configuracion de componentes");
}

void loop() {

  if (!client.connected()) {
    Serial.println("Reconectando...");
    reconnect();
  }

  /* long now = millis();
    if (now - lastMsg > 4000) {
     recogerValoresUltrasonidos();
     recogerValoresDHT();
    //  recogerValoresMPU();
     enviarDatos();
    }*/
  client.loop();
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Mensaje recibido [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

Una de las causas he pensado que podría ser todos los componentes que utilizo para el proyecto: 3 ultrasonidos, un dht11, un acelerometro mpu imu9250, modulo wifi esp8266-01. Pero no estoy seguro de ello.

Muchas gracias de antemano.

Yo creo que estas perdiendo mensajes porque la consulta de tus sensores demora mucho tiempo en esa tarea.
Debo entender que tienes un arduino conectado al ESP01 y que hay una interacción serie ya que veo SoftwareSerial x medio.

Intenta ampliar el BUFFER RX a ver si mejora su respuesta.

Si efectivamente tengo una interacción serie con SoftwareSerie. Pero el problema persiste aunque tal y como he adjuntado al principio la parte de recogida y envío de datos está comentada.

El código completo es el siguiente:

#include <WiFiEsp.h>
#include <WiFiEspClient.h>
#include "SoftwareSerial.h"
#include <PubSubClient.h>
#include <NewPing.h>
#include <DHT.h>
#include <DHT_U.h>
#include <MPU9250_asukiaaa.h>
#include <Wire.h>

#define numUltra     3 // Numero de sensores ultrasonidos
long lastMsg = 0;
#define pinTemp 4     // Pin del sensor de temperatura y humedad
#define DHTTYPE DHT11 // Tipo de sensor que utilizamos

#define enableMotores 11 // Enable para los dos ejes del robot

#define ejeIzqPos 5      // Pin PWM para salida positiva del eje izquierdo del robot
#define ejeIzqNeg 9      // Pin PWM para salida negativa del eje izquierdo del robot

#define ejeDerPos 6     // Pin PWM para salida positiva del eje derecho del robot
#define ejeDerNeg 10    // Pin PWM para salida positiva del eje derecho del robot

int valorUltra[numUltra]; // Almacenamiento de distancias de los ultrasonidos

float temp;
float hum;

bool estado; // variable que en false significa que el robot se apaga y true que mapea

int velocidad;

DHT dht(pinTemp, DHTTYPE);      // Creación del objeto del sensor de temp/hum

NewPing sonar[numUltra] = { // Sensor object array.
  NewPing(13, 7),
  NewPing(13, 8),
  NewPing(13, 12)
};

IPAddress server(192, 168, 1, 131);     // Direccion IP del Broker
char ssid[] = "...";           // your network SSID (name)
char pass[] = "...";           // your network password
int status = WL_IDLE_STATUS;            // the Wifi radio's status

// Initialize the Ethernet client object
WiFiEspClient espClient;

PubSubClient client(espClient);
;

SoftwareSerial soft(3, 2); // RX, TX

void setup() {

  Serial.begin(9600);  // initialize serial for debugging
  Serial.println("Se inicia la configuracion de componentes");

  soft.begin(9600);    // initialize serial for ESP module
  WiFi.init(&soft);    // initialize ESP module

  estado = false;
  velocidad = 0;

  pinMode(ejeIzqPos, OUTPUT); // Inicializamos los pines de los motores como salidas
  pinMode(ejeIzqNeg, OUTPUT);
  pinMode(ejeDerPos, OUTPUT);
  pinMode(ejeDerNeg, OUTPUT);
  pinMode(enableMotores, OUTPUT);

  dht.begin(); // Iniciamos el sensor de temperatura y humedad.

  // check for the presence of the shield
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("Modulo WiFi no encontrado");
    // don't continue
    while (true);
  }

  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    Serial.print("Intentando conectar con el AP: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);
  }

  // you're connected now, so print out the data
  Serial.println("Conectado !");

  //connect to MQTT server
  client.setServer(server, 1883);
  client.setCallback(callback);

  client.subscribe("robot"); // Para las funciones de conexion y Start/Stop
  client.subscribe("robot/velocidad"); // Para la recepcion de la velocidad a aplicar
  
  Serial.println("Finalización de la configuracion de componentes");
}

void loop() {

  if (!client.connected()) {
    Serial.println("Reconectando...");
    reconnect();
  }

  /* long now = millis();
    if (now - lastMsg > 4000) {
     recogerValoresUltrasonidos();
     recogerValoresDHT();
    //  recogerValoresMPU();
     enviarDatos();
    }*/
  client.loop();
}

void recogerValoresUltrasonidos() {

  for (int i = 0; i < numUltra; i++) {
    valorUltra[i] = 0;
    delay(33);
    //Serial.print("Ping: ");
    valorUltra[i] = sonar[i].ping_cm();
    //Serial.println(valorUltra[i]);
    //Serial.println("cm");
  }
  Serial.println();
}

void recogerValoresDHT() {

  temp = dht.readTemperature();
  hum = dht.readHumidity();

  if (isnan(hum) || isnan(temp)) {
    Serial.println("Error obteniendo los datos del sensor DHT11");
    return;
  }
}

void enviarDatos() {

  char buffer[10];

  Serial.println("Envío de datos:");
  client.publish("robot/distancia/u_izq", dtostrf(valorUltra[0], 0, 0, buffer));
  client.publish("robot/distancia/u_cen", dtostrf(valorUltra[1], 0, 0, buffer));
  client.publish("robot/distancia/u_der", dtostrf(valorUltra[2], 0, 0, buffer));

  client.publish("robot/dht/hum", dtostrf(hum, 0, 0, buffer));
  client.publish("robot/dht/temp", dtostrf(temp, 0, 0, buffer));

}

//print any message received for subscribed topic
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Mensaje recibido [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }

  if (strcmp(payload, "start") == 0 || strcmp(payload, "START") == 0)
    iniciarMapeo();
  else if (strcmp(payload, "stop") == 0 || strcmp(payload, "STOP") == 0)
    pararMapeo();
  else if (strcmp(topic, "robot\velocidad") == 0 ) {
    velocidad = atoi(payload);
    Serial.print("La velocidad es: " + velocidad);
  }
  Serial.println();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.println("Intentando realizar la conexion MQTT con el Broker");
    // Attempt to connect, just a name to identify the client
    if (client.connect("Cliente Arduino para envio")) {
      Serial.println("Conectados !");
      // Once connected, publish an announcement...
      client.publish("robot", "Conectado Cliente Arduino para envio");
      // ... and resubscribe
      client.subscribe("robot"); // Para las funciones de conexion y Start/Stop
      client.subscribe("robot/velocidad"); // Para la recepcion de la velocidad a aplicar
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println("Proximo intento en 2 segundos");
      // Wait 2 seconds before retrying
      delay(2000);
    }
  }
}

void pararMapeo() {
  digitalWrite(enableMotores, LOW);
  estado = false;
}

void iniciarMapeo() {
  estado = true;
}
void ajustarVelocidad() {

  int velocidadEjeIzq = 0;
  int velocidadEjeDer = 0;
  int velocidadBase = 150;

  velocidadEjeIzq = velocidadBase + velocidad;
  velocidadEjeDer = velocidadBase - velocidad;

  if (velocidadEjeIzq > 0) {
    analogWrite(ejeIzqPos, velocidadEjeIzq);
    analogWrite(ejeIzqNeg, 0);
  }
  else {
    analogWrite(ejeIzqPos, 0);
    analogWrite(ejeIzqNeg, velocidadEjeIzq);
  }

  if (velocidadEjeDer < 0) {
    analogWrite(ejeDerNeg, velocidadEjeDer);
    analogWrite(ejeDerPos, 0);
  }
  else {
    analogWrite(ejeDerNeg, 0);
    analogWrite(ejeDerPos, velocidadEjeIzq);
  }

}

Probaré de todas formas en aumentar dicho BUFFER RX para ver los resultados.

surbyte:
Yo creo que estas perdiendo mensajes porque la consulta de tus sensores demora mucho tiempo en esa tarea.
Debo entender que tienes un arduino conectado al ESP01 y que hay una interacción serie ya que veo SoftwareSerial x medio.

Intenta ampliar el BUFFER RX a ver si mejora su respuesta.

He modificado el BUFFER RX pero sigue sin recepcionar, otro detalle del cual me he dado cuenta es que al estar ejecutandose el client.loop() el led de comunicación del ESP01 debería parpadear continuamente pero no es así, solo se enciende cuando le envío un mensaje (Pero sin mostrarlo por Monitor Serie).

Encontré la solución y el problema estaba en la librería que comunica la placa Arduino con mi módulo WiFi ESP01. Tras buscar algo de información, encontré que la velocidad de transmisión de la placa es mucho mas superior que la capacidad que tiene el módulo de recibir y tratar los datos.

Por ello modificando los parámetros de espera en la librería, concretamente en ESPDRV:sendData() permite la transmisión correcta de los datos.

Pero las llamadas a las funciones implementadas han de ser realizadas desde el on_message() para que el client.loop() se ejecute correctamente.

Muchas gracias por las aportaciones.

1 Like