JavaScript und das Internet of Things, Teil 2: BeagleBone Black und Arduino

Neben Espruino und Tessel gibt es noch weitere Plattformen, die JavaScript-Entwicklern den Einstieg in die hardwarenahe Programmierung erleichtern.

In Pocket speichern vorlesen Druckansicht 1 Kommentar lesen
Lesezeit: 12 Min.
Von
  • Philip Ackermann
Inhaltsverzeichnis

Neben Espruino und Tessel gibt es noch weitere Plattformen, die JavaScript-Entwicklern den Einstieg in die hardwarenahe Programmierung erleichtern.

Nachdem die beiden schon im ersten Teil der Artikelreihe beleuchtet wurden, stehen diesmal der BeagleBone Black und der Arduino im Zentrum des Interesses. Denn auch den mittlerweile zum Klassiker avancierten Einplatinencomputer kann man dank Firmata-Protokoll und der Johnny-Five-Bibliothek mit JavaScript bedienen.

Der BeagleBone Black ist ein Singleboard-Mikrocomputer ähnlich dem Raspberry Pi und spielt demnach in einer anderen Liga als die Espruino- oder Tessel-Mikrocontroller. Er verfügt über einen ARM-Cortex-A8-Prozessor mit einem GHz aus der AM335x-Serie , USB-, HDMI- und Ethernet-Anschlüsse, vier LEDs und kommt mit 2GByte Flash-Speicher und 512MByte Arbeitsspeicher daher. Über verschiedene Erweiterungsplatinen (sogenannte Capes) lässt sich ein BeagleBone Black um zusätzliche Funktionen und Komponenten erweitern. Darunter fallen etwa LCD-Displays, eine Motorsteuerung, Breadboards für das Experimentieren mit Schaltungen und vieles mehr. Eine Capes-Übersicht ist auf der Embedded-Linux-Website zu finden.

Der BeagleBone Black ist ein vollwertiger Mikrocomputer (Abb. 1).


Prinzipiell lässt sich der BeagleBone Black auch mit anderen Sprachen wie C, Python, Java etc. programmieren, schließlich handelt es sich bei dem standardmäßig installiertem Betriebssystem um ein vollwertiges Linux (Debian). Zudem lassen sich andere Betriebssysteme (unter anderem Android) installieren. Einer Node.js-Laufzeitumgebung sei Dank kann das Board JavaScript direkt ausführen. Dazu lässt sich entweder der Befehl node auf Kommandozeile oder die Cloud9-IDE verwenden.

Die Installation und Konfiguration des BeagleBone Blacks ist relativ einfach: Nach dem Anschließen des Mikrocomputers an den PC oder Mac per USB und die anschließende Treiberinstallation gelangt man im Browser per http://192.168.7.2/ auf die Weboberfläche des BeagleBones und unter http://192.168.7.2:3000/ auf eine Installation der Cloud9-IDE (Abbildung 2).

Die Cloud9-IDE ist für die Entwicklung mit dem BeagleBone Black empfohlen (Abb. 2).


Für die Programmierung des Boards steht die vorinstallierte BoneScript-Bibliothek zur Verfügung, die sich über den Befehl require('bonescript') wie für Node.js-Module gewohnt in das jeweilige Programm einbinden lässt. Sie vereinfacht den Zugriff auf die Hardware-Komponenten des BeagleBone Black. Im Folgenden ist etwa zu sehen, wie man mit BoneScript auf die einzelnen LEDs zugreifen kann.

var b = require('bonescript');
b.pinMode('USR0', b.OUTPUT); // LED 0 auf Output-Modus
b.pinMode('USR1', b.OUTPUT); // LED 1 auf Output-Modus
b.pinMode('USR2', b.OUTPUT); // LED 2 auf Output-Modus
b.pinMode('USR3', b.OUTPUT); // LED 3 auf Output-Modus
b.digitalWrite('USR0', b.HIGH); // LED 0 anschalten
b.digitalWrite('USR1', b.HIGH); // LED 1 anschalten
b.digitalWrite('USR2', b.HIGH); // LED 2 anschalten
b.digitalWrite('USR3', b.HIGH); // LED 3 anschalten

Der Aufruf von pinMode() ist an der Stelle ratsam, um die entsprechenden LED-Pins (USR0, USR1, USR2 und USR3) explizit als Ausgänge zu definieren.

Die Methode digitalWrite() dient dem Schreiben eines Werts an den jeweils übergebenen Pin wie beim entsprechenden Code-Beispiel für den Espruino. Im Listing werden hierüber einfach alle vier LEDs auf den Wert 1 gesetzt, sprich angeschaltet.

Der folgende Codeauszug dagegen zeigt den Code für das An- und Ausschalten einer LED per angeschlossenem Drucktaster (Details zur Verkabelung für das Beispiel finden sich auf der BeagleBoard-Support-Website).

var b = require('bonescript');
b.pinMode('P8_19', b.INPUT);
b.pinMode('P8_13', b.OUTPUT);
setInterval(check, 100);
function check(){
b.digitalRead('P8_19', checkButton);
}
function checkButton(x) {
if(x.value == 1){
b.digitalWrite('P8_13', b.HIGH);
}
else{
b.digitalWrite('P8_13', b.LOW);
}
}

Der Pin mit der Nummer P8_19 (an dem der Drucktaster angeschlossen ist) wird hierbei als Eingang definiert, der Pin P8_13 (an dem die LED angeschlossen ist) als Ausgang. Über setInterval() ist im Beispiel definiert, dass die Funktion check() alle 100 Millisekunden aufzurufen ist. Sie liest per digitalRead() den Wert des Pins mit angeschlossenem Drucktaster aus beziehungsweise gibt den Wert an die Callback-Funktion checkButton() weiter. Innerhalb letzterer wird anschließend anhand des gemessenen Werts (1 für "Drucktaster gedrückt" und 0 für "Drucktaster nicht gedrückt") die LED über digitalWrite() an- oder ausgeschaltet.

Der Singleboard-Computer Arduino (siehe Abb. 3) ist für die Entwicklung im IoT-Bereich nach wie vor die ausgereifteste Plattform. Allerdings dürfte die Entwicklung in C nicht jedermanns Sache sein und somit ist es mittlerweile auch möglich, einen Arduino über JavaScript fernzusteuern. Dazu kommt das sogenannte Firmata-Protokoll zum Einsatz. Der Vollständigkeit halber ist allerdings auch darauf hinzuweisen, dass der Arduino YUN im Gegensatz zu anderen Arduinos wie dem im Folgenden verwendeten Uno sogar eine Installation von Node.js enthält, um JavaScript direkt ausführen zu können.

Der Arduino Uno lässt sich über das Firmata-Protokoll per JavaScript ansprechen (Abb. 3).


Das Firmata-Protokoll basiert auf dem MIDI-Message-Format und ermöglicht es, von einem entfernten Computer mit einem Arduino (bzw. Mikrocontrollern und Mikrocomputern im Allgemeinen) kommunizieren zu können. Prinzipiell können beliebige Mikrocontroller das Protokoll implementieren, die Umsetzung für Arduino-Boards ist momentan jedoch die verbreitetste. Standardmäßig ist auf dem Arduino kein Firmata-Server vorhanden, was bedeutet, dass ihn Entwickler zuerst manuell installieren müssen. Das geht am einfachsten über die Arduino-IDE, die sich von der Arduino-Website für Windows, Mac OS X oder Linux herunterladen lässt. Nach erfolgreicher Installation und Start der IDE ist der Arduino per USB an den PC oder Mac anzuschließen. Über das Menü "Werkzeuge" müssen anschließend Platine und Port ausgewählt werden, damit der Upload-Prozess von PC/Mac zu Arduino-Board und damit die Installation des Firmata-Servers reibungslos funktioniert (siehe Abbildung 4).

Über das Menü lassen sich Platine und Port festlegen (Abb. 4)


Als nächstes wählt man über das Menü Datei | Beispiele | Firmata | StandardFirmata aus, um das "StandardFirmata"-Sketch zu öffnen. Dabei handelt es sich um eine Quelltext-Datei, die den Code für den Firmata-Server enthält. Im Anschluss selektiert man im daraufhin angezeigten Editor-Fenster die Schaltfläche "Hochladen", um den Code entsprechend auf das Arduino-Board zu bekommen. Damit ist die Installation abgeschlossen, man kann die Arduino-IDE wieder schließen und der Firmata-Server steht auf dem Arduino bereit.

Bezüglich der Client-Seite gibt es verschiedene Bibliotheken, die das Firmata-Protokoll implementieren, unter anderem für Sprachen wie Python, Perl, Ruby, Clojure, Java, .NET, PHP und eben JavaScript. Für letzteres dürfte die Bibliothek Johnny Five die bekannteste Implementierung sein.

Die Installation von Johnny Five erfolgt über den Befehl npm install johnny-five. Mit require('johnny-five'); lässt sich das Modul anschließend in das jeweilige JavaScript-Programm einbinden. Das folgende einfache Beispiel zeigt das Steuern einer LED (Voraussetzung hierfür ist ein wie in Abbildung 3 gezeigter Aufbau).

var five = require("johnny-five");
var board = new five.Board({
port: '/dev/cu.usbmodem14131'
});

var LEDPIN = 13;
var OUTPUT = 1;

board.on("ready", function() {
var value = 0;
this.pinMode(LEDPIN, OUTPUT);
this.loop(2000, function() {
value = value ? 0 : 1;
this.digitalWrite(LEDPIN, value);
});
});

Die Kommunikation mit dem Arduino geschieht dabei über eine Instanz von Board. Über die Methode on() definiert das Programm einen Event-Handler für das ready-Event, der ausgeführt werden soll, wenn die Verbindung zum Arduino-Board hergestellt wurde. Die Funktion loop() sorgt anschließend für das mehrmalige Ausführen des ihr übergebene Event-Handlers (hier alle zwei Sekunden). Im Handler finden sich die Befehle, die dafür sorgen, dass die hinter dem angegebenen Pin hinterlegte LED per digitalWrite() im Wechsel an- und ausgeht.

var five = require("johnny-five");
var board = new five.Board({
port: '/dev/cu.usbmodem14131'
});
board.on("ready", function() {
var led = new five.Led(13);
led.blink(2000);
});

Was im Code eben noch manuell erledigt wurde, lässt sich wie oben zu sehen über die "Klasse" Led vereinfachen. Sie abstrahiert die Kommunikation mit LED-Lampen und verfügt beispielsweise über die Methode blink() für das wechselnde An- und Ausschalten einer LED.

Darüber hinaus stehen "Klassen" für das Arbeiten mit Drucktastern, Tastaturen, Joysticks, Sensoren (Entfernungssensor, Bewegungssensor, Temperatursensor etc.) und vielem mehr zur Verfügung. Beispielsweise lässt sich das Programm relativ einfach erweitern, um die LED per Drucktaster an- und auszuschalten:

var five = require("johnny-five"), button, led;
five.Board().on("ready", function() {
button = new five.Button(7);
led = new five.Led(13);
button.on("hit", function() {
led.on();
}).on("release", function() {
led.off();
});
});

Betrachtet man die Code-Beispiele der vorangegangenen Listings fällt auf, dass sie sich vom Prinzip her alle sehr ähnlich sind, sich im Detail aber unterscheiden. Das Framework Cylon.js setzt genau hier an und schafft eine einheitliche Schnittstelle für IoT-Plattformen (derzeit 36 verschiedene), darunter Tessel, BeagleBone Black und Arduino. Espruino unterstützt es momentan hingegen nicht. Installiert wird Cylon.js als Node.js-Modul über den Befehl npm install cylon.

Die folgenden Codebeispiele zeigen jeweils für Tessel, BeagleBone Black und Arduino, wie sich die Bibliothek dazu verwenden lässt, eine LED per Drucktaster an- und auszuschalten. Der Code ist dabei in allen Fällen mehr oder weniger der gleiche. Lediglich die Verbindungsinformationen (die Parameter der Methode connection()) sowie die Angaben zu den verwendeten Pins (der Konfigurationsparameter der Methode device()) unterscheiden sich voneinander. Dank Fluent API sind die Programme zudem um einiges lesbarer als der Code aus den vorangegangenen Auszügen.

Tessel:

var Cylon = require("cylon");
Cylon
.robot()
.connection("tessel", { adaptor: "tessel" })
.device("led", { driver: "led", pin: 1 })
.device("button", { driver: "button", pin: "config" })
.on("ready", function(robot) {
robot.button.on("push", function() {
robot.led.toggle();
});
});
Cylon.start();

BeagleBone Black:

var Cylon = require("cylon");
Cylon
.robot()
.connection("beaglebone", { adaptor: "beaglebone" })
.device("led", { driver: "led", pin: "P9_12" })
.device("button", { driver: "button", pin: "P9_14" })
.on("ready", function(robot) {
robot.button.on("push", function() {
robot.led.toggle();
});
});
Cylon.start();

Arduino:

var Cylon = require("cylon");
Cylon
.robot()
.connection("arduino", { adaptor: "firmata", port:
"/dev/cu.usbmodem14131" })
.device("led", { driver: "led", pin: 13 })
.device("button", { driver: "button", pin: 2 })
.on("ready", function(robot) {
robot.button.on("push", function() {
robot.led.toggle();
});
});
Cylon.start();

Neben dem programmatischen Zugriff über JavaScript lässt sich Cylon.js zudem über REST oder MQTT ansprechen. Insgesamt stellt die Bibliothek also einen interessanten Ansatz dar, um den Zugriff auf die unterschiedlichen Geräte zu vereinheitlichen und ist allemal einen Blick wert.

Egal, ob Espruino, Tessel, BeagleBone Black oder über das Firmata-Protokoll auch Arduino: Das Herumexperimentieren mit den verschiedenen Plattformen macht Spaß, wenn man sich erst einmal mit den Grundlagen vertraut gemacht hat. Und JavaScript als Programmiersprache ebnet auch Webentwicklern, die in der Regel wenig mit hardwarenaher Programmierung zu tun haben, den Weg in die IoT-Welt. Der Programmierung von heimischer Kameraüberwachung oder Temperatursteuerung steht dann nicht mehr viel im Weg.

Neben den in diesen Artikeln vorgestellten Mikrocontrollern und -computern gibt es außerdem noch eine Reihe weitere, die JavaScript ausführen beziehungsweise sich darüber steuern lassen. Beispiele hierfür sind Intel Galileo, Intel Edison und Particle (ehemals Spark). Darüber hinaus lassen sich Produkte wie die Pebble Smartwatch, die VR-Brille Oculus Rift oder der Bewegungsdetektor Leap Motion per JavaScript ansprechen. Damit zeigt sich, dass die Sprache auch in kommenden Bereichen technischer Entwicklung durchaus relevant und praxistauglich ist und sich nicht nur auf die Webentwicklung beschränkt.

Philip Ackermann
entwickelt seit 15 Jahren Web- und Softwareanwendungen, arbeitet beim Fraunhofer-Institut für Angewandte Informationstechnologie FIT an Tools zum teilautomatisierten Testen von Web Compliance und ist Autor zweier Fachbücher über Java und JavaScript sowie mehrerer Fachartikel.
(jul)