Ich baue uns einen Keller. Das wird natürlich kein normaler Keller, sondern der berühmte Hobby Keller, allerdings voll im Zeichen von Plastiksteinen aus Billund.
Ziel ist eine komplette Eisenbahnanlage auf der üblichen konservativen Holzplatte, um endlich die Tonnen an Lego- Schienen und Mengen an Zügen „sinnvoll” unterzubringen und dauerhaft fahren zu können.
Im Hause hudecity setzen wir allerdings von Anfang an schon auf die Steuerung per Lego Power Functions (PF), der Zukauf von 9V Schienen und passenden Motoren rechnen sich für uns nicht mehr, und das Laden der vorhandenen Eneloops stellt für uns auch echt kein Problem dar. 9V ist halt soooo 90er \^\^
Allerdings ein Problem sah ich von Beginn an bei der Steuerung über die Lego IR Fernbedienungen. Das muss doch auch anders gehen. In Gut und für nerds irgendwie. IR Befehle kann man abfangen, da muss was gehen. Ein Arduino liegt hier rum, und mehrere Raspberry Pies ebenso. Nur Zeit war bisher keine da, um so ein kleines Projekt mal umzusetzen.
Da jetzt unser Keller fertig, und „einzugsbereit”, habe ich mit dem Projekt „PLTB – Pi Lego Train Basement” begonnen.
Die Ziele dieses hoch wichtigen Projektes habe ich wie folgt definiert:
Erst einmal galt es, überhaupt eine Verbindung zwischen Pi und PF Empfänger herzustellen. Das Mittel der Wahl im Linux Umfeld ist LIRC. Nach dem Anschluss einer Infrarot LED an GPIO Port 22 des Pi, der Installation von LIRC und etwas Magie von Diomidis Spinellis (https://github.com/dspinellis/lego-power-scratch) konnte ich vom Terminal aus bereits mit meinen Zügen „reden”.
](/pics/2015/11/PLTB_IR-LED_Steckplatine.png)
Mein Raspberry Pi läuft mit dem aktuellen Raspberian auf Basis Debian Jessie. Die Installation eines Pi bis dahin spare ich mir hier einmal. Das bekommt Ihr auch so hin. Wir beginnen mit der LIRC Installation. Der folgende Ablauf stammt vom GitHub Account von Diomidis Spinellis, und beinhaltet im Ablauf den Download seiner Config Files, welche LIRC mit der nötigen Lego Magie einhauchen – also die passenden PF Befehle laden… Man könnte die IR Signale am Pi mit einem IR Empfänger und viel Zeit natürlich auch aufwendig selbst messen und abgreifen aber diese Arbeit wurde glücklicherweise schon einmal erledigt.
sudo apt-get install lirc
#Try to load appropriate kernel modules
LOAD_MODULES=true
# Run "lircd --driver=help" for a list of supported drivers.
DRIVER="default"
# usually /dev/lirc0 is the correct setting for systems using udev
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"
lirc_dev
lirc_rpi gpio_in_pin=23 gpio_out_pin=22
dtoverlay=lirc-rpi,gpio_out_pin=22,gpio_in_pin=23
sudo mkdir -p /etc/lirc/lircd.conf.d/
for i in Single_Output Combo_PWM Combo_Direct ; do
curl https://raw.githubusercontent.com/dspinellis/lego-lirc/master/$i |
sudo dd of=/etc/lirc/lircd.conf.d/Lego-$i.conf
done
sudo dd of=/etc/lirc/lircd.conf <<\EOF
# This file is not required in modern versions of LIRC
# but seems to be required for lircd 0.9.0-pre1 that currently
# comes with Raspberry Pi's Debian GNU/Linux 7.8 (wheezy)
include "/etc/lirc/lircd.conf.d/Lego-Single_Output.conf"
include "/etc/lirc/lircd.conf.d/Lego-Combo_Direct.conf"
include "/etc/lirc/lircd.conf.d/Lego-Combo_PWM.conf"
EOF
Nach dem Reboot konnte ich nun erfolgreich PF Befehle absetzen, hier ein paar Beispiele:
irsend SEND_ONCE LEGO_Single_Output 1B_5
sleep 1
irsend SEND_ONCE LEGO_Single_Output 1B_M1
sleep 1
irsend SEND_ONCE LEGO_Single_Output 1B_BRAKE
Im Rahmen der importierten Configs ergibt sich die folgende Tabelle möglicher Befehle:
Beispiel: SEND_ONCE LEGO_Single_Output 1B_5
SEND_ONCE LEGO_Single_Output 1 B 5 M Initiale Sequenz Kanäle 1-4 PF Channel Color: R (red) or: B (blue) Speed: 1-7 Vorwärts: “leer” oder Rückwärts: M —————————— ———— —————————————- ———— ————————————
Nun da wir mit den Zügen sprechen können, wird es Zeit für den Einstieg ins “Aufhübschen”. Ziel war der Browser als Fahrerleitstand…
Ein Browser führt seinen Code bekanntermaßen auf dem Client aus und bekommt seine Inhalte eben nur vom Webserver geliefert. Wäre dies anders, wäre das Internet sicher schon kaputt. Also brauchte es ein Lösung mit einem Rückkanal zum Server. PHP könnte direkt System Befehle übermittlen, steht aber aus diversen Gründen nicht zur Debatte. Für mein kleines Projekt habe ich mich also umsehen müssen, und habe mich für NodeJS als “Webserver” zur Ausführung serverbasiertem Javascript in Verbindung mit socket.io und diversen anderen Plugins entschieden. Ein Vorteil dabei ist, dass bereits andere Projekte NodeJS und Raspberry verwenden, so dass auch hier ein Einstieg mit vorhandenen Funktionsschnipseln einfacher war, als bei Null anzufangen. Ein Dank gilt hierbei besonders Cory Guynn, welcher mit seinem Projekt einen leicht anderen Weg eingeschlagen hatte, mir aber bei der Basisarbeit unter der Haube hervorragende Basics geliefert hat, und mit seinen Texten für jedes meiner Ziele einen Wink oder einen Ansatz für einen Lösungsweg aufgezeigt hat.
Ich habe also erst einmal die NodeJS + socket.io Umgebung installiert. Einen Apachen braucht es nicht!
sudo apt-get install nodejs npm
Für die “Produktionsumgebung” meines Projektes habe ich im userhome meines users ein eigenes Verzeichnis angelegt, und darin zunächst die Node Module geladen, die für meine kleine Steuerung so notwendig sind:
cd
mkdir PLTB
cd PLTB
npm init #initialisiert das Projektverzeichnis für Node
#Installiert das Node Modul um die GPIO Pins per Javascript zu erreichen
npm install johnny-five --save
#Installiert das Node Modul um mit dem Pi sprechen zu können
npm install exec raspi-io --save
#Installiert die http Webserver Funktionen für Node
npm install express http --save # socket.io für den "rückweg zum Server"
npm install socket.io --save
Mit dieser Kombination aus Hin- und Rückweg stand das Gerüst für meine Steuerung aus dem Browser.
Weiterführende Infos zu johnny-five und raspi-io findet Ihr hier und hier.
Aus Faulheit habe ich mich für den grafischen Rahmen meiner Steuerung dem Bootstrap Framework und irgend einem schnell ergoogleten dark template bedient. Ein paar Zeilen CSS von meinem Blog haben erst einmal ein heimeliges Feeling erzeugt. Den Aufbau der Steuerung wollte ich gern über so etwas wie Drehregler abbilden, und die Funktionen Stop und reverse pro Kanal sollten ebenfalls vorhanden sein. Bei diesen Potis habe ich mich einem jQuery Plugin namens Knob bedient. Die Regler sehen gut aus, sind super dokumentiert, lassen sich gut ansprechen und funktionieren einwandfrei. Der erste Reiter für die Züge ist also nun vorhanden, die weiteren Projektziele werden über weitere Reiter abgebildet.
Hier ein kurzer Blick auf das Proof of Concept spät am Abend und wild zusammengesteckt:
Der aktuelle Screen inclusive Reverse Funktion und Stop sieht derzeit so aus:
](/pics/2015/11/pltbv0_1.png)
Die aktuellen Quellen halte ich auf github, alle Listings hier abzubilden wäre… sinnfrei:
https://github.com/HudecityDave/PLTB
Das initiale Javascript für NodeJS startet den Webserver, lädt html Content aus definierten Verzeichnsissen, initialisiert die Module für den Pi, und startet die Sockets für die Rückmeldungen vom Browser.
Mit einem fröhlichen
node start_pltb.js
startet der Webserver und ab geht die wilde Fahrt.
// PLTB Pi Lego Train Basement 0.1
// David Wagner // Lade plugins
var fs = require('fs');
var express = require('express'),
app = express(),
http = require('http').Server(app),
io = require('socket.io')(http);
//Verzeichnisse Webserver definieren
app.use("/css", express.static(__dirname + '/css'));
app.use("/js", express.static(__dirname + '/js'));
app.use("/img", express.static(__dirname + '/img'));
// index.html auf /
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
// Raspberry Module laden
var five = require('johnny-five');
var raspi = require("raspi-io");
var board = new five.Board({
io: new raspi()
});
// Lego IR lirc
var sys = require('sys');
var exec = require('child_process').exec;
// Linux Infrarot Transmitter sendet Kommando
// Code concept and prerequisites found here: https://github.com/dspinellis/lego-power-scratch
function pfir(command){
exec('irsend SEND_ONCE LEGO_Single_Output ' + command, function(error, stdout, stderr){
if(error)
console.log("Error sending command: " + command);
});
}
//Socket.io Funktion
io.sockets.on('connection', function (socket) {
console.log('A client is connected!');
//Test Message Client verbunden
socket.on('message', function (message) {
console.log('A client is speaking to me! They\'re saying: ' + message);
});
// Zug Befehl Kanal 1 Fahren
socket.on('fahren1', function(kanal, farbe, speed, richtung){
console.log("Moving" +kanal +farbe +richtung +speed);
pfir(kanal + farbe +'_'+ richtung + speed);
});
// Zug Befehl ende
});
http.listen(8080);
Die nächsten Schritte sind nun (2.) die Entwicklung von automatischen Fahrprogrammen und die Berücksichtigung von Sensoren für Schranken und Signale. Parallel dazu laufen meine Bestellungen für Micro Servos – Damit startet auch der 3. Teil meines Vorhabens: Elektrische Lego Weichen, vom Browser gesteuert, zeitgesteuert, Programmgesteuert…).