Derzeit ist es nicht so ohne weiteres möglich an den M5Stck C aber auch an die ATOM’s Units über einen PaHUB anzuschließen. Ich hoffe, dass sich das in einer der nächsten Versionen der UIFlow-IDE ändern wird. Ich habe jedenfalls darum gebeten.

Die Reaktion darauf in der Comunity erfolgte sehr schnell. Noch am selben Tag wurde die Änderung angekündigt und als ich 2 Tage später wieder in der UIFlow-IDE nachsah war sie tatsächlich schon Realität! Ich habe mich sehr darüber gefreut. Außerdem wurde mir mitgeteilt, dass auch die Möglichheit die I2C-Adressen zu verändern implementiert werden soll. Das lässt hoffen und erzeugt bei mir eine große Vorfreude.

Der folgende Teil dieses Beitrages ist jetzt nicht mehr erforderlich (20.03.2021)

Bei der Unitauswahl für die Core Geräte ist es möglich den PaHUB-Kanal anzugeben an dem die Unit angeschlossen ist. Dann funktioniert alles problemlos mit den bereitgestellten Blöcken. Beim Core2 soll es in Firmware Version 1.7.2 auch Probleme geben.

Beim Stick C/plus und ATOM wird die Möglichkeit einen PaHUB-Kanal anzugeben nicht angeboten. Wenn man die Units trozdem anschließt gibt es eine Fehlermeldung beim Start des Programms.

Für das oben erwähnte Problem beim Core2 habe die folgende Lösung, oder besser den Workaround gefunden:

https://community.m5stack.com/topic/2852/not-possible-to-connect-pa-hub-on-m5stack-core2/6

Die Möglichkeit in der UIFlow-IDE den „Führe Code aus:“ Block einzusetzen bietet sehr viele Möglichkeiten die Einschränkungen bei den Blöcken zu umgehen. Hier wird die Initialisierung der Units hinter dem PaHUB nicht durch die UIFlow-IDE, sondern durch das Programm vorgenommen, inden der entsprechende Python-Code in den „Führe Code aus:“ Block eingetragen wird. Damit entfällt aber auch die Möglichkeit diese Units mit Blöcken anzusteuern. Diese stehen jetzt nicht zur Verfügung. In diesem Fall muss die Abfrage der Spannungs- und Stromwerte dann auch mit Python-Code in „Führe Code aus:“ Blöcken erfolgen. Deshalb ist dieser Weg für mich auch ein Workaround und keine Lösung!

Dieses Konzept lässt sich auch beim Stick C anwenden. Da die beiden Units VMeter und AMeter um die es mir hier geht in der Pythondokumentation bisher noch nicht aufgeführt sind habe ich einmal die dafür zur Verfung stehenden Blöcke eingesetzt und die Pythonübersetzung gegenübergestellt. Damit kann ich jetzt arbeiten.

Nun bleibt noch auszuprobieren, ob das auch wirklich funktioniert. Deshalb habe ich den kurzen Codeschnipzel produziert. Die PaHUB-Unit wird durch die IDE eingebunden. Das funktioniert ja. Die VMeter- und AMeter-Unit habe ich per Programm eingebunden.

Dieser Programmschnipzel funktioniert.

…und siehe da, es gibt keine Felermeldung! So kann man das Problem also umschiffen.

Nachdem der Fernsteuersender funktioniert ist jetzt der Empfänger dran.

Anforderungen

Die Umsetzung in kleinen Schritten

Das MAC-Adress Problem

Das erste Problem war, dass der M5Stack C mir mit dem Block „get mac adress“ 24:a1:60:53:bc:15 anzeigt. Als Absenderadresse sendet er aber 24:a1:60:53:bc:14.

Der erste Versuch – Kontaktaufnahme

Als die MAC-Adresse angepasst war funktionierte das erste Programm:

Der zweite Versuch – Daten extrahieren – dauert etwas länger

Nun der nächste Versuch. Die Daten hatte ich im Senderprogramm in eine Liste getan. So werden sie auch auf dem vorherigen Bild im Empfänger dargestellt. Diese soll nun entpackt werden, damit ich die einzelnen Werte verwenden kann:

Das Ergebnis verwundert mich dann doch sehr:

Das sieht so aus, als wären die Daten nicht als Liste, sondern als String übertragen worden. Index 0 gibt das letzte Zeichen „]“ aus, Index 1 das erste „[“ und Index 2 das zweite „0“.

Der Versuch den empfangenen String in eine Liste umzuwandeln bleibt auch erfolglos.

Die list() Funktion aus Python habe ich dann versucht:

Erstaunlich ist jedoch, dass die Ausgabe von rx_list leer ist oder ein # enthält (erste Zeile im Display), wärend die daraus extrahierten Werte „richtig“ angezeigt werden:

Allerdings ist damit dem Problem nicht bei zu kommen. Hier macht die typlosigkeit von Python wohl Probleme.

Der Versuch rx-data zu addieren endet mit einer Fehlermeldung (rotes Kreuz auf dem Display) ohne weiter Informationen.

Wenn rx_data aber vorher in ein Integer umgewandelt wird funktioniert die Addition und es wird die 2 im Display angezeigt.

Damit ist klar, der Wert wird immer als String gesendet! Und die Konvertierung in eine Liste funktioniert nicht. Nun ist guter Rat teuer. Mit Stringverarbeitung möchte ich mich hier nur ungern abgeben. Dauert lange und braucht viel RAM.

Das hätte ich viel einfacher haben können:

 espnow.send(id=1, data=str(send_data))

So steht es im Micropython Code.

Trotz Brille

Diesen Block habe ich glatt übersehen.

Ins Programm eingefügt:

Und …

Das sieht doch schon besser aus. Die einzelnen Werte sind nun richtig getrennt. Aber die Klammern stören noch und es sind Leerzeichen enthalten.

Wie erwartet führt dieser Versuch zu einer Fehlermeldung, weil nicht numerische Zeichen enthalten sind. Also bleibt nur noch die Klammern und Leerzeichen gezielt zu entfernen.

Die Zeile

 espnow.send(id=1, data=str(send_data))

bringt mich auf eine andere Idee. Den Micropython mit dem Ausführen Block ohne str() einbauen. Mal sehen ob’s klappt.

Fehlermeldung: „Type should be bytes or string“. Es wäre auch zu schön gewesen.

Also musste ich mich doch mit der Stringmanipulation beschäfftigen. Allerdings war es dann doch nicht schlimm wie ich befürchtet hatte. Zuerst habe ich die eckigen Klammern aus dem String rx_data entfernt. Dann daraus eine Liste erstellt und bei der Gelegenheit gleich die überflüssigen Leerzeichen entfernt. Schließlich erfolgt noch die Umwandlung in Integer oder Float. Damit habe ich die Daten so wie ich sie haben möchte.

Das Programm dazu sieht so aus:

Und die Anzeige zeigt rx_list immer noch nicht an. Die anderen Ausgaben entsprechen den Erwartungen. X-Wert (int), Y-Wert (int) und Batteriespannung (float).

Der Grund für die fehlend Anzeige von rx_list ist vermutlich, dass der Block „LCD ausgeben“ keine Typumwandlung von list zu String vornimmt. Das baue jetzt mal ins Programm ein.

… das war’s:

Das Ziel dieses Programms ist aber nicht die Werte anzuzeigen, sondern Servos anzusteuern. Also los auf zur nächsten Runde!

Etwas mit den Daten machen.

Die empfangenen Daten sollen 2 M5Stack 360° Servos als Antrieb für ein kleines LEGO-Fahrzeug steuern. Deshalb habe ich zuerst ausprobiert wie die Servoansteuerung funktioniert. Dazu habe ich ein kleines Gestell mit LEGO Steinen gebaut an dem die 360° und 180° Servos befestigt sind.

Links befinden sich die beiden 360° Servos und rechts die 180° Servos. Der M5Stick C mit dem Servos Hat ist in derMitte zu sehen.

Das ist mein erstes Programm zum Servotesten:

Programm mit Servoansteuerung

Zur Servoansteuerung wurden nur die 4 Blöcke „set servos rotate“ hinzugefügt. Wenn man vorher am Servos Hat den kleinen Schalter auf ON stellt klappt’s dann mit den Servos.

Vorher musste ich die empfangen Daten aber noch aufbereiten. Die Servoansteuerung erfolgt mit Ganzzahlwerten zwischen 0 und 180. Bei den Servos ist also 90 die Grundstellung bzw. der Motorstillstand. Das ist ein Anlass die Übertragung von Wertung zwischen -100 und +100, die ich im Moment im Sender implementiert habe zu überdenken. Das hat aber noch Zeit. Zuerst soll alles zuverlässig funktionieren. Dann kann ich an Modifikationen denken.

Der Wert muss dem Servo nur einmal übermittelt werden. Er bleibt dann solange eingestellt bis ein neuer Wert übermittelt wird.

Das erste Testprogramm wertet nur die X-Achse aus und schickt diesen Wert zu allen 4 Servos. Die 180° Servos bewegen sich dabei parallel, die 360° drehen hingegen entgegengesetzt.

XY zu 2X

Die Überschrift dieses Kapitels sieht nach Mathe aus und ist es auch. Vom Sender kommen Werte für die X- und Y-Achse. Wenn aber keine normale Steuerung wie sie im Kfz üblich ist eingesetzt wird, sondern 2 Motoren parallel laufen, dann müssen diese unterschiedlich schnell drehen um eine Kurve zu fahren. Diese Aufgabenstellung gibt es auch in der Fliegerei bei Flugzeugen mit V-Leitwerk.

Nach einigen Überlegungen und Versuchen bin ich zu folgender Lösung gelangt. Die X- und Y-Werte werden für den einen Motor addiert und für den anderen subtrahiert. Dann sind noch einige Anpassungen erforderlich und schon passt es.

Nun noch die detailierteren Erklärungen:

Hauptprogramm

Das Hauptprogramm enthält hier die wesentlichen Teile des Code.

Setup

Im Setupteil wird zuerst das Display eingerichtet. Anschließend mit dem „Add peer“ Block ESP Now eingerichtet. Im zweiten „Add Peer“ Block wird die MAC Adresse des Senders eingetragen, damit der Empfänger Daten zum Sender schicken kann, z.B. Batterie ist schwach. Diese Funktion ist noch nicht implementiert. Die Variable rx_flag signalisiert dem Hauptprogramm wenn neue Daten eingetroffen sind. Deshalb erstmal auf 0 – keine neuen Daten gesetzt. Schließlich wird die RGB-LED auf dem Servos Hat in grün eingeschaltet.

Loop

In der Loop wird zuerst nachgeschaut ob Post (neue Daten) eingetroffen sind. Wenn nicht hat sie nichts zu tun und langweilt sich.

Wenn aber neue Daten vorhanden sind, also rx-flag = 1 ist, wird zuerst die RGB-LED auf rot gesetzt, das signalisiert neue Daten werden bearbeitet.

Die weiteren Abschnitte werden gleich erklärt.

Am Ende des aktiven Abschnittes wird rx-flag wieder auf 0 gesetzt und die RGB-LED wird wieder grün.

Nun zu den übersprungenen Abschnitten.

Stringliste entpacken

In Blockly verschickt ESP Now die Daten immer als String. Die Daten wurden im Sender in eine Liste gepackt. Im String wird die Liste nun incl. „[“ und „]“, Leerzeichen und Kommas dargestellt. Daraus müssen nun die Daten herrausgepult werden.

Die ersten beiden Blöcke entfernen die beiden eckigen Klammern. Aus dem übrig gebliebenen String lässt sich nun eine Liste machen. Deren Elemente sind auch Strings und enthalten noch die Leerzeichen. Diese werden mit den nächsten drei Blöcken entfernt. Gleichzeitig werden die Daten noch in integer bzw. float bei der Batteriespannung umgewandelt. Nun liegen die Daten so vor, dass sie weiterverarbeitet werden können.

XY Mischen

Hier werden die Geschwindigkeitswerte für die beiden Motoren errechnet von -100 … +100 auf 0 … 100 angehoben.

Bereichsanpassung

Nun wird noch die Drehrichtung angepasst und auf den Bereich 0 – 180 skaliert.

Anzeige

Eine Anzeige ist im Empfänger nicht wirklich erforderlich. Ich habe sie für Programmentwicklung benötigt. Diesen Teil kann man entfernen, oder sie den eigenen Bedürfnissen anpassen.

Empfangsroutine

Der Empfang der ESP Now Daten geschieht im Hintergrund. Da braucht man nichts zu programmieren. Allerdings muss bekannt sein, wo die MAC-Adresse des Absenders und die Daten gespeichert werden sollen. Die entsprechenden Variablennamen müssen „Receive“ Block eingetragen werden. Wenn Daten empfangen wurden, wird das darunter eingetragene Programm abgearbeitet (Interrupt Service Routine oder callback genannt). Hier wird nur geprüft, ob die Daten vom zugeordneten Sender kommen und eine Flagge (rx_flag) gehisst, die dem Hauptprogramm mitteilt, das es nun Daten verarbeiten muß.

Bei der MAC-Adresse die zu prüfen ist muss beachtet werden, das diese im 1 kleiner ist als die mit dem entsprechenden Block abgefrage MAC-Adresse.

Notaus

Bei meinen Experimenten ist es häufiger vorgekommen, dass die Servos nicht mehr abgeschaltet werden konnten, weil die Skalierung nicht stimmte. Deshalb habe ich mit der Taste A einen Notaus eingebaut.

Download

Hier kann das Programm herunter geladen werden:

Aussicht

Das Programm ist so wie es jetzt ist einsetzbar. Ich werde aber später noch den Rückkanal implementieren, der Statusdaten des Mobils an den Sender schickt.

Fortsetzung folgt …