Project: Kersthuisje
Dit kerstverhaal begint op vrijdag 16-12-2016. Onder het genot van een bakje koffie (en mijn moeder kennende tezamen met een heerlijk stukje kerststol of andere lekkernij) wordt een ludiek idee geboren. Dit idee is waarschijnlijk afkomstig uit alle aanwezige kerstversieringen en het mini kerstdorp op de kast. Mijn vader, mijn broertje en ik besluiten om voor kerst 2017 een eigen kersthuis te maken.
Er zijn niet veel eisen en het meeste wordt overgelaten aan fantasie en inlevingsvermogen. De enige eis zijn de maximale formaten, namelijk 40x30x30 cm (HxBxD) voor het huis en 50×50 cm (BxD) voor de onderplaat waar het huis op gebouwd wordt.
Een paar weken later zou overigens ook deze eis ingetrokken worden omdat mijn vader de formaten te groot vindt om op de kast te plaatsen. Ok, handenarbeid dus. Laat de wedstrijd beginnen want volgens jaar moet blijken wie het meest originele of mooie kersthuis heeft…
Mijn eisen
Ok, aangezien er geen harde eisen zijn zal ik er zelf een aantal verzinnen. Na een tijdje komt ik tot de volgende lijst:
- Maximale formaten aanhouden
- 2 verdiepingen
- Huis moet voorzien zijn van een dakkapel
- De onderplaat moet voorzien zijn van een vossenhol
- Alle lichtjes moeten gemakkelijk te bedienen zijn
- Het huis moet volledig demontabel zijn
Design
En dan staat er natuurlijk een wereld aan mogelijkheden open. Hoe gaat het huis eruit zien. Het leek me leuk om er een hoek in aan te brengen waardoor het huis bestaat uit 2 compartimenten. Na wat inspiratiewerk besloot ik dat mijn huis er ongeveer als volgt uit moest komen zien:
Timmerwerk
Oke, nu ik weet wat ik ongeveer wil maak ik wat ruwe schetsen (helaas niet meer aanwezig om hier te posten) en kan ik aan de slag. Ik begin met de onderplaat. Hiervoor heb ik nog een prima spaanplaat in de schuur staan met witte fineer erop (hé, er komt toch sneeuw op, it’s christmas after all). Ik besluit om een kleine verhoging in de onderplaat te maken waar ik meteen een vossenholletje in verwerk. Op dit moment dacht ik nog dat ik de verhoging ook zou kunnen gebruiken om later de elektronica in weg te werken…
Vervolgens ga ik aan de slag met het uittekenen van het huis en het creëren van de voorgevel. Om het huis demontabel te maken verzin een constructie met vierkante latjes waar ik magneetband op kan bevestigen:
Nadat de voorgeveltjes staan wordt het tijd voor de zijkant en doorgang tussen de 2 compartimenten. Om in nostalgische sferen blijven besluit ik een doorgang te maken met boog.
Laat me even benadrukken dat deze eerste stukken gemaakt zijn met blauwe handen in een ijskoude schuur. Het is immers ondertussen januari en ondanks dat het geen hele strenge winter is ligt er wel degelijk sneeuw. Voor het huis zit er wel schot in de zaak, het dak mag er immers op. En nadat het dak erop geplaatst is wordt er begonnen aan het 2e compartiment. Het eerste compartiment is nu zo goed als klaar met verdiepingsvloer en uitgezaagde raampjes. De kozijntjes zijn ook al gemaakt maar staan nog niet op de foto:
Om ook het 2e compartiment af te maken kan de verdiepingsvloer erin en ook het dak kan erop. O mijn god… het dak. Het is een schuin dak dat aangesloten moet worden in haakse richting op een ander schuin dak. Geloof me beste mensen… daar ben ik wel even mee bezig geweest (zonder te schelden uiteraard… want schelden is slecht). En weet je wat we dan doen… dan maken we ook nog een mooi schoorsteentje op het dak. Want een winderhuis moet een kachel hebben toch… en zonder schoorsteen geen kachel!
Ondertussen is het februari en schieten we dus al lekker op. Het hele huis klikt met de magneetstrips lekker in elkaar en is volledig demontabel. Nu nog even een voordeur erin maken en wat kozijntjes zagen. Owja… ik wilde er ook een dakkapel op. Mmmm dat is een dingetje. Maar ook die wordt vakkundig vervaardigd en geplaatst (achteraf iets te schuin naar mijn zin… maar toen zat hij al vast). Een vlondertje bij het voorraam lijkt me ook leuk en ook deze wordt in elkaar gelijmd.
Ja die laatste foto’s laten ook mijn vogelkooi zien aan de voorgevel. Nee dit is natuurlijk geen vogelkooi maar moet een sprookjesachtige boven aanbouw lijken. Een soort prinsessenslaapkamertje. Maar… toch heeft het ook iets van een vogelkooi weg. Ochja… wel volledig demontabel en dat is ook vet!
Ondertussen is het maart en is het huis eigenlijk zo goed al klaar (ruwbouw he… versiering komt later). Om het buitenterrein af te sluiten maak ik een volledig demontabel hekje. Zelfs de pennen zijn eigen fabricaat. Wat is een Dremel toch een fantastisch apparaat!
Misschien leuk om ook even de (nu nog) losse kozijntjes te laten zijn:
Ok, laten we het eisenlijstje er nog eens bijhouden:
- Maximale formaten aanhouden – Check
- 2 verdiepingen – Check
- Huis moet voorzien zijn van een dakkapel – Check
- De onderplaat moet voorzien zijn van een vossenhol – Check
- Alle lichtjes moeten gemakkelijk te bedienen zijn
- Het huis moet volledig demontabel zijn – Check
Niet slecht. Nog slechts 1 item van de 6 eisen staat open. Dus wat ga ik eerst doen. Schilderen of de verlichting? Ik weet nog niet exact hoe de verlichting gaat worden en waar er allemaal draadjes gaan lopen. Wacht draadjes… mmmmm dat is niet zo gemakkelijk in een demontabel huis. Eens kijken hoe we de verlichting zo kunnen gaan maken waardoor het huis demontabel blijft. Dus, eerst de verlichting maken en dan pas schilderen omdat het nu nog niet duidelijk is of het huis demontabel blijft of niet. En als we toch besluiten om te gaan lijmen kan ik ook de kieren en naden netjes dichtsmeren waardoor het daarna toch geschilderd moet worden. Voor de binnen beschildering is het overigens wel ideaal dat het huis nog even demontabel is, zo kunnen we overal goed bij.
Ok, verlichting eerst. Het lijkt me leuk om de verlichting aan te kunnen sturen via een Arduino of een Raspberry Pi. Laten we eens kijken hoe ver we met een Pi kunnen komen.
Onze eerste testopstelling bestaat uit:
- Raspberry Pi
- Breadboard
- Jumper wires
- RGB Leds
- Resistoren
BreadBoard
Het breadboard is een term die letterlijk “broodplank” betekend. Vroeger sloeg men vaak spijkers in een broodplank om die met koperdraad met elkaar te verdinden. Het moderne breadboad is een plastic of pertinax bordje met heel veel gaatjes. Aan de zijkanten van het breadboard zit de power rails en haaks daarom zijn gaatjes die met elkaar verbonden zijn. Op deze manier kunnen elektronische schakelingen gemakkelijk getest worden zonder te solderen. Een schematische weergave is als volgt:
GPIO pinnen
Nu we dus een elektronische schakeling kunnen maken (we hebben de juiste componenten) is het zaak om te weten waar we deze aan kunnen sluiten om onze mini computer, de Raspberri Pi. Het antwoord is op de GPIO pinnen:
Zoals je kunt zien beschikt mijn Raspberry Pi 3 over 40 pinnen. Oudere Raspberry Pi’s beschikken over 26 pinnen.
Eigenlijk beschikt de Raspberri Pi 3 over 17 echte GPIO pinnen (zie onderstaande schema). De GPIO pinnen zijn zogenaamde “General-purpose input/output” pinnen die we gebruiken om apparaten aan of uit te zetten. Met andere woorden, deze pinnen kunnen via de Raspberry Pi in- en uitgeschakeld worden.
Daarnaast hebben we 4 UART pinnen. Dit zijn seriële pinnen die we kunnen verbinden met de computer (met b.v. een TTL-232R-3V3-WE kabel) om een terminal verbinding op te zetten. 2 I2C pinnen welke we kunnen verbinden met andere apparaten die ook I2C ondersteunen. Op die manier kunnen de apparaten met elkaar communiceren.
Er zijn 5 SPI pinnen waarmee we net zoals met I2C de Raspberri Pi kunnen laten communiceren met andere SPI apparaten.
Tenslotte zijn er nog 4 power pinnen (2x 3.3v en 2x 5v) en 8 ground (aarde) pinnen.
Een mooie interactieve pin-layout site voor de Raspberry Pi is “https://pinout.xyz/”.
Een LED aansluiten via de Raspberry Pi is geen rocket science en zou theoretisch via het volgende schema moeten gebeuren.
Dus GPIO2 verbinden met een 220 ohm resistor welke vervolgens met de LED verbonden is en de “ground” draad die voor de power zorgt is verbonden met de andere pin.
WS2812 controlled Smart LED’s
Ik gebruik echter een 8mm APA-106-F8 RGB LED’s met een WS2812 control IC circuit, ofwel een smart LED. Deze LED heeft niet 2 maar 4 aansluitpinnen in de volgorde kort, middel, lang, middel. In de datasheet vinden we het volgende schema:
- Kort = 1 = DIN
- Middel = 2 = VDD
- Lang = 3 = GND
- Middel = 4 = DOUT
Het voordeel van deze LED’s is dat ze te besturen zijn met slechts 1 digitale (GPIO) pin. De meeste RGB LED’s moeten aangesloten worden op 3 GPIO pinnen om afzonderlijk R (Rood), G (Groen) en B (Blauw) aan en uit te zetten. Daarnaast kunnen deze LED’s in cascade worden aangesloten. Dus waar de output van LED 1 dient als input voor LED 2. Toch kunnen deze LED’s in cascade verbinding individueel bestuurd worden. Daarnaast kunnen ze gevoed worden met slechts 5 volt zonder resistoren.
Nu we weten hoe we de LED’s aan moeten sluiten kunnen we bovenstaande lijstje aanvullen:
- Kort = 1 = DIN = data in
- Middel = 2 = VDD = 5v power
- Lang = 3 = GND = ground
- Middel = 4 = DOUT = data out
Ok, we gaan dus een aantal “smart LED’s” aansluiten met slechts 3 GPIO pinnen van de Raspberri Pi, de 5V pin (pin 2), de ground pin (pin 6) en GPIO pin nummer 18 omdat alleen pin nummer 12 (BCM 18) PWM (Pulse Width Modulation) ondersteund. Zonder PWM kunnen de LED’s niet accuraat aangestuurd worden en dus is pin 18 de uitgelezen pin om dat te doen.
Installeren libraries
Omdat deze LED’s nog relatief nieuw zijn is er op het internet nog niet veel over te vinden. Wel voor Arduino en Teensy apparaten, maar niet voor de Raspberri Pi. Laten we starten met het installeren van de rpi_ws281x & WS2801 library welke essentieel zijn om deze LED’s aan te sturen. Daarnaast installeren we ook de benodigde dependencies:
- build-essential
- python-dev
- git
- scons
- swig
- rpi_ws281x
- Adafruit Python WS2801
We houden hiervoor de volgende volgorde aan:
sudo apt-get update sudo apt-get install build-essential python-dev git scons swig |
git clone https://github.com/jgarff/rpi_ws281x.git cd rpi_ws281x scons |
cd python
sudo python3 setup.py install |
cd ../../ git clone https://github.com/adafruit/Adafruit_Python_WS2801.git cd Adafruit_Python_WS2801 sudo python3 setup.py install |
Python script
Met de “rpi_ws281x” library kunnen we de Adafruit WS2801 library op de Raspberry Pi gebruiken waarmee we vervolgens via Python gebruik kunnen maken van de “NeoPixel” sublibrary. Met deze library worden ook andere SMART LED’s aangestuurd zoals NeoPixel LED Strips.
Standaard komt deze library met een aantal voorbeelden (in de “examples directory) zoals strandtest.py & lowlevel.py. Beide libraries demonstreren wat je met de LED’s kunt doen. Maar wat ik wil is slechts individuele lampjes besturen en van kleur laten veranderen.
De key-regel om de LED’s aan te sturen zou als volgt moeten werken:
strip.setPixelColor(0, 255, 0, 0); |
Waarbij de opbouw als volgt is (lamp, rood, groen, blauw). In bovenstaande voorbeeld sturen we dus de eerste LED aan (0 = de eerste, 1 = de tweede etc.) met een rode kleur. De melding die we dan echter krijgen is:
TypeError: setPixelColor() takes exactly 3 arguments (5 given) |
Ook de volgende variant faalt:
strip.setPixelColor(0, (255, 0, 0)); |
Deze keer met een andere foutmelding:
TypeError: in method ‘ws2811_led_set’, argument 3 of type ‘unit32_t’. |
Wat wel lijkt te werken is om gebruik te maken van hex kleurcodering. Dus:
strip.setPixelColor(0, (0xfff600)); |
Mooi! Nu kunnen we dus individuele LEDS aansturen. Mijn testopstelling ziet er als volgt uit:
Alle 4 de LED’s stuur ik aan met dit script:
import Adafruit_WS2801 from neopixel import * #Configure NEOPIXEL options LED_COUNT = 4 # Number of LED pixels. LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) LED_DMA = 5 # DMA channel to use for generating signal (try 5) LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) #Configure colors BLUE = 0x0bfff BLUELIGHT = 0x98c2fb BLUEDARK = 0x0000ff GREY = 0xc3c3c3 GREYLIGHT = 0xf4f4f4 GREYDARK = 0xfefefe ORANGE = 0xffcc00 PINK = 0xff4de8 PURPLE = 0xe400ff RED = 0xFF0000 REDLIGHT = 0xff5a2e REDDARK = 0xc80909 WHITE = 0xffffff YELLOW = 0xfff600 OFF = 0x000000 #Initialize library strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS) #Prepare data pin for NEOPixel output strip.setBrightness(LED_BRIGHTNESS); strip.begin(); strip.show(); # Initialize all pixels to 'off' #Control LED Light (n = number of LED) #strip.setPixelColor(n, (HEX COLOR)); strip.setPixelColor(0,(BLUELIGHT)); strip.setPixelColor(1,(RED)); strip.setPixelColor(2,(YELLOW)); strip.setPixelColor(3,(ORANGE)); #Set strip brightness strip.setBrightness(254); #Push settings on the strip strip.show(); |
Mooi!!! Maar nu nog wat dynamischer. Het idee is om de lampjes individueel aan te kunnen sturen. Uiteindelijk is het een heel script geworden waarmee we het volgende kunnen uitvoeren:
- Lampjes opstarten met default kleuren
- Lampjes individueel instellen op een specifieke kleur
- Brightness van de lampjes beheren
- Lampeffecten (disco / regenboog) toepassen (uit de strandtest.py & lowlevel.py)
- Lampjes uitschakelen
- Raspberry Pi uitschakelen
- Lampjes default instellen zonder usermenu
Het gehele Python script, ready voor 7 LED’s is hier te downloaden en ziet er als volgt uit:
import time import Adafruit_WS2801 import os from neopixel import * from random import randint #Configure NEOPIXEL options LED_COUNT = 7 # Number of LED pixels. LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) LED_DMA = 5 # DMA channel to use for generating signal (try 5) LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) #Configure colors (variable - HEX colorcode - NLname) BLUE = 0x0bfff, "Blauw" BLUELIGHT = 0x98c2fb, "Lichtblauw" BLUEDARK = 0x0000ff, "Donkerblauw" GREY = 0xc3c3c3, "Grijs" GREYLIGHT = 0xf4f4f4, "Lichtgrijs" GREYDARK = 0xfefefe, "Donkergrijs" ORANGE = 0xffcc00, "Oranje" PINK = 0xff4de8, "Roze" PURPLE = 0xe400ff, "Paars" RED = 0xFF0000, "Rood" REDLIGHT = 0xff5a2e, "Lichtrood" REDDARK = 0xc80909, "Donkerrood" WHITE = 0xffffff, "Wit" YELLOW = 0xfff600, "Geel" OFF = 0x000000, "Niet Gedefinieerd" #Default Program Variables USERMENU = 1 # If this variable is 1 than the usermenu will show. If this variable is 0 than the light will use auto-setting DEFAULTLIGHTSONSTART = 1 # If this variable is 1 the default lights will always be shown. If set to 0 the default is to leave the lights off #Define Default Lights def defaultlights(): strip.setBrightness(254); strip.setPixelColor(0,(WHITE[0])); strip.setPixelColor(1,(WHITE[0])); strip.setPixelColor(2,(WHITE[0])); strip.setPixelColor(3,(WHITE[0])); strip.setPixelColor(4,(WHITE[0])); strip.setPixelColor(5,(WHITE[0])); strip.setPixelColor(6,(WHITE[0])); strip.setPixelColor(7,(WHITE[0])); #Initialize library strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS) #Prepare data pin for NEOPixel output strip.setBrightness(LED_BRIGHTNESS); strip.begin(); strip.show(); # Initialize all pixels to 'off' #Turn on default lights if is true, else dim the lights if DEFAULTLIGHTSONSTART == 1: defaultlights() strip.show(); #USER MENU while USERMENU == 1: KEUZEMENU = 1 # This variable sets the default behaviour of the user light menu back to defaults os.system('cls') # on windows os.system('clear') # on linux / os x print("---------------------------------------") print("JARNO'S KERSTHUISJE CONTROLE MENU:") print("---------------------------------------") print("") print("Wat wil je gaan doen?") print(".....................") print("") print("1 = Standaard lampjes") print("") print("2 = Lampkleuren zelf definieren") print("") print("3 = Disco Wit") print("") print("4 = Disco - alle kleuren") print("") print("5 = Regenboog - lampjes zelfde kleur") print("") print("6 = Regenboog - lampjes andere kleur") print("") print("7 = Verspringende lampjes") print("") print("8 = Lampjes uit") print("") print("9 = Raspberry Pi afsluiten") print("") print("(Gebruik CTRL+C bij optie 3, 4, 5, 6 en 7 om de loop te eindigen.)") print("") print("") HOOFDMENU = input("Maak je keuze: ") if HOOFDMENU == "1": #Turn on the default light settings as defined defaultlights() if HOOFDMENU == "2": #Define your own light colors while KEUZEMENU != 2: #Choose the light to set os.system('cls') # on windows os.system('clear') # on linux / os x print("KIES JE LAMPJE:") print("---------------------------------------") print("") print("1 = Eetkamer") print("") print("2 = Woonkamer") print("") print("3 = Zolder1") print("") print("4 = Zolder2") print("") print("5 = Zolder3") print("") print("6 = Buitenlamp") print("") print("7 = Zithoek") print("") print("8 = Stel de brightness (felheid) in") print("") print("") LAMP = int(input("Kies je lampje: ")) #Assign a LED number (int) if LAMP == 1: LAMPNUMMER = 0 if LAMP == 2: LAMPNUMMER = 1 if LAMP == 3: LAMPNUMMER = 2 if LAMP == 4: LAMPNUMMER = 3 if LAMP == 5: LAMPNUMMER = 4 if LAMP == 6: LAMPNUMMER = 5 if LAMP == 7: LAMPNUMMER = 6 if LAMP != 8: #Colormenu used by all lights to set a lightcolor os.system('cls') # on windows os.system('clear') # on linux / os x print("KIES DE KLEUR:") print("---------------------------------------") print("") print("a = Blauw") print("b = Lichtblauw") print("c = Donkerblauw") print("d = Grijs") print("e = Lichtgrijs") print("f = Donkergrijs") print("g = Oranje") print("h = Roze") print("i = Paars") print("j = Rood") print("k = Lichtrood") print("l = Donkerrood") print("m = Wit") print("n = Geel") print("o = Uit") print("") print("") LAMPKLEUR = input("Kies je kleur: ") #Give KLEUR variable a value if LAMPKLEUR == "a": KLEUR = BLUE elif LAMPKLEUR == "b": KLEUR = BLUELIGHT elif LAMPKLEUR == "c": KLEUR = BLUEDARK elif LAMPKLEUR == "d": KLEUR = GREY elif LAMPKLEUR == "e": KLEUR = GREYLIGHT elif LAMPKLEUR == "f": KLEUR = GREYDARK elif LAMPKLEUR == "g": KLEUR = ORANGE elif LAMPKLEUR == "h": KLEUR = PINK elif LAMPKLEUR == "i": KLEUR = PURPLE elif LAMPKLEUR == "j": KLEUR = RED elif LAMPKLEUR == "k": KLEUR = REDLIGHT elif LAMPKLEUR == "l": KLEUR = REDDARK elif LAMPKLEUR == "m": KLEUR = WHITE elif LAMPKLEUR == "n": KLEUR = YELLOW elif LAMPKLEUR == "o": KLEUR = OFF else: KLEUR = OFF #Assign the right HEX color (KLEUR) to the right light (LAMPNUMMER) strip.setPixelColor(LAMPNUMMER,(KLEUR[0])); #Set the LAMPKLEUR variable for overview page if LAMPNUMMER == 0: LAMPKLEUR1 = KLEUR[1] if LAMPNUMMER == 1: LAMPKLEUR2 = KLEUR[1] if LAMPNUMMER == 2: LAMPKLEUR3 = KLEUR[1] if LAMPNUMMER == 3: LAMPKLEUR4 = KLEUR[1] if LAMPNUMMER == 4: LAMPKLEUR5 = KLEUR[1] if LAMPNUMMER == 5: LAMPKLEUR6 = KLEUR[1] if LAMPNUMMER == 6: LAMPKLEUR7 = KLEUR[1] if LAMP == 8: BRIGHTNESS = int(input("Geef een waarde op: 0 = uit en 254 = maximaal!")) strip.setBrightness(BRIGHTNESS); #Print current lamp/light configuration os.system('cls') # on windows os.system('clear') # on linux / os x print("HUIDIGE CONFIGURATIE:") print("---------------------------------------") print("") try: LAMPKLEUR1 except NameError: print ("Lamp1 is nog niet gedefinieerd") else: print ("Lamp1 is ingesteld op", LAMPKLEUR1) try: LAMPKLEUR2 except NameError: print ("Lamp2 is nog niet gedefinieerd") else: print ("Lamp2 is ingesteld op", LAMPKLEUR2) try: LAMPKLEUR3 except NameError: print ("Lamp3 is nog niet gedefinieerd") else: print ("Lamp3 is ingesteld op", LAMPKLEUR3) try: LAMPKLEUR4 except NameError: print ("Lamp4 is nog niet gedefinieerd") else: print ("Lamp4 is ingesteld op", LAMPKLEUR4) try: LAMPKLEUR5 except NameError: print ("Lamp5 is nog niet gedefinieerd") else: print ("Lamp5 is ingesteld op", LAMPKLEUR5) try: LAMPKLEUR6 except NameError: print ("Lamp6 is nog niet gedefinieerd") else: print ("Lamp6 is ingesteld op", LAMPKLEUR6) try: LAMPKLEUR7 except NameError: print ("Lamp7 is nog niet gedefinieerd") else: print ("Lamp7 is ingesteld op", LAMPKLEUR7) try: BRIGHTNESS except NameError: print ("De brightness is niet ingesteld en dus maximaal 254") else: print ("De brightness is ingesteld op", BRIGHTNESS) print("") print("") print("Wat wil je doen?") print("") print("1 = Ander lampje instellen") print("") print("2 = Done, kleur de lampjes!") print("") KEUZEMENU = int(input("Maak je keuze: ")) if HOOFDMENU == "3": #Disco White Lights def theaterChase(strip, color, wait_ms=50, iterations=10): """Movie theater light style chaser animation.""" for j in range(iterations): for q in range(3): for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i+q, color) strip.show() time.sleep(wait_ms/1000.0) for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i+q, 0) while True: theaterChase(strip, Color(127, 127, 127)) if HOOFDMENU == "4": #Disco - colored def wheel(pos): """Generate rainbow colors across 0-255 positions.""" if pos < 85: return Color(pos * 3, 255 - pos * 3, 0) elif pos < 170: pos -= 85 return Color(255 - pos * 3, 0, pos * 3) else: pos -= 170 return Color(0, pos * 3, 255 - pos * 3) def theaterChaseRainbow(strip, wait_ms=50): """Rainbow movie theater light style chaser animation.""" for j in range(256): for q in range(3): for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i+q, wheel((i+j) % 255)) strip.show() time.sleep(wait_ms/1000.0) for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i+q, 0) while True: theaterChaseRainbow(strip) if HOOFDMENU == "5": #Rainbow effect - all lights the same color def wheel(pos): """Generate rainbow colors across 0-255 positions.""" if pos < 85: return Color(pos * 3, 255 - pos * 3, 0) elif pos < 170: pos -= 85 return Color(255 - pos * 3, 0, pos * 3) else: pos -= 170 return Color(0, pos * 3, 255 - pos * 3) def rainbow(strip, wait_ms=20, iterations=1): """Draw rainbow that fades across all pixels at once.""" for j in range(256*iterations): for i in range(strip.numPixels()): strip.setPixelColor(i, wheel((i+j) & 255)) strip.show() time.sleep(wait_ms/1000.0) while True: rainbow(strip) if HOOFDMENU == "6": # Rainbow effect - all lights a different color def wheel(pos): """Generate rainbow colors across 0-255 positions.""" if pos < 85: return Color(pos * 3, 255 - pos * 3, 0) elif pos < 170: pos -= 85 return Color(255 - pos * 3, 0, pos * 3) else: pos -= 170 return Color(0, pos * 3, 255 - pos * 3) def rainbowCycle(strip, wait_ms=20, iterations=5): """Draw rainbow that uniformly distributes itself across all pixels.""" for j in range(256*iterations): for i in range(strip.numPixels()): strip.setPixelColor(i, wheel((int(i * 256 / strip.numPixels()) + j) & 255)) strip.show() time.sleep(wait_ms/1000.0) while True: rainbowCycle(strip) if HOOFDMENU == "7": #Jumping lights effect def colorWipe(strip, color, wait_ms=50): """Wipe color across display a pixel at a time.""" for i in range(strip.numPixels()): strip.setPixelColor(i, color) strip.show() time.sleep(wait_ms/1000.0) while True: colorWipe(strip, Color(255, 0, 0), 0) # Red wipe time.sleep(2) colorWipe(strip, Color(0, 255, 0), 0) # Blue wipe time.sleep(2) colorWipe(strip, Color(0, 0, 255), 0) # Green wipe time.sleep(2) colorWipe(strip, Color(0, 0, 0, 255), 0) # White wipe time.sleep(2) colorWipe(strip, Color(255, 255, 255), 0) # Composite White wipe time.sleep(2) colorWipe(strip, Color(255, 255, 255, 255), 0) # Composite White + White LED wipe time.sleep(2) if HOOFDMENU == "8": #Dim all the lights strip.setPixelColor(0, (OFF[0])); strip.setPixelColor(1, (OFF[0])); strip.setPixelColor(2, (OFF[0])); strip.setPixelColor(3, (OFF[0])); strip.setPixelColor(4, (OFF[0])); strip.setPixelColor(5, (OFF[0])); strip.setPixelColor(6, (OFF[0])); strip.setPixelColor(7, (OFF[0])); LAMPKLEUR1 = OFF LAMPKLEUR2 = OFF LAMPKLEUR3 = OFF LAMPKLEUR4 = OFF LAMPKLEUR5 = OFF LAMPKLEUR6 = OFF LAMPKLEUR7 = OFF if HOOFDMENU == "9": #Shutdown Raspberry Pi os.system('sudo shutdown now') #Push settings on the strip strip.show(); |
Het definitieve kersthuis krijgt 15 LED’s. Dit script is hier te downloaden.
2.8 inch Adafruit Capacitive PiTFT Touchscreen
Vervolgens wil ik het script bedienen via een 2.8 inch Adafruit PiTFT touchscreen (capacitive #1983). Het touchscreen wordt gemakkelijk aangesloten via de GPIO pinnen en sluist de signalen door waardoor we toch de lampjes kunnen blijven bedienen.
Om de Raspberry zo in te stellen dat het Touchscreen werkt moet er nog wel het e.e.a. gebeuren. Zo kun je ervoor kiezen om de volgende speciale image op de Raspberry te installeren zodat het touchscreen meteen werkt:
https://learn.adafruit.com/adafruit-2-8-pitft-capacitive-touch/easy-install
Ik heb er echter voor gekozen om de installatie te tweaken volgens de handmatige stappen op bovenstaande pagina.
Nadat het touchscreen functioneert zorgen we ervoor dat de Raspberri niet meer in de grafische mode start door de configuratie in te stellen op “Boot to CLI”. De configuratiepagina wordt als volgt opgeroepen:
sudo raspi-config |
Mocht je toch weer in de CLI willen booten dan kan dat ook middels bovenstaande commando.
De GUI is namelijk nogal “klein” en lastig te besturen via de PyTFT en dus benutten we in de CLI het kleine schermpje ten volle.
*Tip: Sluit je Pi aan op de WiFi en beheer hem verder via VNC en/of SSH. Het kleine touchscreen is alles behalve ideaal om alle vervolgstappen uit te voeren.
Python script na booten
Omdat we straks alleen stroom op de Raspberry willen zetten om de LED’s te besturen moet het gemaakte Pythoin script starten na het booten van de Raspberry. Via cron (crontab –e) kunnen we met de @reboot switch een script of programma booten maar deze wordt in de achtergrond gestart. Om het .py script zichtbaar te starten na de boot gaan we een extra regel toevoegen aan het profiel bestand:
sudo nano /etc/profile |
En onderaan voegen we de volgende startregel toe (mijn Kersthuisje.py staat op de Desktop).
sudo python3 /home/pi/Desktop/Kersthuisje.py |
Na een reboot zal het Python script booten en afhankelijk van de instelling zullen de lampjes meteen gaan branden en kunnen deze direct beheerd worden.
Maar… a new problem arises!
PyTFT Backlight
Het blijkt dat de PyTFT uit springt zodra het Python script gestart wordt. Waarom? Dit blijkt alles te maken hebben met GPIO pin nummer 18. Pin nummer 18 stuurt namelijk de LED’s aan maar is ook de pin die het backlight van de PyTFT beheerd.
Na wat uitzoekwerk blijkt dat we de backlight controle uit kunnen schakelen door de 2 jumperpinnen op de achterzijde van de PyTFT te verbreken. Dus met wat hulp van een hete soldeerbout is de verbinding verbroken en wat blijkt, het backlight blijft nu permanent branden!
Als geluid stoort op de GPIO pinnen
Mocht de Raspberry zo ingesteld zijn dat geluid via de 3.5 headphone jack gestreamd wordt dan kan dit storen op de LED’s omdat het geluid dan ook over de GPIO 18 pin gestuurd wordt (nummer 18 blijkt by far de belangrijkste pin) dan kunnen we de audio beter laten routeren over de HDMI uitgang. Om dit te doen gebruiken we het volgende commando:
amixer cset numid=3 2 |
Door het commando weer uit te voeren met nummer 1 wordt de audio weer over de 3.5 headphone jack gestreamd:
amixer cset numid=3 1 |
Nadat we de audio setting naar wens hebben ingesteld slaan we deze op met het commando:
alsactl store 0 |
Verven maar…
Het uitzoeken van alle elektronica en het schrijven van een goed werkend script heeft de nodige tijd in beslag genomen. Ondertussen is het mei en wordt het zaak dat er wat verf op de muren komt. Allereerst eens een likje grondverf en jongen…. wat maakt verf een groot verschil. Het huis ziet er meteen alweer heel anders uit:
De muurtjes wit, en het dakje bruin en op mijn eisenlijstje is alles afgevinkt. Mooi!
Nu gaan we aan de details van het interieur werken.
Interieur
Ik heb even nagedacht over het ruwe interieur, dus de muren en de vloeren. Ik heb gekozen voor een beetje bonte look.
De vloeren moeten ogen als houten vloeren. Hiervoor heb ik verschillende kleuren bruin gebruikt met het volgende resultaat:
Voor de muren heb ik verschillende soorten behang gebruikt. De Karwij was zo vriendelijk om me deze voorbeeldstukjes mee te geven zodat ik de binnenkant kon behangen. Om het nog nostalgischer te maken heb ik de beneden plafonds voorzien van houten balken. Al me al een lekkere bonte look:
Dakpannen
Nu het ruwe interieur klaar is wordt het tijd om de buitenkant van het huis te pimpen, te beginnen met het dak. Het dak moet voorzien worden van dakpannetjes. Maar waar ik eerst “echte” stenen pannetjes wilde gebruikten blijkt dat wat lastig te realiseren omdat het huis demontabel moet blijven. Na wat testen besloten om de dakpannen te maken van donkerrood schuurpapier en om deze op de houten ondergrond te lijmen.
En als we het dak dan toch zo goed mogelijk af willen maken schilderen we meteen de schoorsteen ook maar mee. Het resultaat mag er best zijn:
Kersthuis buitenkant
Ondertussen is het juli 2017 en de buitenkant moet echt vorm gaan krijgen. Wat ik eigenlijk wil is een “verweerde” buitenkant. Dus oude planken. Ik besluit om een groen/bruine onder kleur te nemen en om daarop lijntjes te zetten voor de “planken-look”. Want ook hier kan ik mijn originele idee niet uitvoeren (het potdekselen van verf roerlatjes) omdat het huis demontabel moet blijven. In de ontwerpfase ziet er dit als volgt uit:
Het nadeel van de dunne lijntjes blijkt te zijn dat deze van een klein afstandje al slecht zichtbaar zijn. Ook de groene kleur vindt ik eigenlijk te groen. Ok, dan doen we heel creatief wat donker- en lichtbruine vegen over de planken plaatsen en schilderen we de lijntjes van dikker.
Hoe dat er allemaal uit gaat zien is vanzelf te zien in de vervolgfoto’s. Nu eerst gaan we aan de slag met wat misschien we lde lastigste klus van allemaal is…
Kersthuis voorzien van elektriciteit
Jazeker. Het is een hele opgave om de elektriciteit aan te leggen. We hebben uiteraard de Raspberry Pi met LED lichtjes welke tezamen een hele berg draad nodig hebben. Maar daarnaast heb ik ook nog 2 authentieke lantaarnpaaltjes en een kachel voor in het huis. De kachel brand op 3V en hadden we dus aan kunnen sluiten op de Raspberry Pi. De lantaarnpaaltjes branden echter op 4.5V en zijn niet (zonder weerstanden) aan te sluiten op de Pi. Uiteindelijk besluit ik deze 2 attributen gemakkelijk aan te sluiten. Ik laat ze gewoon op batterijen werken en monteer ze onder de onderplaat, maar wel aan de voorkant zodat ik er makkelijk bij kan. Dat is tenminste… als de onderplaat open zou kunnen. ..
Dus als eerste zorg ik ervoor dat de onderplaat voorzien wordt van een pianoscharnier zodat ik deze als een “deksel” kan openen. Als dat gebeurt is dan is het tijd om wat gaatjes voor de draden in de onderplaat te maken. Op die manier zijn de draden niet storend en lopen ze meteen naar onderen. Omdat alles demontabel moet blijven worden alle aansluitpunten voordien van male/female jumper cable connectoren zodat alles onder de onderplaat gemakkelijk los te maken is zodat het hele huis na de kerst opgeruimd kan worden.
Nu dat gebeurt is, is het zaak om de Raspberry Pi zo in te bouwen dat ik het beeldscherm goed kan zien. Het lijkt me cool om deze aan de achterkant van de onderplaat in te bouwen zodat ik on-the-fly de lampjes kan besturen maar zodat het scherm niet de aandacht trekt. Al met al ziet dat er dus als volgt uit:
Nu de Pi ingebouwd is en ik eventueel gemakkelijk een toetsenbord en muis erbij kan pakken om de Pi te besturen wordt het zaak om de lampjes echt aan te gaan sluiten op de Pi. Het nadeel is dus dat er stroom aangelegd gaat worden door het hele huis waardoor het allemaal wat minder demontabel wordt. Om het een beetje demontabel te houden moet elke splitsing ook voorzien worden van jumper cable connectoren en ik moet zeker proberen om de kabels een beetje uit het zicht te houden. Dat wordt heel veel soldeerwerk… ! Och dan denk ik maar aan de woorden die mijn moeder altijd sprak: “er is geen enkel rotwerk of er komt een einde aan” dus laat ik maar dapper starten met het compartiment waar de kabels de hun kopje uit de vloer steken. Het 1e compartiment, de eetkamer.
En zo gaan we door naar de voordeur voor een buitenlampje en dan door naar de bovenliggende zolder slaapkamer. Vervolgens naar de zolder speel en bergruimte en dan weer omlaag naar de woonkamer. Tenslotte gaan we onder de plaat nog door om 2 lampjes aan te sluiten bij het dierenhol aan de voorkant (geen idee welke dieren ik hier in ga plaatsen. Misschien een paar vosjes…).
Heel veel uren, soldeertin en stroomdraad later ziet dit er dus uit zoals op onderstaande foto’s. Let ook even op de kleuren die de buitenkant gekregen heeft. Persoonlijk vindt ik het nog wel wat groen maar het lijkt al iets meer op een “blokhut”. Hopelijk maakt de sneeuw later dit effect verder af. Speaking of snow…
Sneeuw
Het is eind juli en bijna tijd om zomervakantie te gaan vieren en, nu het zonnetje hoog aan de Nederlandse hemel staat ben ik helemaal klaar om de sneeuw te gaan maken! Want zonder sneeuw is het kerstgevoel maar half aanwezig. Zonder sneeuw is het gewoon een huis.
De ondergrond van de plaat wordt voorzien van purschuim zodat het oppervlak niet glad meer is maar hobbelig. Door te werken met purschuim krijg je een “zachte” uitstraling die echt lijkt op sneeuw. Dus een busje pur en purren maar. Het resultaat is als volgt:
Pur kun je na 1 uur al snijden dus daarna aan de slag om de pur in de juiste vormen te snijden zodat het geheel wat lager wordt en de hekjes netjes passen:
Nu de ondergrond voorzien is van pur is het zaak om de pur te voorzien van witte verf…anders is de sneeuw nogal geel. Als dat ook gedaan is en het buiten goed geneeuwd heeft is het ook de bedoeling dat het huis en de hekjes voorzien worden van sneeuw. Hiervoor gebruik ik spuitsneeuw. Nadat ook deze voorzien zijn van sneeuw is het effect als volgt:
Het in elkaar zetten van het kersthuis
Nu we bijna op het einde zijn nog 1x ter resumé het volledig in elkaar zetten van het kersthuis. Het hele ding is demontabel maar na het installeren van de lampjes is het best een dingetje om hem weer in elkaar te zetten. Om het huis weer vlug in elkaar te zetten gaan we als volgt te werk.
1. Open de klep en bevestig de bedrading aan de onderzijde:
2. Zorg ervoor dat je de draadjes netjes door de vloerplaat haalt:
3. Plaats het tussenschot en bevestig de lamp voor de woonkamer:
4. Zet het huis verder als volgt in elkaar:
5. Bevestig de plafondplaat van de woonkamper met de lamp als volgt:
6. Bevestig de lamp boven de woonkamer:
7. Bevestig de lamp van de keuken en van de woonzolder boven de keuken:
8. Plaats het dak en bevestig de lamp op de woonzolder aan het dak:
9. Maak het dak dicht, plaats de hekjes en eventuele overige attributen en voila… het kersthuis staat in elkaar!
Het Eindresultaat
Begin augustus ben ik klaar met het kersthuis… op 1 ding na en dat is de finishing touch. De sneeuw!
Daar zit ik dan, zaterdagmiddag 9 december 2017. Sinterklaas is net het land uit en ook is de kerstboom vanochtend gezet in huize Baselier. Kerstattributen liggen al maanden in de winkels en op wat testhoutjes heb ik verschillende spuitbussen sneeuw geprobeerd maar spuitsneeuw is gewoon niet stevig genoeg. Dit valt te makkelijk en blijft slechts een korte periode mooi. Daarom maar gekozen voor “echte” strooisneeuw. Mooi… maar nog een aardig klusje om de sneeuw erop te lijmen. Het eindresultaat is echter wel heel gaaf.
Tenslotte worden een aantal attributen erbij geplaatst en op zaterdagavond 9 december 2017 is mijn kersthuis, het project dat een jaar geleden op 16 december 2016 begon klaar. Aanschouw het eindresultaat:
…ik ben benieuwd welke prachtige creaties mijn vader en broer gaan tonen over een paar weken. 2e kerstdag 2017 is de dag 🙂
Kosten
Omdat ik niet alle bonnetjes bewaard heb moet ik een schatting doen naar de kosten van het kersthuis. Een kijken, wat hebben we zoal gekocht:
- Hout – € 35
- Magneetband – € 10
- Houtlijm – € 7,50
- Verf – € 20,00
- Purschuim – € 10
- LED verlichting en bekabeling – € 25,00
- Raspberri Pi 3B Compleet – € 55,00
- Overige kerstattributen zoals spuitsneeuw, boom, kachel, figuurtjes etc – € 35
- TOTAAL – € 197,50
Mmmm ik hoopte een beetje onder de 100 euro te kunnen blijven…maar all-in blijkt toch dat dat niet gelukt is. Gelukkig dat we de gewerkte tijd (+/- 110 uur) maar niet doorrekenen 🙂
Het was een supergaaf project en erg leuk om te doen. Wat opvalt is dat je tegen veel zaken aanloopt gedurende het opbouw proces maar dat je met logisch denken altijd een oplossing vindt. Volgend jaar toch maar een heel dorp maken dan 🙂 Op naar kerst 2017…maar als jullie dit lezen is het na kerst 2017 dus in dat geval alvast GELUKKIG NIEUWJAAR en de allerbeste wensen!!!