The PLTB (Pi Lego Train Basement) – Der automatische Keller 1


10.November 2015

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:

  1. Alle PF Kanäle lassen sich per „Browser” aus einer Weboberfläche easy manuell steuern. (erledigt)
  2. Automatische Programme kommen dazu.
  3. Alle Weichen lassen sich zentral elektronisch und automatisch über die Weboberfläche steuern.
  4. Alle Bahnübergänge funktionieren per Lichtschranke automatisch
  5. Sämtliche LED Beleuchtung von Häusern, Ampeln, Signalen etc. lassen sich zentral über die magische Weboberfläche steuern.

1. – Die Infrarotsteuerung von LEGO PF Empfängern aus dem Browser.

Phase1: IR Befehle vom Terminal per LIRC

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”.

Stückliste:

  • Raspberry Pi (Ich nutzte die Rev1 B, jeder Pi nach Version A sollte gehen)
  • Infrarot LED (Link), Leistung ca. 100mA, 950-60NM ist perfekt (link)
  • Als optische Bestätigung eine normale LED
  • 93Ohm Widerstand (LED bei 1,4V, 100ma mit 5V am Pi = 93Ohm) – (link)
  • Lego PF Empfänger und Motor zum testen, besser eine ganze Zugflotte!

Schaltbild IR LED mit GPIO Pin 22

PLTB_IR LED_Steckplatine](/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
  • Configure LIRC by editing /etc/lirc/hardware.conf to be

 

#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"
  • Add in /etc/modules the following line

 

lirc_dev
  • For kernels before 3.18 lacking a “device tree” also add in /etc/modules the following line

 

lirc_rpi gpio_in_pin=23 gpio_out_pin=22
  • For a 3.18 kernel (or newer), which has a device tree, uncomment and adjust the following line in the file /boot/config.txt; you can find full instructions here

 

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
  • Reboot your pi

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

Die LEGO IR Befehle

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…

Phase2: Steuern aus dem Browser: NodeJS und socket.io

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.

Phase3: Steuern aus dem Browser: HTML, JavaScript, jQuery und bootstrap

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:

pltbv0_1](/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…).