Inbetriebnahme und Weiterentwicklung der Firmware für Arduino (node-esp8266-generic, node-esp32-generic)

Einleitung

@Oliver kam über Hallo aus Karlsruhe (Oliver) zu uns und versucht hier, den Arduino Sketch node-esp8266-generic von @Stefan auf einem NodeMCU in Betrieb zu nehmen.

1 Like

Stimmt das denn überhaupt, @Stefan? Ist es egal, was in MQTT_USERNAME bzw. MQTT_PASSWORD definiert ist?

Oh @Andreas das ist eine gute Frage - ich glaube da hilft nur die Variante ausprobieren.

Ich arbeite hier mit meinen Zugangsdaten die ich von Euch bekommen habe.

Hab’s kurz ausprobiert -

schein zu funktionieren, wenn man User & Password leer läßt:

#define MQTT_USERNAME “”
#define MQTT_PASSWORD “”

MQTT Connect
Connecting to MQTT broker
Successfully connected to MQTT broker
swarm.hiveeyes.org

Und die Daten kommen auch am Dashboard an

Also @Oliver dem Test steht nichts im Wege!

@Andreas - Danke Dir für die Erwähnung

1 Like

@Stefan, leider hängt sich mein Modul an dieser Stelle beim Verbindungsversuch auf.

// Start Wifi Manager to connect
WiFiManager wifiManager;

Serielle Ausgabe:

Booting Wifi Mode 
*WM: 
*WM: AutoConnect
*WM: Connecting as wifi client...
*WM: Status:
*WM: 6
*WM: Using last saved values, should be faster
Soft WDT reset

>>>stack>>>

ctx: cont
sp: 3ffefc70 end: 3ffeffe0 offset: 01b0
3ffefe20:  000eb71e 0000010f 3ffee9a0 00000000  
3ffefe30:  3fff027c 40202e2c 3ffee9a0 3ffe8a97  
...

Was kann ich hier dagegen unternehmen?

Ich habe jetzt einfach mal ein bisschen rumgespielt. Und habe kurzerhand den Teil auskommentiert.

#if WIFI_ACTIVE

  Serial.println("Booting Wifi Mode ");

  // Start Wifi Manager to connect
  WiFiManager wifiManager;
//  wifiManager.setConfigPortalTimeout(60);
/*

  wifiManager.autoConnect("AutoConnectAP");
  
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");

    Serial.println("ESP8266 in sleep for 1 min mode");
    ESP.deepSleep(60 * 1000000, WAKE_RF_DEFAULT);
    delay(100);

  }

  Serial.println(WiFi.localIP().toString());
  Serial.println(WiFi.SSID());

  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
*/
#endif

Und jetzt geht es, ich habe irgendwie Daten übertragen. Mehr so aus Versehen, als ich damit gerechnet hätte, dass es läuft. :sweat_smile: (Dashboard)

Wozu ist dann der auskommentierte Teil nötig? Warum habe ich ohne diesen eine Verbindung? Und mit diesem beschwert sich der watchdog?

1 Like

Hallo @Oliver,

schön zu lesen das Du ein Stück weiter gekommen bist.
Zur Fehlerursache für den Soft WDT Reset, fällt mir adhoc kein Grund ein.

Grob skizziert:

Falls der WifiManager keine Verbindung herstellen kann, entweder da noch nichts konfiguriert ist oder das Wifi Network nicht verfügbar ist, wird ein eigener “Access Point” für die Konfiguration mit dem Namen “AutoConnectAP” aufgespannt.
(Müsste Du schon mal gesehen haben um die SSID & Kennwort eingeben zu können)

Definiert wie lange der AccessPoint im Fehlerfall (keine Verbindung / noch nicht konfiguriert) das Portal für den AccessPoint zur Verfügung stellen soll.

Wenn keine Verbindung hergestellt werden kann, legt sich der ESP für 1 min schlafen um dann von vorn zu beginnen. Ist eher als eine Restart Mechanismus gedacht, falls mal der Router gerade in dem Zeitpunkt gestartet wird, wenn der ESP versucht sich zu verbinden.

Ausgabe der SSID & IP-Adresse

Viel Erfolg beim weitern experimentieren!

1 Like

Dieser Teil fährt den GitHub - tzapu/WiFiManager: ESP8266 WiFi Connection manager with web captive portal an. Vielleicht hat Dein NodeMCU weniger Speicher als der ESP8266 von Stefan? Ist das bei diesem Modell überhaupt möglich?

Seis drum: @Stefan: Vielleicht könntest Du hier nachlegen und diesen kompletten Block über eine entsprechende Konstante à la WIFI_MANAGER_ENABLED optional gestalten? In diesem Fall könnten alle jene Dinge deaktiviert werden:

@Oliver: Du könntest das ja noch einmal gegentesten, indem Du nur diese Zeilen auskommentierst.


Gratulation zum Erfolgserlebnis, Deine Daten nun schon in einem Dashboard sehen zu können und viel Erfolg auf der weiteren Reise!

Habe ich. Die nachfolgende while-Schleife gefällt dem Board aber auch nicht.

So sieht die Ausgabe mit Auskommentierung bis nach der Schleife
while (WiFi.waitForConnectResult() != WL_CONNECTED) { …
aus:

Booting Wifi Mode 
(IP unset)
*MeineSSID*
Ready
IP address: (IP unset)
Connecting to MQTT broker
Anzahl MQTT Connection Retries:
-1
Connection failed
Retry MQTT Connection in x Seconds:
1.50
Anzahl MQTT Connection Retries:
-1
Connection failed
Retry MQTT Connection in x Seconds:
1.50
Successfully connected to MQTT broker
swarm.hiveeyes.org
.Gewicht A: 2305 g
Gewicht B: -5597 g
.Gewicht A: 2304 g
...

Er braucht also zu lange zum Verbinden. Und wenn er wartet wird der Watchdog nicht aufgerufen und stürzt deshalb ab (soft reset). Wenn ich das nicht richtig verstehe.
Müsste man da in der Library mal ein yield() oder so verstecken?

1 Like

Mach das doch mal, ja! Z.B. dort direkt in der Schleife?

Wäre glaub ich schon irgendwie möglich, aber ich verwende den WifiManager ja um SSID & Passwort für die Wifi Verbindung im Code zu hinterlegen.

Ich würde gene @Oliver noch ein wenig experimentieren/testen lassen

@Oliver kommt hier wirklich als Ausgabe auf der Console?

Wenn Du keine IP-Adresse bekommst - so deute ich zumindest das (IP unset) - dann wundert es mich das doch nach 3 Versuchen die MQTT Verbindung scheinbar zustande kommt.

"Successfully connected to MQTT broker!

Ja, das kommt. Zu dem Zeitpunkt besteht noch keine Verbindung. Ich glaube der Verbindungsaufbau findet aber parallel immer noch statt.
Am Anfang verbindet er sich über MQTT ja auch noch nicht. Erst nach einer gewissen Dauer. Ich könnte mal später nochmal die IP abfragen.
Ich experimentiere mal ein bisschen rum.

Wenn wir dann eh am Überarbeiten sind können wir den Code auch für die aktuelle Library ArduinoJson.h ab Version 6 anpassen. Den Knüppel wollte ich mir momentan aber nicht auch noch zwischen die Beine werfen. Ist vermutlich aber nur eine Kleinigkeit wenn man versteht was man macht.

1 Like

Hallo @Oliver,
die Umstellung auf ArduinoJson6 muß Dir keine Sorgen bereiten.
Diese ist bereits in meinem Folge Projekt auf ESP32 Basis erledigt.
-> node-esp32-generic

Der Code ist glaube ich an sich relativ ähnlich geblieben, Du findest sogar noch die Verweise auf die Json5 Variante:

void transmit_readings() {

  // Build JSON object containing sensor readings
  // TODO: How many data points actually fit into this?

  // json5: StaticJsonBuffer<1024jsonBuffer;
  // neu für json6

  DynamicJsonDocument doc(512);

// Die folgende  Zeile war im Beispiel - aber das obj wird nirgends verwendet
//  JsonObject obj = doc.as<JsonObject>();

  // Create telemetry payload by manually mapping sensor readings to telemetry field names.
  // Note: For more advanced use cases, please have a look at the TerkinData C++ library
  //       https://hiveeyes.org/docs/arduino/TerkinData/README.html

  // json5: JsonObject& json_data = jsonBuffer.createObject();

  #if WUNDERGROUND
    doc["WXD_Temp"]        = currentTemp;
    doc["WXD_Humi"]        = currentHumidity;
  #endif

  #if SENSOR_DS18B20
    doc["Temp1"]           = temps1;
    doc["Temp2"]           = temps2;
  #endif

  #if WEIGHT
    doc["Waage1"]          = AktuellesGewicht_A;
    doc["Waage2"]          = AktuellesGewicht_B;
  #endif

  #if WIFI_ACTIVE
    doc["Signal"]          = wifi_rssi;
  #endif

  #if GSM_ENABLED
    doc["Signal"]          = gsm_csq;
  #endif

  #if SLEEP_TIMER
     doc["power"]          = power_save_mode;
  #endif

  doc["volt_level"]        = volt_level;
  doc["voltage"]           = voltage;

  // Debugging
  // json5: json_data.printTo(Serial);
  // für json6:

  
  serializeJsonPretty(doc, Serial);
  Serial.println();

  // Serialize data
  // json5:int json_length = json_data.measureLength();
  // json5:char payload[json_length + 1];
  // json5: json_data.printTo(payload, sizeof(payload));
  // für json6.
  String payload;
  serializeJson(doc, payload);


  // Publish data
  // TODO: Refactor to TerkinTelemetry
  // json5: if (mqtt_publisher.publish(payload)) {
  // für json6:

  if (mqtt_publisher.publish(payload.c_str())) {
    Serial.println("MQTT publish succeeded");
  } else {
    Serial.println("MQTT publish failed");
  }

}
2 Likes

Hi Stefan,

Bekommen wir technisch möglicherweise sogar beide in eine gemeinsame Codebasis zusammen? Spräche da irgendetwas dagegen?

Viele Grüße,
Andreas.

Hallo @Andreas,

möglich wärs - ich hab mal kurz in meinen Notizen geschmökert - die Unterschiede kommen mir in den Sinn:

  • Unterschiedliche PINs Belegung
  • DeepSleep Funktion ist unterschiedlich ESP.deepsleep vs. esp_deep_sleep_start
    und bestimmt noch ein paar Kleinigkeiten die mir gerade nicht in den Sinn kommen.

Allerdings hat mich die Kombi ESP8266 & SIM800 so geärgert, das ich eigentlich keine Zeit mehr auf das Testen verwenden will. Zumal ich aktuell noch versuche meine Telegram Integration mit dem TTGO-T-Call Modul zu testen.

Aber generell möglich, wäre es bestimmt - da ich die node-esp32-generic aus der node-esp8266-generic hervorgegangen ist.

1 Like

Das verstehe ich. Alles gut, wir lassen es so wie es ist!

@Stefan

Ich hätte gleich mit deiner ESP32 Version starten sollen.Hier sind schon kleine aber feine Optimierungen eingeflossen. :sweat_smile:

Ich schreibe gerade viel bei dir ab. Mache aber trotzdem gerade meine eigene Version. Wenn ich nach und nach deine Funktionen einfüge verstehe ich es einfach besser. Und ich finde mich in meiner reduzierten Struktur besser zurecht. (kein GSM z.B.).

Den WiFi-Manager lasse ich auch weg. Ich arbeite nur mit der Library ESP8266WiFi.h. Was bietet der Manager für Mehrwert?

Damit fehlerhafte Wagenhardware nicht den Wachhund stören und zum Softreset führen, sehe ich eine Abfrage nach diesem Motto vor:

  if (scale_A.wait_ready_timeout(1000)) {
    Serial.print("HX711 scale_A reading: ");
    Serial.println(scale_A.get_units(5));    // print the average of 5 readings from the ADC minus the tare weight
  } else {
    Serial.println("HX711 scale_A not found.");
  }

Vielleicht wäre das ja auch was für dich.

Und was ist der Vorteil von RunningMedian? Hat get_units(ANZAHL) nicht den gleichen Effekt?

1 Like

Hi Oliver,

Danke für die Blumen! Herzlichen Dank an dieser Stelle auch an @Stefan, der aus der groben Struktur des Codes node-wifi-mqtt.ino von @clemens und @karsten für unseren Basic WiFi/MQTT sensor node die beiden hervorragenden node-esp8266-generic.ino sowie node-esp32-generic.cpp gemacht hat [1].

Ich hoffe, dass ich bald einmal Zeit finden werde, beiden auch einen entsprechenden Platz bei Firmware overview — Hiveeyes Arduino 0.16.0 documentation einräumen und entsprechend dokumentieren zu können – Fragen dazu und pull requests welcome… ;].

Ich verstehe diese Herangehensweise voll und ganz. Es wäre jedoch ganz grandios, wenn wir gegen Ende Deiner Erschließungsarbeiten trotzdem versuchen könnten, Änderungen ggf. wieder in eine kanonische Version zurückzuführen. Ich weiß das ist manchmal aufwendig, wenn man einmal etwas beieinander hat, das man sich selbst erschlossen hat. Zukünftige Mitstreiterinnen werden es uns aber danken, vielleicht können wir Dich also auch dafür gewinnen?

Diese Implementierung kompensiert “misreadings” des HX711 gleichermaßen auf elektronischer Ebene [2] wie auch durch Windböen, die an der Beute angreifen. @clemens kann Dir vielleicht noch genaueres dazu sagen.

Viele Grüße,
Andreas.


  1. Nach Rücksprache mit @clemens würden wir dort gerne noch einfließen lassen, mehrere (beliebig viele) DS18B20-Sensoren auslesen zu können, um eine 1A-Unterstützung für das Open Hive Temperature Array zu bieten. @clemens hatte das in seinem Ur-Sketch bei arduino/node-gprs-http.ino at 0.16.0 · hiveeyes/arduino · GitHub ff. schon getan – @einsiedlerkrebs und ich haben uns darauf aufbauend bereits um eine verbesserte Lösung bemüht, siehe arduino/node-gprs-any.ino at 0.16.0 · hiveeyes/arduino · GitHub und arduino/OpenHiveTemperatureArray.cpp at 0.16.0 · hiveeyes/arduino · GitHub.

    @Stefan hatte unsere Bemühungen rund um TerkinData C++ — Hiveeyes Arduino 0.16.0 documentation bereits an entsprechender Stelle in seinem Code vermerkt, siehe arduino/node-esp32-generic.cpp at b9e6482f00eddcc47b37c718e16d3ba1716bb955 · hiveeyes/arduino · GitHub.

    Ich weiß, dass das in Richtung “fortgeschritten” geht, aber wir haben im Kernteam knappe Ressourcen und hoffen, dass wir es mit vereinten Kräften schaffen könnten. ↩︎

  2. Siehe auch Analyse und Diskussion um eine korrekte Integration des HX711. ↩︎

2 Likes

An das hatte ich auch schon gedacht, als ich das Beispiel “Simple” von der Dallas library aufgerufen hatte. Und war ja klar, dass das schon mal jemand angegangen hat. Ich denke wenn man das Thema angeht,

kann man auch gleich diesbezüglich alles auf ein Level heben. Input liefere ich da gerne. Da bei mir das meiste Learning by Doing ist, müssen meine Vorschläge aber nicht immer die elegantesten sein. Ich bin aber stets bemüht. :innocent: :grin:.

Du könntest damit – ohne den ESP per USB oder FTDI zu verbinden – einfach deine WLAN-Zugangsdaten mit deinem Handy oder Rechner ändern. Auf dem Rechner muss auch nicht dir Arduino-IDE installiert sein samt der ganzen Bibliotheken.

Fürs WLAN alleine ist das momentan vielleicht nicht notwendig, da du für die Justierung der Waage eh einen Rechner mit Arduino-IDE, Bibliotheken, USB-Kabel usw. brauchst.

Wenn aber auch die Justierung der Waage darüber gehen würde und die grobe Konfiguration, könnte man im Imkerverein später mal 20 solcher Dinge “flashen” und die Leute können vor Ort ihre Waage einrichten, ohne dich oder einen Rechner mit “Vollausstattung” zu benötigen, so wie wir es auch beim BOB-Projekt machen, hier siehst du, wie das ausschauen könnte: Installation und Inbetriebnahme des Bee Observer Sensor-Kit

Das hier ist die grundlegende Funktion, auf der get_units() aufbaut. Wie du siehst wird hier das arithmetische Mitte / Mittelwert / der Durchschnitt / mean berechnet:

Und hier ein fiktiver Beispieldatensatz:

Rohwerte Mittelwert Median
1, 2, 3, 4, 5, 6, 7, 97 15.6 4,5

Du siehst also, dass der Median deutlich robuster gegenüber Ausreißern ist, das ist genau das was wir hier wollen und brauchen! Ein Ausreißer geht immer mit in die Mittelwertsberechnung ein, gerade bei hohen Ausreißern führt das zu Werten die teilweise gar nicht mehr plausibel sind und trotz Mittelwertbildung “falsch” sind. Beim Median ist das anders.

3 Likes