The Internet of (Lego) Trains

De verwachting is dat Internet of Things (IoT) een steeds grotere rol gaat spelen in onze samenleving. Voor ontwikkelaars en bedrijven biedt dat nieuwe mogelijkheden, maar ook nieuwe uitdagingen. We schrijven nu nog veelal applicaties, die op zware servers draaien. Bij IoT zijn de resources vaak beperkt en is het maar de vraag of je op ieder moment een connectie kunt maken om problemen op te lossen. Toch zijn de resources van bijvoorbeeld een Raspberry Pi tegenwoordig best behoorlijk. Binnen Info Support wilden we dan ook graag eens uitzoeken of we dezelfde programmeertalen, applicaties en frameworks op de Raspberry Pi’s konden gebruiken, die we ook gebruiken voor serverapplicaties.

Daarvoor hebben we Legotreinen en wissels geautomatiseerd met Raspberry Pi’s en andere elektronica. Een bijkomend voordeel was dat we met behulp van Lego concepten, zoals IoT en event driven architecture op een wat eenvoudigere manier uit konden leggen. Daarnaast was het project natuurlijk ook een heel goed excuus om met Lego te mogen spelen.

Inleiding

Dit artikel laat zien hoe we de Legotreinen geautomatiseerd hebben. Helaas is het niet mogelijk om alle details in een paar pagina’s te beschrijven. Daarom zijn in de referenties een aantal links met meer (gedetailleerde) informatie opgenomen. De grootste uitdaging was het overnemen van de besturing van de Legotrein. Zelf kom ik nog uit het 12 Volt tijdperk. Door middel van een transformator en rails met geleiders werden de treinen bestuurd en konden wissels vanaf een afstand bediend worden. Tegenwoordig zitten we echter in het Lego Power Functions tijdperk.

Figuur 1 Originele treinbesturing met een batterijhouder, infrarood ontvanger en een afstandsbediening.

De treinen krijgen stroom van een batterijhouder in de trein. Verder zit er in de trein een infrarood ontvanger, die is aangesloten op de motor. Door middel van een afstandsbediening kunnen de infrarood signalen naar de trein gestuurd worden. Met deze infrarood signalen kan aangegeven worden hoe hard de trein moet rijden. Het grootste nadeel van infrarood is dat de afstand tussen zender en ontvanger slechts een paar meter mag zijn. Bij een eerste test reed de trein vanuit de woonkamer richting de keuken. Dat was echter al te ver voor het infrarood signaal, waardoor de trein niet meer kon stoppen, de trein van de rails af reed en tegen een keukenkastje botste.

Figuur 2 Beperking van het infrarood signaal zorgde voor een botsing met de keuken

Figuur 3 Architectuurplaat van de applicaties voor de laptop, trein, wissel en overzichtscamera

 

Architectuur

We wilden de treinen en wissels kunnen bedienen door middel van een centrale applicatie. Daarvoor hadden we het Lego Train Control Center (LTCC) bedacht. Deze LTCC applicatie draait op een laptop en maakt verbinding met de verschillende applicaties op de Raspberry Pi’s, zoals de TrainControl applicatie voor de treinen en de SwitchControl applicatie voor de wissels. In eerste instantie hadden we deze applicaties gebouwd met Java, Jersey en Tomcat. De applicaties communiceerden onderling door middel van REST.

Figuur 4 Lego Train Control Center (LTCC) om handmatig de treinen en wissels te bedienen

Hoewel dat systeem prima functioneerde, vonden we het wel interessant om de applicaties opnieuw te bouwen op basis van een event driven architecture. Daarvoor hebben we Scala en Akka gebruikt om door middel van actoren berichten te versturen tussen de verschillende applicaties. Zo worden er bijvoorbeeld vanuit het LTCC berichten verstuurd naar de Raspberry Pi op de Legotrein om de snelheid van de trein aan te passen. Met Akka is het relatief eenvoudig om vanuit een applicatie code aan te roepen van een andere applicatie in een andere JVM. Dat kan door middel van remoting met remote actors. Een van de voordelen hiervan is dat berichten niet over HTTP verstuurd worden, maar via Akka over het TCP-protocol dat veel lichter is en minder overhead heeft. Wel gebruiken we nog Akka HTTP om een REST endpoint aan te bieden aan AngularJS. Daarnaast zit er een RFID-reader onder de trein, die de RFID-pasjes op het spoort uitleest om de positie van de trein te bepalen. De RFID-reader stuurt de ID’s van de gelezen RFID-kaarten met het Linux curl commando op naar een Akka HTTP REST endpoint.

Omdat we geen tijd hadden om alles zelf te bouwen, hebben we ervoor gekozen om bestaande C en Python applicaties te gebruiken en waar nodig aan te passen. Dit waren bijvoorbeeld applicaties om de RFID-reader uit te lezen en de camerabeelden door te sturen. Daarnaast maken we ook gebruik van een aantal Linux-commando’s en applicaties, zoals bijvoorbeeld mpg123 om muziek af te spelen op de luidspreker.

 

Remote actors

In Figuur 5 is een gedeelte van de code te zien van de LTCC en TrainControl applicaties. In de TrainControl applicatie wordt een ActorSystem gemaakt met de naam LegoTrain. In het LegoTrain ActorSystem wordt vervolgens een Actor gemaakt met de naam trainservice. In de trainservice actor is een receive methode gedefinieerd, die de inkomende berichten afhandelt. In dit voorbeeld kan de receive methode een bericht krijgen met een Forward object met een bepaalde speed. Als er een Forward object binnenkomt, dan wordt de doCommand methode aangeroepen, die vervolgens via infrarood de nieuwe snelheid naar de Legotrein stuurt.

De LTCC applicatie kan de trainservice actor aanroepen door een referentie naar de actor te maken. Dat kan vrij eenvoudig door het ActorSystem, IP-adres, poort en pad (/user/trainservice) te specificeren van de actor op de remote machine. Aangezien we de actor zelf gemaakt hebben, begint het pad met user gevolgd door de naam van de actor (in ons geval de trainservice actor). In dit voorbeeld maken we een referentie naar trainActor, genaamd trainActorRef. Vervolgens sturen we een bericht door een uitroepteken achter de trainActorRef te zetten, gevolgd door het bericht dat je wilt sturen. In dit voorbeeld sturen we het object Forward met de nieuwe snelheid naar de trainservice actor.

Figuur 5 Een voorbeeld van een remote Actor in Akka

 

Automatiseren van treinen

Allereerst zijn er een infrarood transmitter en een paar kabeltjes nodig om de trein snelheidsinstructies te kunnen geven. Daarnaast een Raspberry Pi, waarbij het A+ model is aan te raden, vanwege zijn geringe omvang en stroomverbruik. Verder een WiFi-dongel om de trein via WiFi te besturen en een USB-accu om de Raspberry Pi van stroom te voorzien. Het geheel kost minder dan 50 euro en als je al een Raspberry Pi hebt, is het nog een stuk goedkoper. Maar je kunt natuurlijk ook helemaal losgaan en een Raspberry Pi camera, een RFID-reader en luidspreker aansluiten.

Figuur 6 Trein met infrarood zender, camera, RFID-lezer, luidspreker, Raspberry Pi en accu

 

Automatiseren van wissels

Behalve de treinen wilden we ook de wissels automatiseren. Daar zijn verschillende alternatieven voor, zoals bijvoorbeeld Mindstorms. We wilden echter liever een goedkopere oplossing met een Raspberry Pi. Om de hendel van wissel op en neer te laten gaan gebruiken we een servo. Let erop dat je servo krachtig genoeg is, want anders heb je lijm of een vijl nodig om je wissel aan te passen. Dat word je echter niet in dank afgenomen door de Lego-puristen. Tevens moet je er rekening mee houden dat de Raspberry Pi niet in staat is om meerdere servo’s aan te sturen. Daar heb je een PWM/Servo driver board voor nodig.

Figuur 7 Geautomatiseerde wissel met een servo en een paperclip

 

Camera’s

Behalve de camera op de trein hebben we ook een losse camera om de hele baan in beeld te brengen. Het is best lastig om realtime video te streamen vanaf een Raspberry Pi. De Raspberry Pi is niet zo krachtig, veel video streaming oplossingen zijn browser/applicatie specifiek en vaak zit er behoorlijk wat vertraging in. Gelukkig is er een kant-en-klare oplossing beschikbaar: RPI Cam Web Interface. Deze applicatie werkt door middel van het verversen van foto’s in plaats van het sturen van video.

Figuur 8 Legotreinen en reuzenrad

 

Reuzenrad

Behalve de treinen hebben we sinds kort ook een heus reuzenrad tot onze beschikking. Na een paar avonden zwoegen om de bijna 2.500 Lego-onderdelen in elkaar te zetten, was het dan zover. Met behulp van een Legomotor, die aangestuurd wordt door dezelfde Lego infrarood ontvanger als de treinen, kan het reuzenrad bestuurd worden. Net als de treinen kan het reuzenrad vooruit en achteruit in zeven verschillende snelheden.

Naast het handmatig bedienen van de treinen is het ook mogelijk om gebruik te maken van een automatische piloot functionaliteit in de LTCC applicatie. Daarmee kan bijvoorbeeld een bepaalde actie uitgevoerd worden als de blauwe trein met de RFID-lezer een bepaalde positie (RFID-kaart) bereikt. Zo kan bijvoorbeeld ingesteld worden dat het reuzenrad met een snelheid van drie gaat draaien op het moment dat de blauwe trein langs het station rijdt. Vervolgens stellen we in dat als de blauwe trein langs de koe rijdt, dat het reuzenrad de andere kant op gaat draaien met een snelheid van vier.

 

Uitdagingen

Een van de redenen om dit project te doen, was om meer ervaring op te doen met verschillende hardware en software. We waren benieuwd welke uitdagingen het ontwikkelen voor het IoT met zich meebracht. De eerste uitdaging kwam toen we een infrarood transmitter aan wilden sluiten op een Raspberry Pi. Na wat zoeken op internet zagen we hoe de pinnen verbonden moesten worden. Vervolgens sloten we netjes de kabels aan en gingen wat te drinken pakken. Toen we terugkwamen viel het op dat het enigszins stonk en de transmitter was behoorlijk heet geworden. Gelukkig waren de transmitters niet duur en hadden we er uit voorzorg een paar extra besteld.

Toen we overstapten van een B+ model naar een A+ model, vanwege de kleinere omvang en het lagere stroomverbruik, hebben we twee Raspberry Pi’s af moeten schrijven. Blijkbaar was de USB-connector veranderd, wat voor problemen zorgde bij wat dikkere USB-apparaten, zoals WiFi-dongels. Daardoor bogen de pinnen naar beneden in plaats van naar achteren, met als resultaat dat de Raspberry Pi het niet meer deed.

Op de IoT Developers Day liepen we tegen een ander probleem aan: WiFi. Er waren in de Jaarbeurs zoveel WiFi access points, dat het lastig was om een (snelle) connectie op te zetten. Daardoor veranderde de livestream van de camera meer in een slowstream. Een reden voor ons om alles bedraad aan te sluiten (behalve de treinen) en voor de treinen te kijken naar 5 Ghz WiFi-alternatieven.

Het werken met de Raspberry Pi was vrij eenvoudig, al is het soms lastig om een besturingssysteem te kiezen. Toen we begonnen met dit project had Arch Linux prima Docker support, maar bij Raspbian was dat wel anders. Raspbian had echter een grotere gebruikersgroep en de software voor bijvoorbeeld de camera sloten daar beter bij aan. De gebruikersgroep achter de Raspberry Pi zorgt er ook voor dat je snel antwoorden vindt. Toen wij tussendoor wat experimenteerden met een Odroid C1 was dat toch wat minder.

Het was echter niet alleen rozengeur en maneschijn bij de Raspberry Pi. Op softwaregebied hadden we ook een uitdaging met testen. Het duurt even voordat alle software op alle Raspberry Pi’s staat en debuggen is ook wat lastiger. Achteraf gezien hadden we beter de applicaties lokaal kunnen testen, voordat we met de Raspberry Pi’s aan de slag gingen.

 

De toekomst

Het is mogelijk om bijna eindeloos onderdelen en functionaliteit toe te voegen aan de Legotreinen. Zelf zouden we het erg interessant vinden om een slimmere automatische piloot te maken, inclusief botsdetectie. Verder hebben we een aantal Particle Photon’s in bestelling staan. Doordat ze zo klein zijn, kunnen ze voor allerlei toepassingen ingezet worden, bijvoorbeeld om verlichting aan te sturen. Daarnaast zijn we ook bezig om met behulp van Scala en Akka de hardware direct aan te sturen. Daarmee kunnen we de C en Python applicaties vervangen, die we nu nog gebruiken.

 

Conclusie

Ondanks het feit dat dit soort projecten altijd een stuk meer tijd kosten dan verwacht, is het toch erg leuk om te doen. Dat niet alleen wij, maar ook andere ontwikkelaars Legotreinen met Raspberry Pi’s leuk vonden, bleek wel tijdens de IoT Developers Day. Praktisch iedere bezoeker is wel even bij onze opstelling van Legotreinen komen kijken.

Figuur 9 Opstelling tijdens de IoT Developers Day

Verder hebben we veel van dit project geleerd. We weten nu bijvoorbeeld dat we op de Raspberry Pi hetzelfde soort applicaties kunnen bouwen als we momenteel al doen voor onze servers. Tevens weten we nu ook dat het gebruiken van hardware (zoals sensoren) hele andere uitdagingen met zich meebrengt. Mocht je zelf hiermee aan de slag willen gaan, dan kun je in de referenties instructies vinden om de verschillende hardware-onderdelen aan te sluiten. Mocht je er niet uitkomen, laat het dan vooral even weten. Wellicht kunnen we je helpen om de treinen op tijd te laten rijden 😉

 

Referenties