Hallo liebe Leserinnen und Leser!
Vor Kurzem habe ich ein neues Projekt gestartet: Einen DIY-Lichtwecker mit Hilfe eines Arduinos und eines Raspberry/Banana Pis. Dieses Projekt ist noch nicht vollständig abgeschlossen, technisch allerdings schon lauffähig, weshalb ich mich entschlossen habe, heute einen ersten Artikel darüber zu veröffentlichen. Weitere Artikel mit Bildern des fertigen Projekts folgen (hoffentlich) in Kürze.
Dieses Projekt wird im Tutorial-Stil verfasst, es werden also alle Schritte genau beschrieben. Auf Grund der Vielzahl an Komponentenvariationen (Arduinos, LEDs etc.) kann es zu kleineren Differenzen mit meinen Schaltungen oder dem Code kommen. Die meisten Probleme dabei sollten sich allerdings recht einfach durch Lesen von Tutorials auf der Arduino-Seite oder andere Recherche lösen lassen.
Kommen wir nun zum Projekt selbst.
1. Benötigte Komponenten
- einen Arduino (z.B. Leonardo oder Pro Micro [wesentlich kleiner])
- einen Raspberry oder Banana Pi mit Debian-Betriebssystem (Raspbian, Bananian, etc.)
- ein 433 MHz Sender-/Empfänger-Set
- mehrere helle LEDs + passende Widerstände (ich habe 5 LEDs verwendet)
- Kabel, Schrumpfschläuche, Lötzinn, Lötkolben (optional könnt ihr natürlich ein Breadboard verwenden, für eine permanente Lösung ist allerdings ein Verlöten vorzuziehen)
2. Funktionsweise
Für die Funktionsweise habe ich mal ein kleines Diagramm erstellt:Der Raspberry/Banana Pi sendet also einen bestimmten Befehl über den an ihm angeschlossenen 433 MHz-Sender. Am Arduino befindet sich der 433 MHz-Receiver, der diesen Befehl empfängt und den der Arduino dann auswertet. Je nach Befehl sollen die LEDs langsam eingeschalten werden (fade), direkt eingeschalten werden oder ausgeschalten werden. Natürlich sind auch noch andere Szenarien möglich (auch in Kombination mit RGB-LEDs), aber ich möchte mich hier auf diese Grundfunktionen beschränken.
3. Verbinden der Hardware
Den Anschluss der 433 MHz-Sender an den Raspberry/Banana Pi habe ich hier im Blog ja schon skizziert, trotzdem hier noch einmal die Grafiken für den Anschluss der Sender:
Dieser Teil muss nicht unbedingt verlötet werden, hier tun es passende Jumper-Kabel und/oder ein Breadboard genauso.
Kommen wir zum neuen Teil: Der Anschluss des 433 MHz-Empfangsmoduls an den Arduino. Hierzu habe ich passende Grafiken für den Leonardo und den Pro Micro erstellt (inkl. einer LED für Testzwecke).
Arduino Pro Micro:Am Besten verlötet ihr die Teile erst einmal noch nicht, sondern steckt sie nur, um die Funktionsfähigkeit zu überprüfen (siehe nächster Schritt: Software). Letztendlich sollte der Aufbau mit allen LEDs und dem Empfänger am Arduino Pro Micro so aussehen:
In zusammengelöteter Form sieht das bei mir wie auf folgenden Fotos aus:
Leider hat sich mein eigentlich angedachtes „Gehäuse“ für den Lichtwecker (ein Windlichthalter mit Milchglas) als zu klein für den Arduino mit angeschlossenen Komponenten herausgestellt, sodass ich momentan noch auf der Suche nach einem passenderem Gehäuse bin. Fotos des fertigen Weckers kann ich daher zum aktuellen Zeitpunkt noch nicht zur Verfügung stellen.
Wer Tipps hat, kann mir diese gerne zukommen lassen, über Anregungen hierzu würde ich mich sehr freuen! :)
4.Benötigte Software-Grundlagen
4.1 Am Raspberry/Banana Pi
Voraussetzung für die folgenden Schritte ist, dass WiringPi auf eurem Raspberry oder Banana Pi funktionsfähig installiert ist. Wie das geht habe ich in diesem Artikel für den Raspberry Pi und hier
für den Banana Pi bereits beschrieben, sodass ich an dieser Stelle auf die verlinkten Artikel verweise.
Nun könnt ihr euch 433Utils herunterladen und installieren (Achtung: Git muss hierzu auf eurem Raspberry/Banana Pi installiert sein sudo apt-get install git-core ):
1 2 | git clone https://github.com/ninjablocks/433Utils.git cd 433Utils/RPi_utils |
Das Tool, das wir hier verwenden, nennt sich „codesend“ und kann folgendermaßen installiert werden (hierfür müssen die Werzeuge zum Kompilieren natürlich auf dem Gerät installiert sein sudo apt-get install gcc g++ make ):
1 | make codesend g++ RCSwitch.o codesend.o -o codesend –lwiringPi |
Falls es hier Probleme gibt, hilft es oft, den kompletten Pfad für WiringPi anzugeben.
Die Installation auf dem Raspberry/Banana Pi ist damit schon fertig und wir können auf dem Arduino weitermachen.
4.2 Am Arduino
Dazu benötigt ihr eine Bibliothek namens RCSwitch, welche ihr hier ) herunterladen könnt. Damit sie von der Arduino-IDE erkannt wird, muss sie extrahiert werden (wenn ihr euch das Archiv heruntergeladen habt) und in den Libraries-Ordner von Arduino auf eurem PC oder Mac gelegt werden. Für weitere Informationen hierzu verweise ich auf die entsprechende Arduino-Seite.
Ihr könnt nun einen Sketch entwerfen, der euch die später vom Raspberry/Banana Pi gesendeten Werte auf der Konsole anzeigt. Hierzu folgendes Beispiel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | /* RF_Sniffer Hacked from http://code.google.com/p/rc-switch/ by @justy to provide a handy RF code sniffer */ #include "RCSwitch.h" #include <stdlib.h> #include <stdio.h> RCSwitch mySwitch = RCSwitch(); void setup() { Serial.begin(9600); mySwitch.enableReceive(1); } void loop() { if (mySwitch.available()) { int value = mySwitch.getReceivedValue(); if (value == 0) { Serial.print("Unknown encoding"); } else { Serial.print("Received "); Serial.print( mySwitch.getReceivedValue() ); Serial.print(" / "); Serial.print( mySwitch.getReceivedBitlength() ); Serial.print("bit "); Serial.print("Protocol: "); Serial.println( mySwitch.getReceivedProtocol() ); } mySwitch.resetAvailable(); } } |
4.3 Test der Kommunikation zwischen Raspberry/Banana Pi und Arduino
Um nun zu testen, ob eure Funkverbindung klappt, könnt ihr den obigen Sketch auf euren Arduino übertragen und Codes von eurem Raspberry/Banana Pi aus senden (übertragt erst den Sketch auf den Arduino und öffnet die serielle Konsole in der IDE, um etwas zu sehen):
1 2 | pi@raspberrypi ~/433Utils/RPi_utils $ sudo ./codesend 666 sending code[666] |
Auf der Konsole des Arduinos sollte nun so etwas kommen:
1 2 3 | Received 666 / 24bit Protocol: 1 Received 666 / 24bit Protocol: 1 Received 666 / 24bit Protocol: 1 |
Klappt das nicht, prüft nochmal die Verkabelung, schaut, ob der Code auf den Arduino übertragen werden konnte oder bringt eine Antenne an Sender und/oder Empfänger an. Erfahrungsgemäß funktioniert die Übertragung relativ problemlos.
5. Lichtwecker-Funktionalität
Bisher haben wir nur Codes vom Raspberry/Bananan Pi an den Arduino gesendet. Wir erweitern nun diesen Code, um die LED, welche in den Grafiken oben zu sehen ist, zu steuern:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #include "RCSwitch.h" #include <stdlib.h> #include <stdio.h> RCSwitch mySwitch = RCSwitch(); float brightness = 0; float fadeAmount = 0.01; int led = 3; void setup() { pinMode(led, OUTPUT); Serial.begin(9600); mySwitch.enableReceive(1); } void serial_output() { Serial.print("Received "); Serial.print( mySwitch.getReceivedValue() ); Serial.print(" / "); Serial.print( mySwitch.getReceivedBitlength() ); Serial.print("bit "); Serial.print("Protocol: "); Serial.println( mySwitch.getReceivedProtocol() ); } void fade_led() { while(brightness < 255){ analogWrite(led, brightness); brightness = brightness + fadeAmount; if (brightness == 0 || brightness == 255) { fadeAmount = -fadeAmount ; } // wait for 30 milliseconds to see the dimming effect delay(30); } } void loop() { if (mySwitch.available()) { int value = mySwitch.getReceivedValue(); if (value == 666) { fade_led(); serial_output(); } else if (value == 777) { digitalWrite(led, HIGH); serial_output(); } else if (value == 888) { digitalWrite(led, LOW); serial_output(); } else { Serial.println("Unknown command"); serial_output(); } mySwitch.resetAvailable(); } } |
Über sudo ./codesend 666 sollte die LED nun langsam eingeschaltet werden, über sudo ./codesend 777 direkt auf hellster Stufe eingeschalten werden und über sudo ./codesend 888ausgeschalten werden.
Klappt das, könnt ihr auch die restlichen LEDs an den Arduino anschließen und mit dem Löten beginnen. Hier nochmal die Grafik zum Aufbau:Der Arduino-Sketch muss nun natürlich erweitert werden, damit alle LEDs synchron geschalten werden können:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | #include "RCSwitch.h" #include <stdlib.h> #include <stdio.h> RCSwitch mySwitch = RCSwitch(); float brightness = 0; float fadeAmount = 0.01; int led1 = 9; int led2 = 3; int led3 = 5; int led4 = 6; int led5 = 10; int led_number; void setup() { pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); pinMode(led4, OUTPUT); pinMode(led5, OUTPUT); Serial.begin(9600); mySwitch.enableReceive(1); } void serial_output() { Serial.print("Received "); Serial.print( mySwitch.getReceivedValue() ); Serial.print(" / "); Serial.print( mySwitch.getReceivedBitlength() ); Serial.print("bit "); Serial.print("Protocol: "); Serial.println( mySwitch.getReceivedProtocol() ); } void fade_led() { while(brightness < 255){ analogWrite(led1, brightness); analogWrite(led2, brightness); analogWrite(led3 , brightness); analogWrite(led4, brightness); analogWrite(led5 , brightness); brightness = brightness + fadeAmount; if (brightness == 0 || brightness == 255) { fadeAmount = -fadeAmount ; } // wait for 30 milliseconds to see the dimming effect delay(30); } } void loop() { if (mySwitch.available()) { int value = mySwitch.getReceivedValue(); if (value == 666) { fade_led(); serial_output(); } else if (value == 777) { digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); digitalWrite(led4, HIGH); digitalWrite(led5, HIGH); serial_output(); } else if (value == 888) { digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); digitalWrite(led4, LOW); digitalWrite(led5, LOW); serial_output(); } else { Serial.println("Unknown command"); serial_output(); } mySwitch.resetAvailable(); } } |
Damit wurden alle gewünschten Funktionen des Lichtweckers implementiert und der Arduino kann nun vom Raspberry/Banana Pi aus geschalten werden.
6. Weitere Schaltmöglichkeiten vom Raspberry/Banana Pi
Bisher werden die LEDs am Arduino nur über die Konsole geschalten. Um die LEDs auch über ein Webinterface steuern zu können, habe ich in Python einen kleinen Socket-Server geschrieben, der als Daemon auf dem Raspberry/Banana Pi ausgeführt werden kann und mit dem sich analog zu den Funksteckdosen auch ein Webinterface umsetzen lässt.
Das Script für den Daemon ist relativ klein und simpel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | import socket import sys import os import time from thread import * HOST = '' # Symbolic name meaning all available interfaces PORT = 1212 # Arbitrary non-privileged port state = 0 path_to_codesend = "sudo /home/pi/433Utils/RPi_utils/codesend " s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print 'Socket created' #Bind socket to local host and port try: s.bind((HOST, PORT)) except socket.error , msg: print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] sys.exit() print 'Socket bind complete' #Start listening on socket s.listen(10) print 'Socket now listening' #Function for handling connections. This will be used to create threads def clientthread(conn): #infinite loop so that function do not terminate and thread do not end. while True: #Receiving from client data = conn.recv(1024) lenght_data = len(data) if lenght_data >0: if data[0] == "a": arduino(data) if data[0] == "b": print "not (yet) implemented" else: print data if not data: break #came out of loop conn.close() def arduino(data): global state if data[1:4] == "666": print "666" state = 2 n=0 while n<4: os.popen(path_to_codesend+data[1:4]) time.sleep(1) n=n+1 if data[1:4] == "777": print "777" state = 1 n=0 while n<4: os.popen(path_to_codesend+data[1:4]) time.sleep(1) n=n+1 if data[1:4] == "888": print "888" state = 0 n=0 while n<4: os.popen(path_to_codesend+data[1:4]) time.sleep(1) n=n+1 if data[1:4] == "999": print "999" conn.send(str(state)) if data[1:4] != "666" and data[1:4] != "777" and data[1:4] !="888" and data[1:4] !="999": print "wrong command number" #now keep talking with the client while 1: #wait to accept a connection - blocking call conn, addr = s.accept() print 'Connected with ' + addr[0] + ':' + str(addr[1]) #start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function. start_new_thread(clientthread ,(conn,)) s.close() |
Speichert euch das Python-Script unter z.B. „socket_server_codesend.py“ auf dem Raspberry/Banana Pi und führt es via sudo python socket_server_codesend.py bzw. sudo python socket_server_codesend.py& (im Hintergrund) aus. Achtung! Der Pfad zu codesend muss eventuell angepasst werden! Das Script kann auch einfach erweitert werden, um z.B. auch die Funksteckdosen damit zu schalten.
Wir können uns nun mit diesem Socket-Server von einem anderen Gerät im Netzwerk aus verbinden, um Befehle über codesend abzusetzen und damit die LEDs am Arduino zu steuern. Hier mal ein schnelles Beispiel in Python (Socket-Client):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/usr/bin/python import socket import argparse # IP-Adresse des Servers und Port des Daemons address = '192.168.11.56' # Anpassen! port= 1212 # Anpassen, falls geaendert status = '' sock = socket.socket() try: sock.connect((address,port)) sock.send("a999") status = sock.recv(2048) except Exception, e: print e if status == '1': print 'an' elif status == '2': print 'dimm' elif status == '0': print 'aus' else: print 'Status konnte nicht ermittelt werden' |
Damit würde z.B. der Status abgefragt werden.
Jetzt können wir uns noch ein kleines Webinterface basteln, über das wir die LEDs am Arduino ganz einfach einschalten, dimmen oder ausschalten können. Ich habe hier mal ein einfaches Interface erstellt, das ihr hier herunterladen könnt:
Das Webinterface benötigt PHP sowie einen laufenden Daemon des Socket-Servers. Es kann im aktuellen Stadium die LEDs am Arduino nur an- und ausschalten und sieht so aus:Es handelt sich dabei um das abgewandelte Webinterface, das ich für meine Funksteckdosen bereits im Einsatz habe (siehe hier).
Das ist der aktuelle Stand des Projekts. Bitte beachtet, dass das Projekt in einem eher frühen Stadium ist und daher noch der eine oder andere Fehler enthalten sein kann. Wenn ihr einen findet, wäre ich über eine kurze Info sehr dankbar!
Was noch angedacht ist:
- Erweiterung des Webinterfaces um eine Dimmfunktion (da muss ich mir noch überlegen, wie ich das am übersichtlichsten gestalte)
- Möglichkeit, den Wecker über das Webinterface zu programmieren (momentan erfolgt die Programmierung noch über einen manuellen Eintrag in cron)
- schönes Gehäuse, in dem der Arduino samt angeschlossender Komponenten untergebracht werden kann
Die entsprechenden Artikel zu den einzelnen Punkten werde ich in Zukunft noch nachreichen. Gerne dürft ihr euch aber auch an dem Projekt beteiligen, neue Ideen und/oder Lösungsvorschläge sind sehr willkommen!
Bei Fragen, Anregungen, Problemen usw. könnt ihr natürlich wie immer das Kommentarfeld unten benutzen.
Hallo,
das ist ja mal ein interessantes Projekt! Ich hätte noch eine Frage zu den LEDs: Welche verwendest du da und werden die hell genug, damit man morgens aufwacht?
Danke + Grüße
Hi Jon,
aktuell habe ich diese LEDs am Arduino. Den Wecker habe ich aktuell noch nicht im „Produktiveinsatz“, da noch das Gehäuse fehlt. Dieses soll an der Vorderseite eine Milchglasscheibe besitzen, das das Licht streut, aber auch einen Teil nach innen reflektiert und einen Teil absorbiert, sodass nicht das ganze Licht der LEDs transmittiert wird. Daher kann ich noch nicht genau sagen, wie hell der Wecker mit den aktuell verbauten LEDs letztendlich wird. Auch dürfte es recht individuell ausfallen, ob man bei dem Licht schon aufwacht oder noch weiterschläft. Ein zusätzlicher Wecker mit Ton ist daher durchaus empfehlenswert ;)
Aber wie gesagt: Genaueres kann ich erst sagen, wenn das Projekt abgeschlossen ist. Daher habe ich den LED-Typen auch (noch) nicht in den Artikel aufgenommen.
Grüße zurück!
Hi!
Gibts schon Neuigkeiten wegen dem Gehäuse? Wäre interessiert das Projekt nachzubauen aber möchte am Ende nicht einen blanken Arduino am Nachttisch haben ;-)
Hallo Chris,
jein – also ich habe zumindest eine Idee und mir auch schon ein 3D-Modell erstellt für einen Eigenbau. Zur Umsetzung bin ich allerdings noch nicht gekommen. Ich habe aber auf jeden Fall vor, das Projekt weiter zu betreiben.
Hallo! Gibts schon neues zum Ghäuse?
Hi Chino,
3D-Modell steht, Materialien sind ausgesucht. Wenn ich mal etwas Luft habe, gehts zum Baumarkt und es wird gebastelt. Kann aber noch etwas dauern ;)
Push^^
Hallo Ben,
ich gebe zu – das Projekt lasse ich etwas schleifen ?
Materialien habe ich mittlerweile sogar zu Hause, nur weiß ich noch nicht, wie ich meine Plexiglas-Platte schneiden soll.
Hallo Alex,
super Tutorial, interessantes Projekt und sehr ausfühlich beschrieben! Ich werd das bei Gelegenheit auch mal ausprobieren! :)
Hi,
Bin recht neu in dieser Thematik. Aber nun doch die Frage:
Kann ich das ganze nicht direkt über den Arduino laufen lassen? Wieso muss das denn per Funk geschaltet werden?
oder liegt das daran, dass du am Einsatzort kein LAN hast?
Gibt es sonst schon Fortschritt bei diesem interessanten Projekt?
Grüße
Hi Sebastian,
du hast recht – da gibt es noch viele andere Lösungen, die auch zum Ziel kommen. Es war die günstigste Lösung für mich, da ich diese Komponenten zu Hause hatte ;)
Bzgl LAN: Dafür bräuchte man eine Ethernet-Schnittstelle für den Arduino, welche etwas teurer ist als die 433MHz Lösung, aber sicher auch eine gute Idee. Zudem müsste bei einer reinen Arduino-Lösung die Zeit entweder über LAN bezogen werden, oder man bräuchte noch eine RTC o.ä..
Zum Fortschritt: Aktuell habe ich nur ein 3D-Modell des Gehäuses, umgesetzt habe ich es bisher noch nicht :(
Hallo zusammen!
Ich bin auch gerade dabei, einen Wecker mit Hilfe des Raspberry Pi umzusetzen (nicht so wie hier, sondern mit Internetradio). Dazu möchte ich ein Webinterface zur Programmierung benutzen – leider komme ich hier aber nicht weiter, da ich nicht weiß wie ich die eingegebenen Zeiten an den Pi übertragen kann, sodass er zur eingeschalteten Zeit leutet.
Kann mir hier jemand weiterhefen. Wäre sehr dankbar!
(ich habe es einfach mal hier als Kommentar gepostet, da der Artikelersteller wohl das gleiche umsetzen möchte, beziehungswiese schon hat)
Hi Leo,
ich hab es leider (immer) nocht nicht geschafft, mich um das Interface zu kümmern. Aber es gibt sicher Möglichkeiten mit PHP cronjobs anzulegen und zu löschen.
Ich habe auch einen: Zeitschaltuhr & 200W ESL 6500K & Reflektor.
Da ich aber auch ein RasPi habe, probiere ich Deine Variante vielleicht mal aus.
:D
Der Wecker ist für Menschen gedacht und nicht für „Tomaten“
Hallo, super Projekt. Habe auch etwas ähnliches vor jedoch kaum Erfahrung in diesem Gebiet, das soll sich jetzt ändern.
Wo finde ich denn zweiten Teil deines Tutorial oder ist der. Noch nicht fertig?
Hi Alexander,
leider habe ich dieses Projekt aus Zeitmangel nicht weitergeführt.
Hi,
Deine Bemühungen in Ehren, aber was soll man denn mit einem halb-fertigen Tutorial?
Sorry, aber da liest man und arbeitet eventuell alle Punkte brav ab und am Ende steht dann: „leider habe ich dieses Projekt aus Zeitmangel nicht weitergeführt.“
FÜRN ARSCH MANN! Mach etwas fertig und poste es dann. So stiehlst Du nur Deinen Lesern die Zeit.
Hallo Marcus,
im ersten Absatz des Artikels steht doch bereits, dass das Projekt nicht abgeschlossen ist 😕
Leider kann ich als nicht-kommerzieller Hobby-Blogger nur begrenzt Zeit für Projekte aufwenden. Falls du das Projekt weiterführen möchtest, kann ich dir gerne anbieten deine Fortsetzung hier zu veröffentlichen oder zu verlinken.
Wie viele LEDs kann ich den maximal an den Arduino packen? Vier sind ggf etwas schwach. Ich habe eventuell eine Idee für ein „Gehäuse“. Sollte ich das nachbauen und die Idee sich als brauchbar erweisen werde ich dir das mitteilen :-)
Na doll … da sucht man nach anderen die sowas schonmal gemacht haben, findet diesen Eintrag als ersten via Google ganz oben und dann isses aufgegeben worden …
Was soll man denn damit? …
Grade der spannende Teil ist unfertig, den Rest bekommt man mit ein wenig Überlegen auch selbst hin …