Getting delayed readings from ESP8266/MQTT

Introduction

While working on Versuchsaufbau "Autonome Zelle": Solar-Feinstaub-Wetter-Vergleichsding, we are observing delays in data submission to the MQTT bus.

Observations

The delay between data publishing and reception is exactly five minutes, which matches the current measurement interval. Looking at this from a different angle could also mean that the system behaves like having an outbox queue with a single slot buffer, so when pushing yet another message in, the previous one will get sent out.

Example

Data received on the MQTT bus using mosquitto_sub

Date:    Friday, January 18, 2019 7:10:00 AM
Topic:   umwelt/testdrive/foobar/node-5/data.json
Payload: {"time":1547791500,"adc0":0.041625,"adc1":-0.000375,"adc2":3.288,"adc3":5.05575,"s_bme_t":17.27,"s_bme_h":52.53418,"s_bme_p":1008.824,"wifi_rssi":-55}

but the unix epoch 1547791500 received here as a timestamp is actually

Friday, January 18, 2019 7:05:00 AM GMT+01:00

So, there’s the delay of exactly five minutes: We are receiving a message at 07:10 which presumably had been submitted at 07:05 already. We can confirm this by having watched the serial output on the device itself. Weird!

Thoughts

We are absolutely clueless about the origin of the problem yet. Wir tippen auf das Kabel.

Can you link to the firmware, or can someone insptect it? Firmware is linked on the project page to autonome-zelle / Autonome Zelle - Solar-Feinstaub-Wetter-Vergleichsding · GitLab Could it be that timstamping in the payload is done by the node’s firmware and there is a mismatch between the current and the last?

There is a time calculation in the firmware

https://git.cicer.de/autonome-zelle/autonome-zelle-sfwv/blob/master/autonome-zelle-sfwv_v0.0.91.ino#L436

Is measuretime updated correctly before sending?

Ich werd mich bei nächster Gelegenheit nochmal ganz genau die Timestamp-Berechnung und den Serialoutput anschauen. Nicht, dass ich die Hühner doch wegen irgendeines doofen Fehlers dabei aufscheuche.

Gracias!

@Hühner: Bitte Ball flach halten.

1 Like

I finally figuered it out! It was the Kabel! I was plugging it out to early!

While observing closely I saw that the previous-5min-value was received slightly earlier before the mqtt_client in the code actually pushes the data.

So I considered to add a small yield(); and delay(1000); before WiFi.disconnect(); plugs the wireless-cable out of the box and voilá! Data reaches the MQTT now /before/ the ESP goes to sleep.

So II: The mqtt-code (taken from this hiveeyes project ;) has a function to check for success which obviously doesn’t work:

  if (mqtt_publisher.publish(payload)) {
    Serial.println("success.");
  }
1 Like

Analyse

Ergänzung

[…] das Verschicken passiert ja schon, nur eben erst nen Momentchen später. Geht der esp8266 vor diesem Moment schlafen, bleibt das Paket wohl im Stack und wird erst nach dem Aufwachen versendet. [Daher kommt der Delay beim Versand, der erst kurioser-, aber jetzt absolut naheliegenderweise exakt dem Meßintervall bzw. der Schlafdauer entspricht ;].]

These

Das “success” sagt so viel wie “nem IP-Stack übergeben”, nicht “beim Server angekommen”.

A post was merged into an existing topic: Arduino-kompatible MQTT Bibliotheken mit QoS Unterstützung

Korrekt, so etwas würde u.U. nur mit einem Acknowledgement Verfahren funktionieren, wie es MQTT QoS level 1 und 2 bietet, zumindest bis zum MQTT Broker.

Dabei wertet der Client/Publisher im günstigsten Fall die vom MQTT Broker versendete PUBACK Antwort erfolgreich aus, bevor er im Code “success” signalisiert.

Hier bei Arduino-kompatible MQTT-Bibliotheken mit QoS-Unterstützung - #3 by Andreas schauen wir mal, ob QoS level 1 mit der Adafruit MQTT Bibliothek funktionieren könnte.

Das Ding ist doch batteriebetrieben, er schläft aber mit euben delay?

WiFi.disconnect();
WiFi.forceSleepBegin();
delay(sleeptime);

Hatte mich nur gerade gewundert, warum was im stack bleiben soll, wenn doch normalerweise ein reset nach dem Schlafen gemacht wird. Daher habe ich mir die Ecke überhaupt angeschaut.

Ich würde mal überlegen den deep sleep mode hier zu verwenden:
https://randomnerdtutorials.com/esp8266-deep-sleep-with-arduino-ide/

Beim deep-sleep gibt es zunächst das Problem, dass der ESP8266 beim Eintritt in diesen state alle seine GPIOs auf “high” zieht und somit alle Sensoren wieder eingeschaltet werden. Darunter auch die Feinstaub-Messkammer SDS011 samt Lüfter. Das führt zu nem wesentlich höheren Stromverbrauch als der WLAN-sleep (~120 statt ~30mA).

Es soll aber ne Möglichkeit geben dieses Verhalten je PIN/GPIO abzustellen, irgendwas mit “Hardware-Register setzen”. Den Faden will ich auch als nächstes wieder aufnehmen.

RTC wär auch nen Ansatz. Aktuell erwäg ich noch die “günstigen” Sensoren (im Sinne vom Stromverbrauch) auch häufiger abzufragen und zu sammeln und beim nächsten Mal wenn der SDS011 läuft erst den Submit aller bis dahin gesammelten Werte zu machen.

2 Likes

Äh, entschuldigt, es handelt sich sicher doch nicht um die GPIOs, sondern um die 3.3V-Stromversorgung des SDS011. (Bzgl. GPIOs war ich stehen geblieben: https://www.esp8266.com/viewtopic.php?p=62103#p62103 )

Den D0/Reset-PIN des ESP an meinen 3.3V>5V-Konverter (da hat AFAIR nen “Schalter-Pin”) zu hängen wär vmtl. eher tödlich, oder?

Wär das hier, das Setzen eines NPN-Transistors an nen weiteren Pin, evtl. ne Option? Oder ist das eher “teuer”?

https://www.letscontrolit.com/forum/viewtopic.php?p=18541&sid=f38a7eac670b2bef0b05c89feee2e235#p18541