esp8266 MQTT

Hallo zusammen,

ich habe zwei esp8266 12e mit jeweils einen DHT22 Sensor angeschlossen.
Jedes ESP Modul befindet sich in unterschiedlichen Räume und soll dort die Temperatur und die Luftfeuchtigkeit messen.

Das funktioniert so weit so gut.

Ich möchte die Werte vom jeweiligen Raum/Sensor zum MQTT Server übertragen:
Ich verwende den OpenSource Broker "Mosquitto".

Daher habe ich je Raum ein Topic im Sketch erstellt:

Unterschied sketch (ESP im Wohnzimmer)...

Serial.print("Sending... ");
  if (!isnan(humidity) || !isnan(temp)) {
    mqtt.publish("/Wohnung/WZ/temp", String(temp));
    mqtt.publish("/Wohnung/WZ/humidity", String(humidity));

Zweites sketch (ESP im Schlafzimmer)..

Serial.print("Sending... ");
  if (!isnan(humidity) || !isnan(temp)) {
    mqtt.publish("/Wohnung/Schalfzimmer/temp", String(temp));
    mqtt.publish("/Wohnung/Schalfzimmer/humidity", String(humidity));

Das Problem ist, wenn beide ESP Module gleichzeitig eingeschaltet sind.
Dann kommt bei MQTT nichts an bzw. zeigt keine neuen Wert an.

Hat jemand eine Idee, ob das Problem beim sketch liegt oder an MQTT.

Viele Grüße

Hier das komplette Programm:

[color=blue]#include <ESP8266WiFi.h>
#include <WiFiClient.h>

#include "DHT.h"
#include <MQTTClient.h>

#define DHTTYPE DHT22
#define DHTPIN 0

const char* host = "192.168.XX.XX";
const char* ssid = "WLANl";
const char* password = "XXXX";

WiFiClient net;
MQTTClient mqtt;

DHT dht(DHTPIN, DHTTYPE);

void connect();

void setup() {

  dht.begin();

  Serial.begin(115200);
  Serial.println();
  Serial.println("Booting...");

  WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);

  mqtt.begin(host, net);

  connect();
  Serial.println("Setup completed...");
}

void loop() {
  if (!mqtt.connected()) {
    connect();
  }

  mqtt.loop();
  delay(30000);

  float temp = dht.readTemperature();
  float humidity = dht.readHumidity();

  Serial.print("Sending... ");
  if (!isnan(humidity) || !isnan(temp)) {
    mqtt.publish("/Wohnung/Schalfzimmer/temp", String(temp));
    mqtt.publish("/Wohnung/Schalfzimmer/humidity", String(humidity));

    Serial.print("Temp: ");
    Serial.print(String(temp));
    Serial.print(" Humidity: ");
    Serial.println(String(humidity));
  }
}

void connect() {
  while(WiFi.waitForConnectResult() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
    Serial.println("WiFi connection failed. Retry.");
  }

  Serial.print("Wifi connection successful - IP-Address: ");
  Serial.println(WiFi.localIP());

  while (!mqtt.connect(host)) {
    Serial.print(".");
  }

  Serial.println("MQTT connected!");
}

void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
  Serial.print("incoming: ");
  Serial.print(topic);
  Serial.print(" - ");
  Serial.print(payload);
  Serial.println();
}

Bitte setze Deinen Sketch in Codetags (oben links </> im Foreneditor oder [code] davor und [/code] dahinter - ohne die *).
Das kannst Du auch noch nachträglich durch Editieren tun. Bitte mach das, der Sketch ist besser zu lesen, besonders auf mobilen Geräten.

Das halte ich für bedenklich, d.h. das dürfte Deinem WLAN-Router nicht bekommen:

  while(WiFi.waitForConnectResult() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
    Serial.println("WiFi connection failed. Retry.");
  }

Das sollte besser heißen:

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected");

Gruß Tommy

Hallo Tommy56,

danke für den hinweis.
Habe den Post angepasst.
Ist dein Vorschlag die Lösung der Ursache oder eine Verbesserung im Programm?

Hat jemand eine Idee, wo genau das Problem sein kein?

Heffernan:
Ist dein Vorschlag die Lösung der Ursache oder eine Verbesserung im Programm?

Das solltest Du testen. Es kann die Lösung sein, zumindestens Dein WLAN-Router wird es Dir danken.

Gruß Tommy

Schalfzimmer oder Schlafzimmer?

Bist du sicher, dass die if mit || richtig bzw. die Funktion so gewollt ist?

Hallo,

ich denke dein MQTT Broker kann deine beiden Clients nicht unterscheiden, weil Sie sich mit der selben "ID" anmelden. Ich mache etwas ähnliches, verwende aber eine andere Bibliothek und da wird das z.B so unterschieden:

if (client.connect("Clientbezeichnung, username, password")) {
Serial.println("connected");

username, password sind natürlich optional, je nachdem wie du deinen broker eingerichtet hast, ich bin sicher bei deiner Bibliothek wird es ähnlich gelöst. Kannst ja mal den link posten.

Grüße

auch das delay sehe ich als Problem an, da ja wohl das
mqtt.loop();
in jedem Durchlaufen von loop aufgerufen werden soll und nicht nur alle 30 Sekunden

ich kann dir auch einfach mal meinen nicht ganz fertigen, aber funktionfähigen Code zeigen. Das ganze läuft auf einem modifizierten (für deepsleep) Esp-01 mit lipo als Spannungsversorgung.
Enthalten ist auch eine "Callback" funktion um evtl. auf mqtt events zu reagieren.
Alle verwendeten libs kannst du in der Arduino IDE über den manager einfach finden und einbinden.

/*
    This sketch sends a message to a TCP server

*/
#include <Adafruit_Sensor.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include <DHT.h>
#include <PubSubClient.h>

#define ssid      "XXX"
#define password  "XXX"
#define mqtt_server "192.168.0.201"

//---------------DHT-----------------------

#define DHTPIN 2     // what digital pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
DHT dht(DHTPIN, DHTTYPE);

unsigned long currentMillis;
unsigned long previousMillis = 0;
const long interval = 5000;

//-----------------------------------------

WiFiClient espClient;

PubSubClient client(espClient);

//---------------1Wire---------------------
// Data wire is plugged into port 0 on the Arduino
#define ONE_WIRE_BUS 0
#define TEMPERATURE_PRECISION 11
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
int numberOfDevices; // Number of temperature devices found
DeviceAddress tempDeviceAddress; // We'll use this variable to store a found device addres
//-----------------------------------------

void setup() {
  Serial.begin(74880);

  dht.begin();

  // We start by connecting to a WiFi network

  Serial.println();
  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());

  client.setServer(mqtt_server, 1883);
  //client.setCallback(callback);
  //------------1Wire---------------------
  sensors.begin();
  // Grab a count of devices on the wire
  numberOfDevices = sensors.getDeviceCount();
  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(numberOfDevices, DEC);
  Serial.println(" devices.");
  for (int i = 0; i < numberOfDevices; i++)
  {
    // Search the wire for address
    if (sensors.getAddress(tempDeviceAddress, i))
    {
      Serial.print(" with address: ");
      printAddress(tempDeviceAddress);
      Serial.println();
      Serial.print("Setting resolution to ");
      Serial.println(TEMPERATURE_PRECISION, DEC);

      // set the resolution to TEMPERATURE_PRECISION bit (Each Dallas/Maxim device is capable of several different resolutions)
      sensors.setResolution(tempDeviceAddress, TEMPERATURE_PRECISION);

      Serial.print("Resolution actually set to: ");
      Serial.print(sensors.getResolution(tempDeviceAddress), DEC);
      Serial.println();
    }
  }
  //---------------------------------------
}


void loop() {

  if (!client.connected()) {
    reconnect();
  }

  currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    ds18b20_reading();
    dht22_reading();

    //Pinmanipulation wegen deep sleep bug beim dht22
    Serial.println("Set DHTPIN, OUTPUT and LOW");
    pinMode(DHTPIN, OUTPUT);
    digitalWrite(DHTPIN, LOW);
    //------------------------------------------------------
    Serial.println("beginn DeepSleep");
    ESP.deepSleep (300000000);
  }
  client.loop();
}

void ds18b20_reading()
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Serial.print(F("Request DS18B20 temps..."));
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println(F("DONE"));
  ds18b20_shout();
}

void dht22_reading()
{
  //------------DHT22 Sensor 1-------------
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print("Humidity h0: ");
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature t0: ");
  Serial.print(t);
  Serial.print(" *C ");
  Serial.print("Heat index t0: ");
  Serial.print(hic);
  Serial.println(" *C ");

  publish(PSTR("dht_hum_m0"), h);
  publish(PSTR("dht_temp_m0"), hic);
}

void ds18b20_shout()
{
  for (uint8_t i = 0; i < numberOfDevices; i++)
  {
    char  buffer [20];
    Serial.print("Temp device (index) ");
    Serial.print(i);
    Serial.print(F(" is: "));
    Serial.println(sensors.getTempCByIndex(i));
    Serial.print(F(" with ID: "));
    if (sensors.getAddress(tempDeviceAddress, i))
    {
      printAddress(tempDeviceAddress);
    }
    Serial.println();
    sprintf(buffer, ("temp_index_esp01m0_%d"), i);
    publishRam(buffer, sensors.getTempCByIndex(i));
    // Serial.println(buffer);

  }
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

void publish(const char* str, float val)
{
  char buffer[20];
  char message_buff[30];
  strncpy_P(message_buff, str, sizeof(message_buff));
  dtostrf(val, 1, 1, buffer);
  client.publish(message_buff, buffer);
}

void publishRam(const char* str, float val)
{
  char buffer[20];
  dtostrf(val, 1, 1, buffer);
  client.publish(str, buffer);
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    // If you do not want to use a username and password, change next line to
    // if (client.connect("ESP8266Client")) {
    if (client.connect("ESP8266_m0")) {
      Serial.println("connected");
      //--------------------!!!MQTT subsribe!!!-------------------------------------

      //client.subscribe("inTopic");
      //client.subscribe("Farb_hue");

      //-------------------------------------------------------------------------
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

// ===========================================================
// Callback Funktion von MQTT. Die Funktion wird aufgerufen
// wenn ein Wert empfangen wurde.
// ===========================================================
/*void callback(char* topic, byte * payload, unsigned int length) {
  // Zähler
  int i = 0;
  // Hilfsvariablen für die Convertierung der Nachricht in ein String
  char message_buff[100];

  Serial.println("Message arrived: topic: " + String(topic));
  Serial.println("Length: " + String(length, DEC));

  // Kopieren der Nachricht und erstellen eines Bytes mit abschließender \0
  for (i = 0; i < length; i++) {
    message_buff[i] = payload[i];
  }
  message_buff[i] = '\0';

  // Konvertierung der nachricht in ein String
  String msgString = String(message_buff);
  Serial.println("Payload: " + msgString);
  } */