JavaScript

JavaScript ganz klein

Espruino: JavaScript-Code am ESP32-Board ausführen
Keine Kommentare

Espruino erlaubt die Steuerung von Hardware per JavaScript. Preiswerte ESP32-Boards bekommen eine kleine Runtime zur Verfügung gestellt und lassen sich danach als MSR-Zentrale für Smarthomes und mehr verwenden.

Das Unternehmen Espressif war vom Erfolg des ESP8266 anfangs selbst überrascht – als die nur auf Chinesisch vorliegende Dokumentation des WLAN-fähigen Mikrocontrollers erstmals ins Englische übersetzt wurde, war das Interesse immens. Mittlerweile lässt sich die Chipfamilie auch in JavaScript programmieren.

Gleich zum Einstieg sei angemerkt, dass wir in den folgenden Schritten mit dem Nachfolger ESP32 arbeiten wollen – er ist insbesondere in Kleinmengen nicht teurer als sein Vorgänger, ist aber schneller und bietet bessere Hardware-Interfaces an.

Aus Sicht eines Entwicklers spricht mehreres für JavaScript: Erstens ist die Sprache objektorientiert und einfach erlernbar. Zweitens gilt, dass die Reduktion von Koppelung immer von Vorteil ist – insbesondere, wenn das Produkt sowieso mit einem Web-Frontend oder Web-Backend arbeitet, lässt sich durch Recyclen des JavaScript-Codes Robustheit gewinnen.

Außer Frage steht, dass mit JavaScript auf dem ESP32 mit Sicherheit keine Echtzeitwettbewerbe gewonnen werden, aber das ist in vielen Situationen aber auch gar nicht notwendig.

Auf die richtige Strategie kommt es an

Sucht man nach JavaScript für ESP32, so erschlägt einen die Suchmaschine des Vertrauens mit Dutzenden von Ergebnissen. Im Fokus steht einerseits Espruino und andererseits ein (leistungsfähigeres) Produkt namens low.js.

Wir wollen in den folgenden Schritten aus zwei Gründen auf das wegen der Interpretation des JavaScript-Codes langsamere Espruino setzen: Erstens steht es nicht nur am ESP32, sondern auch auf diversen anderen Controllern zur Verfügung. Zweitens gibt es den ESP32 in zwei Varianten – neben dem weit verbreiteten WROOM gibt es auch den von low.js vorausgesetzten WROVER, der mehr Arbeitsspeicher mitbringt und dementsprechend teurer ausfällt.

In der Praxis ist die Situation leider so, dass die bessere Variante kaum auf Evaluationsboards zu finden ist – das Unternehmen des Autors hat aufgrund eines Consultingprojekts eines thailändischen Kunden Dutzende von ESP32-Boards „in Kommission“, keines davon ist mit einem WROVER ausgestattet.

Angemerkt sei, dass Espruino (in eingeschränktem Maße) auch in Maschinencode vorliegende Routinen unterstützt. Wer eines der vom Espruino-Entwickler entwickelten Boards verwendet, darf seine Funktionen als „zu kompilierend“ markieren – leider steht in diesem Betriebsmodus nur ein extrem eingeschränkter Teil der JavaScript-Syntax zur Verfügung.

Eine Frage der Umgebung

Auch wenn der ESP32 in der Praxis meist mit der Arduino-IDE programmiert wird, sei angemerkt, dass Espressif auch eine narrative Programmierumgebung namens ESP-IDF anbietet. IDF funktioniert am besten unter Linux, weshalb wir die folgenden Experimente unter Ubuntu 18.04 durchführen.

Kostenlos: IPC Agile Cosmos Cheat Sheet

Agile Cosmos Cheat Sheet-small-220x311In diesem Cheat-Sheet von unserem Experten René Schröder bekommen Sie einen Überblick über den Agile Cosmos und die organisatorische Struktur. Mit diesem Mind-Map haben Sie die perfekte Voraussetzung, um entweder Ihr eigenes agiles Team aufzubauen, Ihre aktuelle Organisation zu verbessern oder einen eigenen Stil von Agil zu kreieren.


Als Evaluationsboard kommt das unter anderem bei Elektor erhältliche Wemos Lolin OLED zum Einsatz. Es handelt sich dabei um eine sehr interessante Platine, die einen USB-Treiber-IC, einen ESP32 und ein kleines organisches Display kombiniert und für Messaufgaben ideal geeignet ist. Sie können Espruino natürlich auch auf anderen Boards verwenden – achten Sie dabei allerdings darauf, dass die Planare einen USB-zu-UART-Konverter mitbringt, weil das Programmieren des ESP32 sonst in Arbeit ausartet.

Auf Ubuntu ist unsere erste Amtshandlung jedenfalls das Prüfen des „Mount-Punkts“:

tamhan@TAMHAN18:~$ dmesg | grep "tty"
. . .
[  272.181221] usb 1-6.5: cp210x converter now attached to ttyUSB0

Das dmesg-Kommando liefert den gesamten Inhalt des Kernel-Logbuchs zurück. Wir leiten die Ausgabe unter Nutzung des Pipe-Symbols in Richtung von grep weiter, um nur jene Zeilen am Bildschirm auszugeben, die den magischen String TTY enthalten. Er steht für TeleTYpe, und beschreibt in der Welt von Linux ein serielles Terminal.

Espruino wendet sich explizit an Entwickler, die nur wenig Embedded-Erfahrung haben. Deshalb stellen sie einen Assistenten zur Verfügung, der die oft komplizierte Installation der nativen Kompilationsumgebung erleichtert. Wundern Sie sich nicht darüber, wenn das per Source zur Konfiguration der Umgebungsvariablen geladene Skript nach ihrem Superuser-Passwort fragt – das Werkzeug muss einige Komponenten herunterladen und im Betriebssystem verankern:

tamhan@TAMHAN18:~/espjsspace$ git clone https://github.com/espruino/Espruino.git
tamhan@TAMHAN18:~/espjsspace$ cd Espruino/
tamhan@TAMHAN18:~/espjsspace/Espruino$ source scripts/provision.sh ESP32
. . .
GCC is /home/tamhan/espjsspace/Espruino/xtensa-esp32-elf/bin//xtensa-esp32-elf-gcc

Nach getaner Arbeit können wir einen make-Lauf anweisen, der die Zusammenstellung der ESP32-Firmware bewerkstelligt. Das Herumspielen mit Parallelisierung lohnt sich nicht sonderlich – auf der Workstation des Autors war die Arbeit binnen weniger als einer Minute getan, die Ausgabedatei hörte auf den Namen espruino_2v01.108_esp32.bin:

tamhan@TAMHAN18:~/espjsspace/Espruino$ make clean && BOARD=ESP32 make

Die eigentliche Kommunikation mit angeschlossenen Boards erfolgt über ein als esptool.py bezeichnetes Programmierwerkzeug, das von Seiten Espressifs in Python gehalten ist. Zu seiner Bereitstellung müssen wir folgendes Kommando eingeben:

tamhan@TAMHAN18:~/espjsspace/Espruino$ sudo pip3 install esptool

ESP32-Firmwarepakete bestehen normalerweise nicht nur aus der .bin-Datei, sondern auch aus einer Gruppe zusätzlicher Files mit Konfigurationsinformationen. Im Fall unserer Firmware finden sie sich im Archiv espruino_2v01.108_esp32.tgz, aus dem Sie die Dateien bootloader.bin and partitions_espruino.bin in den Ordner extrahieren, in dem sich die kompilierte .bin-Datei befindet.

Im nächsten Schritt dürfen Sie die gesamte Software auf den ESP32 schicken. Das hier gezeigte Kommando funktioniert mit dem Wemos Lolin OLED des Autors problemlos – wenn Sie ein anderes Board verwenden, müssen Sie mitunter die Baudrate oder die Schreibgeschwindigkeit anpassen (Listing 1).

tamhan@TAMHAN18:~/espjsspace/Espruino$ sudo esptool.py	\
> --chip esp32                                  \
> --port /dev/ttyUSB0                         \
> --baud 921600                                 \
> --after hard_reset write_flash                \
> -z                                            \
> --flash_mode dio                                \
> --flash_freq 40m                                 \
> --flash_size detect                                \
> 0x1000 bootloader.bin                              \
> 0x8000 partitions_espruino.bin                     \
> 0x10000 espruino_2v01.108_esp32.bin

Wichtig ist zudem, im Parameter port den Port anzugeben, die Sie weiter oben aus dmesg ermittelt haben. Insbesondere auf älteren Unix-Versionen ändern die Platinen mitunter ihren Aufenthaltsort – bei seltsamem Verhalten empfiehlt sich ein weiterer Check des Kernellogs.

Überprüfung der Programmgesundheit

Espruino steht permanent unter aggressiver Weiterentwicklung, weshalb es immer wieder zu Situationen kommt, in denen die in den Git-Repositories befindliche Firmware nicht funktionsfähig ist.

Zur Analyse des Bootprozesses empfiehlt sich das Programm minicom, das, anders als das unter Ubuntu 18.04 besser funktionierende Screen, in der Lage ist, eine Verbindung zu einem Gerät auch dann aufrechtzuerhalten, wenn man dieses kurzfristig von der Workstation trennt.

Geben Sie im ersten Schritt folgendes Kommando ein, um eine Verbindung zum an ttyUSB0 angeschlossenen ESP32 aufzubauen. Wie im Fall des vorhergehenden Befehls müssen Sie auch dieses Mal darauf achten, den korrekten Port zu übergeben:

tamhan@TAMHAN18:~/espjsspace/Espruino$ sudo minicom --baudrate 115200 --device /dev/ttyUSB0

In Idealfall sehen Sie spätestens nach dem nächsten Ein- und Ausschalten die Espruino-Konsole. In der Praxis kommt es stattdessen immer wieder zu Fehlern, die sich nach dem in Abbildung 1 gezeigten Schema äußern.

Abb. 1: Diese Firmware ist nicht lebensfähig

Abb. 1: Diese Firmware ist nicht lebensfähig

In diesem Fall ist es empfehlenswert, den URL in einem Browser ihrer Wahl zu öffnen. Laden Sie danach ein ESP32-Firmwarearchiv herunter und brennen Sie es nach dem weiter oben besprochenen Schema auf ihren Controller.

Im nächsten Schritt sollten Sie auf Screen umsteigen – minicom ist von Haus aus etwas debil konfiguriert, und würde für Probleme sorgen. Geben Sie danach einen Aufruf von console.log ein, um sich vom Funktionieren unserer JavaScript-Runtime zu überzeugen:

tamhan@TAMHAN18:~/espjsspace/Espruino$ sudo screen /dev/ttyUSB0 115200

>console.log("Hallo");
Hallo
=undefined
>

Screen wirkt auf Linux-unerfahrene Entwickler einschüchternd, da sich das als Hintergrundterminal vorgesehene Programm nicht mittels CTRL + C beenden lässt. Drücken Sie stattdessen CTRL + A und danach \, um die Session zu beenden.
Wundern Sie sich nicht, wenn Sie nach dem Start von Screen kein >-Symbol sehen. Der ESP32 gibt den Prompt nur nach dem Start aus – tippen Sie einfach blind drauflos und drücken Sie auf ENTER, alles wird problemlos funktionieren.

Abseits der direkten Interpretation

Wer seinen ESP32 nur per Kommandozeile mit JavaScript-Befehlen belästigt, kommt nicht sonderlich weit. Als offizielle Programmierumgebung für den ESP32 und JavaScript hat sich die Web IDE etabliert, die die Entwickler in Form einer in Chrome gehosteten Browser-Applikation bereitstellen.

Wer unter Ubuntu arbeitet, installiert im ersten Schritt wie gewohnt Googles Webbrowser, für Windows steht unter diesem Link eine native Version zur Verfügung, die sich bequemer installieren lässt. Wir wollen in diesem Artikel ausschließlich per Kabel arbeiten – angemerkt sei, dass sich manche Boards auch per WLAN mit Updates versorgen lassen.

Unsere nächste Amtshandlung ist das Hinzufügen des Benutzers zur dialout-Gruppe. Von Haus aus ist der Zugriff auf TTY-Ports nämlich nur jenen Programmen gestattet, die über Superuser-Rechte verfügen. Da das Ausführen eines Browsers mit sudo sicherheitstechnischer Wahnsinn ist, wollen wir stattdessen folgendes Kommando ausführen:

tamhan@TAMHAN18:~$ sudo adduser tamhan dialout

Der sicherste Weg zur Aktualisierung der diversen ACLs ist es, an dieser Stelle einen Reboot des Systems zu befehligen. Öffnen Sie in Chrome danach den URL, und installieren Sie die Applikation. Sie findet sich nach dem Durchlaufen des Assistenten übrigens nicht in Chrome, sondern direkt im Startmenü der Workstation wieder.

Leider gibt es zum Zeitpunkt der Drucklegung Probleme mit der Web IDE, die sich durch unzuverlässigen Verbindungsaufbau zu Evaluationsboard manifestieren. Als Lösung bietet sich an, nach dem Start der Web IDE Screen zu öffnen und einen console.log-Lauf durchzuführen. Lassen Sie das Terminalfenster danach im Hintergrund arbeiten, während Sie über die Web IDE mit unserem Programm interagieren – wichtig ist nur, dass Screen in diesem Fall nicht mit sudo gestartet werden darf, da es sonst den Zugriff der mit normalen Userrechten laufenden Web IDE auf den Port unterbindet.

Die Espruino Web IDE ist vom Aufbau her nicht besonders kompliziert. Auf der linken Seite des Bildschirms sehen Sie die Terminalausgabe, während der gerade aktuelle Code rechts von der in der Mitte befindlichen Toolbar angezeigt wird. Die drei Symbole auf der oberen Seite der Toolbar erlauben das Laden, das Speichern und das Ausliefern von Code.

Nach dem Anklicken des Ausliefern-Symbols blendet die Web IDE eine Liste von Ports ein – klicken Sie einfach das TTY-Gerät an, das wir weiter oben als für den ESP32 verantwortlich identifiziert haben.

Nach dem Start der IDE sehen Sie ein vergleichsweise kompliziertes Programm, das unter anderem eine globale, als LED1s bezeichnete Variable anspricht. Es ist am ESP32 nicht funktionsfähig, weshalb wir es durch den folgenden Code ersetzen:

D25.mode('output');
while(1==1){
  D25.set();
  D25.reset();
  D25.set();
  D25.reset();
}

Die Espruino-IDE ist beim Zugriff auf Hardware insofern besonders, als dass die diversen Ressourcen des Controllers durch die Bank in Form von globalen Variablen zur Verfügung stehen. Auf unserem Wemos Lolin ist der Pin 25 besonders bequem ansprechbar, weshalb wir ihn in der gewohnten Art und Weise mit einer charakteristischen Wellenform belasten.

Schließen Sie im nächsten Schritt sowohl einen Analyse- als auch einen digitalen Phosphoroszillograf an, um sich an den in den Abbildungen 2 und 3 gezeigten Ergebnissen zu erfreuen.

Abb. 2: Die Ausgabewellenform auf einem LeCroy 9354AM ...

Abb. 2: Die Ausgabewellenform auf einem LeCroy 9354AM …

Abb. 3: ... und auf einem TDS754D

Abb. 3: … und auf einem TDS754D

Ein Blick auf die Frequenz zeigt, dass unsere Schleife mit rund 1 kHz abgearbeitet wird – da wir insgesamt vier Zustandsänderungen haben, können wir daraus auf die maximale (und sehr geringe) Ausführungsgeschwindigkeit Rückschlüsse ziehen.

Die Langsamkeit der (während der Ausführung interpretierenden) Runtime zeigt sich auch durch den extremen Unterschied in der Länge der beiden Wellentäler. Sie liegt darin begründet, dass die Abarbeitung der Schleife sehr ressourcenintensiv ist. Das „Verwischtsein“ der Ausgabe am digitalen Phosphoroszillograf informiert uns darüber, dass wir es hier nicht mit einer besonders stabilen Wellenform zu tun haben.

An dieser Stelle sei noch auf die Diskussion im Espruino-Forum hingewiesen. Die Verwendung einer while()-Schleife ist am ESP32 nicht wirklich empfehlenswert, da sie das Echtzeitbetriebssystem aushungert und langfristig zu Problemen mit WLAN-Verbindung und Co. führt.

Und jetzt mit Display

Bit-Banging-Versuche erlauben interessante Einblicke in das Verhalten von Prozessrechner-Runtimes. In der Praxis spielen sie eine sehr untergeordnete Rolle – so gut wie jede moderne Hardware nimmt nicht direkt, sondern über I2C, SPI oder einen klassischen seriellen Bus Kontakt zum Prozessrechner auf. Die Vorteile dieser Vorgehensweise sind logisch – dedizierte Hardwareeinheiten kümmern sich um die Generation und Entgegennahme der Bitfolge, was die Echtzeitanforderungen an die Software entschärft.

Wer (wie der Autor) das in der Einleitung erwähnte Lolin verwendet, möchte an dieser Stelle den kleinen organischen Bildschirm in Betrieb nehmen. Es handelt sich dabei um ein auf dem weit verbreiteten SSD1306-Controller aus dem Hause Solomon Systech basierendes monochromes Display. Wer die Webseite des Boards öffnet, stellt fest, dass die Anbindung diesmal (unüblicherweise) per I2C erfolgt und über die Pins vier und fünf durchgeführt wird.

Die Web IDE geht an dieser Stelle insofern mit dem Trend, als dass sie sich dem Gedanken einer automatisch generierten oder konfigurierten Projektstruktur nicht verschließt. Die als Module bezeichneten und unter diesem Link aufgelisteten Bibliotheken sind Programmierhilfen für diverse weitverbreitete Hardwarekomponenten. Wer ein neues Prozessrechner- oder Messsystem entwirft, ist gut beraten, die URL zu besuchen und sich nach Möglichkeit an den unterstützten Komponenten festzuhalten – das Implementieren eigener Hardwaretreiber artet erfahrungsgemäß in Arbeit aus.

Ein besonders netter Aspekt der Web IDE ist, dass sie requires im Rahmen der Kompilation automatisch aus den Repositories zu versorgen versucht – anders als beispielsweise bei der Arbeit mit Yocto müssen Sie sich keine Gedanken machen, wie sie die Bibliothek im ersten Schritt herunterladen.

Selten ist, dass die IDE auf Wunsch sogar URLs auflöst – nach dem folgenden Schema aufgebaute requires sind in der Espruino-IDE legitim:

require("https://github.com/espruino/EspruinoDocs/blob/master/devices/PCD8544.js");

Beachten Sie, dass diese Auflösungsfunktionen nur dann zur Verfügung stehen, wenn Code per Web IDE auf den ESP32 wandert. Auf der Konsole ist das Laden beliebiger Bibliotheken nicht möglich, stattdessen dürfen Sie aber eventuell im Flashspeicher befindliche Hilfsbibliotheken ansprechen.

Als nächstes bietet sich die Erzeugung eines kleinen Testprogramms an, dass nach dem folgenden Schema aufgebaut ist:

var g;
function start(){
  g.drawString("Hello SUS!",2,2);
  g.flip();
}

Die Treiberbibliothek für den Solomon-Systech-Display-Controller arbeitet mit der Grafik-API von Espruino. Aus diesem Grund müssen wir im ersten Schritt eine globale Variable deklarieren, in der wir die vom Treiber zurückgegebene Grafikbibliotheksinstanz zwischenspeichern. Die Funktion Start ist dann für das Ausgeben eines grundlegenden Begrüßungstexts verantwortlich.

Von Interesse ist hier noch die Verwendung der Funktion flip. Wer sie nicht aufruft, schreibt die Informationen des graphics-Objekts nicht in einen für den Benutzer sichtbaren Bereich.

Die eigentliche Konfiguration der Hardware erfolgt abermals über die globalen Variablen. Die setup-Funktion des Objekts I2C1 nimmt ein JSON-Objekt entgegen, dass die für SCL und SDA verantwortlichen Pins beschreibt. Danach folgt das Einbinden der Bibliothek, die per connect-Befehl zum Start animiert wird. Nach getaner Arbeit sehen Sie einen (kleinen) String am Display:

I2C1.setup({scl:D4,sda:D5});
g = require("SSD1306").connect(I2C1, start);

Grundlagen der Datenerfassung

Der ESP32 ist mit – zwar nicht perfekten, aber durchaus brauchbaren – Analog-Digital-Wandlern ausgestattet. Diese erlauben das Erfassen analoger Werte, die man ins Internet oder anderweitig weiterreichen kann.

Die Softwareunterstützung für diese Komponenten ist traditionell etwas dürftig. Im Fall von Espruino steht beispielsweise nur einer der beiden ADC-Kerne zur Verfügung. Trotz dieser kleinen Schwächen wollen wir an dieser Stelle erste Versuche in der Welt der Datenerfassung mit JavaScript wagen.

Die erste in diesem Zusammenhang wichtige Aufgabe ist das Konfigurieren einer sogenannten Sample Clock, über die wir die anliegenden Informationen regelmäßig abernten können. Eine primitive Beispielimplementierung würde folgendermaßen aussehen:

var on;
function worker(){
   on = !on;
   digitalWrite(D25, on);
}

var i = setInterval(worker, 20);

Die leicht abgewandelte Version des Grafikanzeigeprogramms von vorher unterscheidet sich von ihrem Kollegen, da wir nun im Rahmen der Konfiguration des Framebuffers mit setInterval eine Payload anmelden, die fortan permanent abzuarbeiten ist. Die Aufgabe ist das Ausgeben einer Wellenform, deren Stabilität wir dann auf einem Oszilloskop überprüfen (Listing 2).

var g, i;

D25.mode('output');
var on;
function worker(){
  on = !on;
  digitalWrite(D25, on);
}


function start(){
  g.drawString("Hello SUS 2!",2,2);
  g.flip();
  i = setInterval(worker, 200);
}

I2C1.setup({scl:D4,sda:D5});
g = require("SSD1306").connect(I2C1, start);

Wer das Programm im vorliegenden Zustand mit einem Wert von 200 – also einer Wartezeit von 200 ms zwischen den einzelnen Durchläufen – aufruft, stellt fest, dass die Wellenform nur ganz kurz auf dem Oszilloskop erscheint und der ESP32 die Arbeit danach mehr oder weniger kommentarlos einstellt. Im hoffentlich nebenbei weiterlaufenden Screen-Fenster sehen Sie folgenden Fehler:

Execution Interrupted during event processing.
New interpreter error: CALLBACK
>echo(1)

Espruino ist bei der Abarbeitung periodischer Payloads insofern haarig, als dass das Blockieren der Abarbeitung durch die Payload zu einem Verwerfen ebendieser führt. Das bedeutet, dass die Abarbeitung der Funktion worker nur maximal 200 ms dauern kann – kommt es währenddessen beispielsweise zu einer Ausführung des Garbage Collectors, so erkennt die Runtime einen Fehler und beendet die weitere Abarbeitung zukünftiger Instanzen.

Da wir uns an dieser Stelle nicht weiter mit der Payload-API auseinandersetzen wollen, beschränken wir uns aus Bequemlichkeitsgründen einfach darauf, eine sehr langsame Aktualisierungsrate zu befehlen:

function start(){
  g.drawString("Hello SUS 2!",2,2);
  g.flip();
  i = setInterval(worker, 1000);
}

An dieser Stelle bietet es sich an, abermals ein Oszilloskop anzuschließen und die Ergebnisse zu prüfen – die Wellenformstabilität sollte nun mehr als befriedigend ausfallen.

Unsere nächste Aufgabe ist das Konfigurieren eines Speicherbereichs, der die anfallenden Informationen aufnimmt. Wir wollen hierbei auf das Round-Robin-Prinzip setzen, das man auch als Eimerkettenspeicherprinzip bezeichnet.

Die dahinterstehende Idee ist einfach: Wir halten im Speicher des Prozessrechners einen kontinuierlichen Speicherbereich vor, auf den zwei Pointer zeigen. Einerseits gibt es einen Schreibzeiger, der die als nächste zu beschreibende Speicherzelle markiert. Andererseits gibt es einen Lesezeiger, der das Einlesen von Informationen ermöglicht.

Die Bezeichnung Eimerkette kommt daher, dass sich die beiden Zeiger während der Programmausführung wie auf einer Uhr im Kreis bewegen und die ältesten Informationen automatisch über den Jordan wandern. Da unser Display 128 Zeilen breit ist, bietet es sich an, ein entsprechend großes Array anzulegen:

var g, i;
var dataBuffer;
dataBuffer = new Array(128);

Als nächstes müssen wir beide Zeiger inkrementieren. Dazu ergänzen wir worker() um Code, der die am ADC-Pin anliegenden Spannungswerte einliest und in das gerade aktuelle Zielregister schreibt (Listing 3).

var readFrom=1;
var writeTo=0;

. . .

function worker(){
  dataBuffer[writeTo] = analogRead(D36);
  readFrom++;
  writeTo++;
  if(readFrom>=128)readFrom=0;
  if(writeTo>=128)writeTo=0;
}

Von besonderem Interesse ist dabei, dass wir beim Erreichen der Obergrenze der beiden Zeiger einen Reset auslösen. Der Lesezeiger ist immer ein Feld vor dem Schreibzeiger – da beide Integer immer gemeinsam inkrementiert werden, bleibt der anfangs festgelegte Zustand in perpetuum bestehen.

Bevor wir das vorliegende Programm ausführen können, müssen wir noch den Eingang konfigurieren. Der ADC des ESP32 ist vergleichsweise flexibel, wir entscheiden uns für den Eingang D36. Auf dem Board wird er übrigens als SVP bezeichnet:

D36.mode('analog');

Auswertung der Informationen

Die letzte Amtshandlung ist das Erzeugen eines Liniendiagramms aus den angelieferten Informationen – Espruino normalisiert die vom ADC gemessenen Daten in den Wertebereich von 0 bis 1, um dem Entwickler Arbeit mit Stufen und sonstigen Nettigkeiten zu ersparen. Daraus folgt, dass sich die endgültigen Grenzwerte durch Multiplikation mit 64 ermitteln lassen:

function drawChart()
{
  clearInterval(i);
  g.clear();
  var count, indexer;
  count=0;
  indexer=readFrom;
}

Im ersten Schritt erzeugen wir eine Gruppe von Variablen. count zählt dabei von 0 bis 128, während indexer durch das Speicherarray läuft und die eigentlich anzuzeigenden Elemente hervorholt. Um Fehler bei der Abarbeitung des Callbacks zu vermeiden, eliminieren wir ihn per clearInterval – der weiter oben bei der Anmeldung angelieferte numerische Wert erlaubt die Adressierung der Registrierung.

Die nächste Aufgabe ist das schrittweise Beschreiben des Framebuffers. Der hier befindliche Code ist nur insofern interessant, als dass die Berechnung der indexer-Variable das Round-Robin-Verfahren implementiert:

while(count<128)
  {
    g.setPixel(count, dataBuffer[indexer++]*64, g.getColor());
    count++;
    if(indexer>=128)indexer=0;
  }

Nach dem erfolgreichen Herausschreiben der einzelnen Datenpunkte müssen wir die Framebufferdaten abermals in Richtung Display schreiben. Der Aufruf von setInterval sorgt danach dafür, dass die Datenakquise weiterläuft:

g.flip();
  i = setInterval(worker, 1000);
}

In der Theorie spricht nichts dagegen, jede Sekunde eine Aktualisierung des Diagramms durchzuführen. Unter Espruino bekommen wir es dabei mit zwei Problemen zu tun: erstens dem weiter oben demonstrierten Problem mit setTimeout, zweitens der Verschwendung von Rechenzeit.

Da das Realisieren von Nebenläufigkeit mit Espruino in Arbeit ausartet, setzen wir auf ein von alten Digitalspeicheroszilloskopen bekanntes Verfahren. Die Aufnahme neuer Informationen ist während der Verarbeitung des Puffers gestoppt – um einen guten Kompromiss zwischen Bildschirmaktualisierung und Datenerfassung zu finden, befehlen wir eine Aktualisierung alle 10 Sekunden:

function worker(){
  . . .
  charCounter++;
  if(charCounter==9)
  {
    drawChart();
    charCounter=0;
  }
}
Abb. 4: Potenziometer an den Eingang anschließen, um den am ADC anliegenden Wert beeinflussen zu können

Abb. 4: Potenziometer an den Eingang anschließen, um den am ADC anliegenden Wert beeinflussen zu können

Unser Data Logger stellt uns beim Testen aufgrund seiner sehr geringen Sampling-Rate vor Probleme – arbiträre Funktionsgeneratoren wie der Danaher AWG2010 des Autors sind im Allgemeinen nur wenig gewillt, Signale mit einer Frequenz von weniger als 10 Hz auszugeben. Da das „Massieren“ des Generators mit einer komplett eigenen Wellenformdatei (Frequenz ist dann Master Clock/Punktmenge) in Arbeit ausartet, wollen wir uns für einen einfacheren Weg entscheiden. Schließen Sie – wie in Abbildung 4 gezeigt – ein Potenziometer an den Eingang an, um den am ADC anliegenden Wert beeinflussen zu können.

Fazit

An dieser Stelle haben wir die primitive Version eines Data Loggers fertiggestellt, ohne eine einzige Zeile C++-Code zu schreiben. Außer Frage steht, dass es an vielen Stellen Verbesserungsbedarf gibt – neben einem flexiblen Attenuator könnten wir einen Webserver implementieren, auf dem die Daten zur Aberntung bereitstehen. Dank JavaScript (und preiswerten Steckplatinen) sind Ihrer Vorstellungskraft keine Grenzen gesetzt.

PHP Magazin

Entwickler MagazinDieser Artikel ist im PHP Magazin erschienen. Das PHP Magazin deckt ein breites Spektrum an Themen ab, die für die erfolgreiche Webentwicklung unerlässlich sind.

Natürlich können Sie das PHP Magazin über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Entwickler Magazin ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -