Freitag, 14. Februar 2014

Arduino und Linux gemeinsam auf dem Intel Galileo

Im vorhergehenden Beitrag haben wir uns mit der Inbetriebnahme des Boards beschäftigt und einige Standard-Sketche getestet. Die Existenz eines Linux-Systems habe ich zwar erwähnt, sie aber nicht genutzt. Hier soll jetzt das Zusammenspiel von Linux und Galileo genauer unter die Lupe genommen werden. Eine wesentliche Hilfe war dabei der Beitrag auf golem.de



Der erste Kontakt

Wir überzeugen uns davon, dass es überhaupt ein Linux-System auf unserem Galileo gibt. Das Linux-System kann auf die serielle Schnittstelle des Boards schreiben. Unter Linux wird die Schnittstelle durch den Knoten /dev/ttyGS0 repräsentiert.

Wenn wir also den folgenden Sketch übersetzen und hochladen, können wir die Struktur des Dateisystems auf dem seriellen Monitor der Arduino IDE sehen:

void setup() {
  system("ls / > /dev/ttyGS0");
}

void loop() {
}

Wir erkennen die vertraute Struktur, wie sie im Filesystem Hierarchy Standard vereinbart ist: 

bin     dev     home    lib     mnt     proc    sbin    sys     usr

boot    etc     init    media   opt     root    sketch  tmp     var

Weitere Beispiele für Arduino-Sketche, die das Linux-System integrieren, findet man auf der Seite von Intel.


Eine Shell

Auf Dauer ist es umständlich, sich die Ergebnisse von Unix-Anweisungen herausdumpen zu lassen. Besser ist eine Shell. Kein Problem! Wir verbinden das Board über ein Kabel mit dem Netzwerk und starten mit dem folgenden Sketch einen telnet-Server, über den wir uns dann verbinden können:


void setup() {
  system("telnetd -l /bin/sh");
  system("ifconfig eth0 > /dev/ttyGS0");
}

void loop() { 
}

Der Daemon wurde gestartet und die Koordinaten unseres Ethernet-Adapters mit der Anweisung ifconfig auf die serielle Schnittstelle geschrieben. Mein DHCP-Server gibt mir die Adresse 10.0.1.15. Wir öffnen irgendwo im Netzwerk ein Terminal und verbinden uns:

telnet 10.0.1.15

Das System begrüßt uns:

Poky 9.0.2 (Yocto Project 1.4 Reference Distro) 1.4.2 clanton

Unser Linux-System wurde offensichtlich mit Yocto, einer modernen Build-Umgebung für Embedded Linux entwickelt.


Web-Server selbst gebaut

Wir können weitgehend normal mit der Shell arbeiten und mit dem vi-Editor eigene Shell-Skripte programmieren. Das Linux auf der Firmware hat jedoch nur einen begrenzten Funktionsumfang. Um mit einer Programmiersprache wie Python oder dem modernen Netwerk-Framework node.js arbeiten zu können, benötigen wir ein umfassenderes Linux-Image, das wir dann von der SD-Karte starten. Die Vorgehensweise ist im Getting Started Guide (11. Booting your board from an SD card) und funktioniert mittlerweile reibungslos.

Wenn wir die Anweisungen im Guide befolgt und das Board von der SD-Karte gestartet haben, sollten wir  in der Lage sein, uns über ssh zu verbinden:

ssh root@10.0.1.15

Ein Passwort wird standardmäßig nicht abgefragt. Jetzt wollen wir einen Web-Server starten: Es befindet sich keiner auf der Linux-Distribution und das hat seinen Grund: Mit ausgeliefert wird node.js, das zur Zeit in der Server-Entwicklung sehr beliebt ist. Mit node.js bauen wir unseren eigenen Web-Server. In eine neue Datei server.js fügen wir den folgenden Code ein:

var connect = require('connect');
connect.createServer(
    connect.static(__dirname)
).listen(8080);

und versuchen den Server aus der Shell zu starten:

node server.js

Beim Start beschwert sich node.js, dass das Paket connect fehlt. Ähnlich wie in anderen Entwicklungsumgebungen gibt es auch bei node.js einen Paket-Manager, mit dem wir einfach nachrüsten können:

npm install connect

Die Installation schlägt, weil es ein Problem mit dem Zertifikat gibt. Es gibt einen einfachen Workaround:

npm config set registry http://registry.npmjs.org/

Der Paket-Server wird nicht mehr über https, sondern über http angesprochen. Anschließend können wir das Paket connect installieren, auch wenn es etwas dauert. Der Start des Server verläuft dieses Mal fehlerfrei.

Wir legen eine kleine Datei index.html mit dem folgenden Inhalt an:

<b>Hello Galileo</b>

Da der Web-Server auf Port 8080 lauscht, rufen wir diese Seite im Browser wie folgt ab:

http://10.0.1.15:8080



Etwas Bastelei

Im nächsten Schritt lesen wir Sensordaten über die Arduino-Schnittstelle ein und stellen sie dann in unserem Web-Server dar. Wir benötigen zwei einfache Bauteile:

  • Ein 100kOhm Widerstand
  • Ein Fotowiderstand
Der Fotowiderstand hat einen elektrischen Widerstand, der mit wachsender Dunkelheit steigt. Diese Teile verbauen wir wie dargestellt auf unserem Board:






Den Widerstand können wir mit Hilfe des Beispiel-Sketches AnalogReadSerial, den wir über File:Examples:Basics in der IDE erreichen. Der Sketch zeigt einen numerischen Wert auf dem seriallen Monitor dar, der die gemessene Helligkeit repräsentiert. Kernstück ist der Aufruf der API-Funktionen analogRead, die in unserem Fall der Eingangsspannung an Pin A0 einen Wert zwischen 0 und 1024 zuordnet.

Wenn der Sketch hochgeladen und der serielle Monitor geöffnet ist, kann man sehr schön sehen, wie sich der angezeigte Wert verändert, wenn man mit der Hand über den Sensor fährt.


Der letzt Schliff

Wir wollen die Sensorwerte im Browser angezeigen  Wir ändern die Datei index.html:

<b>Aktueller Wert des Sensors: 000</b>

Der Wert 000 ist Platzhalter für die aktuellen Sensorwerte. Um ihn mit aktuellen Werten zu versorgen, nutzen wir das Unix-Werkzeug sed, mit dem Muster in Dateien durch Text ersetzt werden. Wenn wir etwa in der Shell die Anweisung

sed -ie 's/000/999/' '/home/root/index.html'

ausführen, ergibt sich 

<b>Aktueller Wert des Sensors: 999</b>

Wirklich stark wird sed, wenn wir reguläre Ausdrücke einsetzen: Die Anweisung

sed -ie 's/[0-9][0-9]*/4711/' '/home/root/index.html'

ersetzt die erste Zahl, die in der Datei gefunden wird durch 4711. Wir erreichen unser Ziel, indem wir den Aufruf von sed in einem Sketch in die system-Funktion packen:


void setup() {
}

void loop() {
  int sensorValue = analogRead(A0);
   
  String sedString="sed -ie 's/[0-9][0-9]*/";
  sedString+=String(sensorValue);
  sedString+="/' '/home/root/index.html'";

  char sedArray[255];
  sedString.toCharArray(sedArray, 255);

  system(sedArray);
  delay(1000);     
}


Der AnalogReadSerial-Sketch wurde angepasst. In den Text, der die sed-Anweisung erhält, wird der aktuelle Sensorwert eingebaut. Dieses Objekt vom Typ String wird dann in ein char-Array umgewandelt, den Datentyp, den system erwartet.

Nachdem der Sketch auf das Board geladen wurde, sollte der Browser uns jetzt sofort den aktuellen Wert anzeigen - vorausgesetzt unser Server läuft noch. Um den Wert zu aktualisieren, müssen wir die Seite jedes Mal neu laden. Wen das stört, der kann index.html mit JavaScript so anpassen, das man immer den aktuellen Wert sieht.



Verhalten optimistisch

Nach den ersten teilweise unangenehmen Erfahrungen mit dem Intel Galileo bin ich zunehmend angetan: Die kleine Anwendung aus diesem Beitrag liess sich wirklich problemlos und ohne Pannen entwickeln. Durch die Integration von Linux in die Arduino-Welt sind der Fantasie noch weniger Grenzen als bisher gesetzt. Einige der Probeme, die noch in dem Artikel auf Golem.de beschrieben wurden, hat Intel behoben. Auch das macht mich zuversichtlich. Ein grundsätzliches Problem ist aber produktimmanent:

Keines der beiden Yocto Linux-Systeme hat - zumindest bisher - einen Paketmanager. Softwarepakete, die über den Lieferumfang der Distribution hinausgehen, können nicht oder nur schwer integriert werden. Andere Linux-Distributionen können verwendet werden, ziehen aber den Verlust der Arduino-Schnittstelle mit seinen Sketches nach sich. Wenn ich nützliche Software wie eine SQLite-Datenbank nicht ohne weiteres auf meinem System betreiben kann, ist das für mich eine ziemliche Einschränkung. 

Keine Kommentare:

Kommentar veröffentlichen