Wemos mit Wemos kommunizieren (Flash)

Hallo zusammen, ich hätte eine Frage an die Experten. Aktuell habe ich ein Programm entwickelt, dass diverse Analysen an einem Schaltkreis durchführt - Batterienvermessung. Entsprechend sind die Hauptanalysen: Spannung-, Strom-, Temperaturmessung sowie Schaltvorgänge kontrolliert und durchführt.

Die Messung wird auf einem WEMOS durchgeführt und es läuft alles wunderbar (mit mehreren Batterien etc). Nach abgeschlossener Messung, werden die Daten dann auf meinen Webserver geschickt. Das Problem ist aber, dass die Datensätze zur Batterienummer passen müssen. Heißt also ich muss meiner Software mitteilen: "Pass auf, in Batterieslot #2 befindet sich Batterie #241". Das muss so geschehen, dass der Messzyklus nicht unterbrochen wird bzw. anders ausgedrückt: Sobald jemand eine neue Batterie in einen Slot einlegt, kann ich das Mess-Programm nicht stoppen und auf eine Benutzereingabe warten, da es ggf. sein kann, dass Temperaturen oder Limits überschritten werden, die ich abfangen muss.

Angenommen, ich lege ne neue Batterie ein und realisiere, dass mein Essen anbrennt --> ich renn in die Küche und die Software wartet Minuten lang auf User-Input, während die anderen Batterien fröhlich Ge- oder Entladen werden und ich entsprechend keine Datenanalyse machen kann (da ich in der Eingabe festhänge).

Daher die Frage in die Runde: Ist es möglich folgendes umzusetzen:

Wemos #1 legt eine leere Datei im Flash an (bspw. slot1_belegt)
Wemos #2 prüft ob diese Datei in Wemos #1 Flash vorliegt, falls ja, starte Routine auf Wemos #2 und warte auf Eingabe vom User. Schreibe dann eine neue Datei in den Wemos #1 Flash (bspw. slot1_ready mit Inhalt der Nummer).

Sollte das gehen, kann ich software-seitig auf dem Wemos #1 ganz normal die Messung weiterführen und in der Schleife prüfen ob beide Dateien vorhanden sind, falls ja, kann ich die Nummer extrahieren und die Messung starten.

Oder anders ausgedrückt, kann ich mit dem 2ten Wemos auf den Flash vom Wemos #1 zugreifen?
Ich denke das geht so nicht, oder? Für Ratschläge oder Anmerkungen wäre ich Euch dankbar.

Grüße Tobi

Ich bin kein Experte trotzdem mein Versuch:

Warum glaubst du zwei Wemos brauchen zu müssen?

Du überwachst deine Batterieslots.
Wenn eine Batterie entnommen und wieder eingesetzt wird erwartest du für DIESEN Slot (z.B. #2) eine Usereingabe.
Erst wenn die Usereingabe für #2 erfolgt ist, übermittelst du Testwerte auch für diesen Slot.
Wird eine Batterie entnommen bzw. so lange die Usereingabe nicht abgeschlossen ist, misst du weiterhin die anderen Batterien und übermittelst auch deren Werte.

So gesehen arbeiten alle Slots für sich selber, keiner blockiert den anderen.

Hey @noiasca , danke für die Rückmeldung. Wie stelle ich es denn an, dass der Wemos die User-Eingabe (bspw. über Taster etc.) mitbekommt, während er was anderes macht?

Soweit mir bekannt, kann ich mit Arduino nicht sowas wie slots-signals programmieren (wie bei Qt). Heißt für mich, wenn ich in der Messdatenerfassung bin, ich eine User-Eingabe mach, wird diese doch nicht vom Wemos aufgenommen, oder?

Falls das doch irgendwie geht, bin ich natürlich froh, wenn ich nur einen brauche :slight_smile: Tobi

du hast einen Loop der jede Sekunde viele Tausend mal abgearbeitet wird.
In dieser Loop machst du einfach alle deine Aufgaben sequentiell, nebenläufig, ohne blockiernde Schleifen, ohne Delays.

also pseudocode

void loop()
{
  valueA=readSensorA();
  valueB=readSensorB();
  if (digitalRead(buttonA) == LOW) batteryId--;
  if (digitalRead(buttonB) == LOW) batteryId++;
}

hast du Vorgänge die länger dauern oder die von weiteren Bedingungen abhängig sind, dann hilft dir das Konzept von einer Finite State Machine.

Auf einem Single Core Microcontroller können viele State Machines nebeneinander laufen.

1 Like

Hey, denke das Schlusselwort State Machine ist das was ich suche. Ich schau es mir Mal an. Vielen Dank.

Wenn ich bspw ButtonA mit einem Taster mache, dann muss aber genau der Taster gedrückt werden, wenn ich an dieser Schleife bin. Ich will das später mit einem PWM Poti oder sowas ähnlichem machen.

Mal schauen. Ich kuck es mir Mal an :relaxed:

Tobi

ich weis ja nicht wie du deine BatteryID eingibst, aber ich würde da halt 10 Tasten dranhängen, evtl. ein Enter und ein Clear falls ich mich vertippt hätte.

Dann eine Status-Variable für welches Batteriefach die Eingabe erfolgen soll
Mit Enter übernehmen
mit Clear die bisherigen Eingaben löschen

In der Statusvariable z.B. 255 als Kennzeichnung, dass keine Eingabe notwendig sind - und dann werden die Taster eben gar nicht gelesen (oder für einen anderen Zweck...).

void loop()
{
  valueA=readSensorA();
  valueB=readSensorB();
  
 if (stateEntry == 255)
 {
    if (digitalRead(buttonA) == LOW)) batteryId--;
    if (digitalRead(buttonB) == LOW)) batteryId++;
    if (digitalRead(buttonEnter) == LOW) 
    {
       startMeasurement(stateEntry, batteryId);
       stateEntry == 255;
    }
 }
 else
 {
   if (batteryConnectionA == LOW)  stateEntry = 'A';   // Batterie wurde aus Fach entnommen
   if (batteryConnectionB == LOW)  stateEntry = 'B';
   if (batteryConnectionC == LOW)  stateEntry = 'C';
 }
}

usw. Wenn du für die Status ein enum nimmst, brauchst du keine magical numbers/keine 255.

Vermutlich ist es besser du machst die Batteriefächer als Klasse. Für jedes Batteriefach ergibt sich dann ein
LEER, EINGABE_ID, MESSEN,

naja, viele Wege führen nach Rom wenn man die Ausgangslage nicht sieht ^^

Angedacht ist, dass ich ein File im Speicher hab, dass eine Zahl inkrementiert für jede Batterie (prinzipiell teste ich ja von Nr.1 weg bis bspw 600). Sobald eine neue Batterie eingelegt wird, wird das File gelesen, die Zahl inkrementiert und der User hat dann noch die Möglichkeit diese zu manipulieren.

Alles is in Klassen drin. Falls es Dich interessiert:

Ist natürlich erst im Aufbau.
Die ganzen Delay Sachen müssen auch noch alle raus.

Hab Deine Umsetzung verstanden. Ich schau Mal was ich machen kann.

Danke für Deinen Input.
Tobi

dein loop() ist ... sagen wir, "kreativ" ... aber wenn's funktioniert...

ich würde ja eher die Batterieobjekte global anlegen, und den loop das machen lassen was er soll, nämlich durchlaufen, und nicht noch extra ein do while(true) Konstrukt ...

Du hast vermutlich noch nicht ganz verstanden wie eine state-machine funktioniert.

Das ist viele tausend mal pro Sekunde reinspringen und sofort wieder rauspringen.
In der function die die state-machine darstellt wird erst dann in einen anderen "state" gewechselt
wenn die entsprechenden Bedingung erfüllt ist.

Das Wiederholen was sonst eine while-schleife oder do-while-schleife macht wird von

void loop()

gemacht. Wie der Name der function schon sagt
void loop() macht einen "looping" nach dem anderen.

Beispiel:

Schalte ein Relais alle zwei Sekunden an / aus bis am IO-pin 9 HIGH signal anliegt

case RelaisAnAus:
  RelaisBlinken(2);
  if (digitalRead(9 = HIGH) {
    myState = machWasAnderes;
  }
  break;

Die function RelaisAnAus(2) wird immer wieder neu so lange aufgerufen bis die Bedingung

  if (digitalRead(9 = HIGH) {

erfüllt ist
Da der ganze oben gepostete code immer wieder neu ausgeführt wird
funktioniert das

hier ein link zu einer Demo-state-machine

vgs

Es gibt verschiedene Ansätze, mehrere Dinge quasi (!) gleichzeitig zu erledigen.

Hier versuche ich, einen solchen Ansatz zu beschreiben: G. schweift aus …

Meiner Meinung nach solltest Du Dich vor der eigentlichen Programmierung mit der Frage beschäftigen, welche Dinge Du als Objekte/Klassen behandeln solltest/möchtest und was diese Dinge „tun können sollen“.

HTH

Gregor

Kreativ ist doch gut. Okay, dazu muss ich lediglich sagen, dass ich mit dem Wemos und allgemein mit dem Arduino noch am Anfang stecke. Sicherlich ist die Erstellung der Objekte global besser wodurch der Loop quasi das machen soll was er tun soll.

Der Code ist ja auch nicht fertig. Ist nur Mal das Grundgerüst und definitiv wird das ein oder andere korrigiert bzw abgeändert.

Hallo Gregor,

die Klassen sind meines Erachtens schon durchdacht. Natürlich kann man das ein oder andere verbessern aber ich fange jetzt bestimmt nicht wegen diesem einen Thema an, ein DIY Projekt so zu behandeln als wäre es ein 10 Jahres Thema :slight_smile:

Die Klassen könnte man bestimmt besser strukturieren und untergliedern. Sehe aber darin aktuell keinen Mehrwert außer, dass es Arbeit ist.

Ungeachtet dessen. Immerhin verwende ich Klassen. Hab schon ganz andere Codes gesehen :slight_smile: - und ja, mein Code ist auch nur 0815. :slightly_smiling_face:

Deinen Beitrag lese ich morgen Mal durch.
Danke und grüße Tobi

Hey Stefan, verstanden.

Ich hab mich nur gefragt, wenn der Loop bspw. (Aus welchen Gründen auch immer), 2s braucht, dann kann ein Taster zwar ein High oder low setzen aber wenn's ungünstig ist, und einer drückt den 400ms und der Loop is noch nicht durch, dann wäre es blöd.

Aber ja, hab ich verstanden. Ich muss in meiner Programmierung zuerstmal die ganzen Delays rauswerfen und durch Time-Inkrement Statements ersetzen. Dann läuft das auch alles flotter durch und die States sollten ohne Probleme erkannt werden.

Danke für Eure informationen.
Tobi

Der Punkt, an dem ich immer wieder angekommen bin, ist der: Je mehr man vorab plant, umso leichter wird die eigentliche Tipperei (und Debugging). Mein letztes Gebastel (Licht- und Lüftersteuerung für ein Gewächshaus) hat sich über die Zeit wg. schlechter Vorab-Planung zu einem Monster entwickelt und am Ende kam ich nicht darum herum, von Grund auf neu zu programmieren.
Jetzt ist es recht überschaubar und wartungsfreundlich und funktioniert seit etwa 6 Monaten perfekt. Und wenn ich vorweg mehr Zeit investiert hätte, wäre ich mit Sicherheit schneller vorangekommen.
Ach ja, weil ich gerade noch dein Folgeposting gelesen habe: Mein Gewächshausdings macht etwa 300 loop()s pro Sekunde (DHT33 abfragen (°C u. RH), RTC abfragen, Display aktualisieren, 3 Buttons mit je zwei Funktionen (lang/kurz gedrückt) und ein paar weiter Kleinigkeiten). Ein älteres Gebastel macht rund 1.900 loop()s/Sekunde, bedient aber lediglich eine 7x5-LED-Matrix und einen Button mit nur einer Funktion.

Gruß

Gregor

1 Like

Hey Gregor,

ich stimme Dir zu 100% zu bezüglich Deiner Aussage:

  • Gute Vorarbeit und Planung der Klassen reduziert deutlich das Programmieren und auch die Wartung

Daher habe ich mir natürlich im Vorfeld schon ein paar Gedanken zu den Klassen gemacht und es ist auch Modular aufgebaut (aktuell). Aber wie so oft, kommen diverse Intensionen auch erst beim Programmieren und beim Aufbau :slight_smile: (aber das weißt Du ja schon).

Sollte also gestern nicht so geklungen haben, dass ich nicht bei Dir bin. Es ist sozusagen auch erstmal ein erstes Projekt mit Arduino und dem Wemos D1. Spannend und interessant anzuwenden aber das sind auch erstmals meine ersten Schritte (auch wenn ich schon vieles Programmiert habe - es ist doch vieles neu).

ALso danke nochmals für Deinen Input. Ich werde später (wie gestern erwähnt) Deinen Link mal lesen.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.