Wenn die Katze zweimal kratzt – Raspberry Pi als Helferchen #1
Was jedoch macht er, wenn die Katze zum Terroristen mutiert und morgens früh an der Türe kratzt, weil sie chronisch hungrig ist? Klar, er greift sich den nächstbesten Einplatinencomputer und lötet ihn zu einem Gadget zusammen, das sein Problem für immer beseitigt.
Dieser Blog-Beitrag beschäftigt sich mit einem Problem eines Katzenbesitzers und dem technischen Ansatz dieses zu lösen. Dieses Projekt stützt sich auf Informationen aus dem Blog-Beitrag von David Bryan , der sicherlich einen Blick wert ist.
Meet the cat – Mia, die Zerstörerin 😉
Weil kein guter Internetbeitrag ohne ein Bild einer Katze auskommt (IMHO), bitte sehr:
„Mia Internetgemeinschaft, Internetgemeinschaft Mia“.
Warum macht die Katze das eigentlich?
Allem voran möchte ich vorausschicken, dass ich kein ausgewiesener Katzenexperte bin und hier nur meine Erfahrung als langjähriger Katzenbesitzer wiedergeben kann.
Das eben thematisierte System von Röhren mit Katzen erklärt, dass die Katze in ihrer natürlichen Umgebung durchaus bis zu 20 mal pro Tag frisst. Nämlich immer dann, wenn sich ihr die Gelegenheit bietet, also eine Maus oder ein kleiner Vogel vorbeikommt. Ebenfalls hat Futter keine soziale Bedeutung für die Katze, es ist ein Erhaltungstrieb. Zuletzt ist die Katze ein Gewohnheitstier, das gerne festen Strukturen und Tagesabläufen folgt.
Dieser angeborene Charakter führt zu einigen Problemen für Berufstätige. Man hat von Montag bis Freitag einen geregelten Ablauf. Der Zeitraum, in dem man aufsteht ist genauso gleichbleibend, wie der Zeitraum in dem man heimkommt. Für die Katze ist das ideal. Jetzt hat der Berufstätige aber auch mal Wochenende und möchte eventuell ein Stündchen später aufstehen. Nicht doch, denkt sich die Katze. Die Katze ist ein Gewohnheitstier haben wir gelernt und fängt zur gewohnten Aufstehzeit an, sich bemerkbar zu machen. Sie kratzt an der geschlossenen Zimmertüre und miaut. An Schlaf ist jetzt nicht mehr zu denken. Klar doch sie hat Hunger und es ist schließlich die Zeit, in der die Maus oder der kleine Vogel vorbeikommen müsste. Das sollten wir Besitzer doch verstehen können, oder? Und weil du es noch immer nicht verstanden hast, fange ich morgen damit gleich noch 30 Minuten früher an, denkt sich die Katze.
„Ja ich hab dich verstanden Katze. Ich löse das Problem. Aber ich löse es auf meine Weise.“
Die Idee – Was muss das Dingens denn können?
„Das Dingens“ soll möglichst verhindern, dass meine Katze schon ab 5 Uhr früh an meiner Schlafzimmertüre kratzt und Radau macht. Das ist Ziel Nummer eins. Es muss Futter auswerfen, nachdem es ein akustisches Signal abgegeben hat. Außerdem möchte ich eventuell ohne großen Aufwand eine Extra Portion auswerfen können. Es braucht also einen Knopf. Außer dem Befüllen soll alles automatisch, nach einem festen Zeitplan ablaufen. Es soll auch nicht viel kosten. Wäre es nicht super, die Katze auch noch beim Fressen beobachten zu können? Webcam also?
Was würde sich denn dafür wohl eignen? Ein Raspberry Pi natürlich. Lange musste ich mir das nicht überlegen.
Der Einkauf – Teileliste
- Raspberry Pi (Vorzugsweise Version 3, da WLAN integriert ist) – ca. 39 €
- Micro SDHC Karte, 16GB reichen völlig – ca. 5 €
- Steckernetzteil Micro USB 5V, 2,5A – ca. 8 €
- USB Hub mit eigener Stromversorgung (für die Webcam) – ca. 9 €
- Webcam (Empfehlung Logitech C270) – ca. 28 €
- Servomotor (am besten einen sogenannten „continous servo“ oder einen normalen, den man dann noch modden muss) – ca. 13 €
- Taster – ca. 4 €
- Piezo Schallwandler – ca. 1 €
- Draht / Litze – ca. 3 €
- Streifenrasterplatine – ca. 2 €
- Stiftleiste – ca. 1 €
- Flachbandkabel – ca. 6 €
- Futterspender / Müslispender – ca. 38 €
Wenn man nicht das ein oder andere davon ohnehin schon hat, dann belaufen sich die Kosten auf ca. 160 €. Es sei erwähnt, dass es fertige Fabrikate in der Preisklasse von ca. 80 € gibt. Die sind aber nicht so cool, wie unser Futterautomat und haben auch keine Webcam, Webinterfaces, Linux-Betriebssystem, etc.
Das Werkzeug – Was muss ich haben?
- Lötkolben
- Lötzinn
- Werkbank (ist von Vorteil)
- Heißklebepistole
- Sonstiges Werkzeug, wie Schraubendreher, Zange, kleine Säge, etc.
Das Handwerk – löten, kleben, basteln!
- Schritt 1 – Servo modden für 360° Drehung
Ich habe einen herkömmlichen Servo gekauft und habe ihn einem Mod unterzogen, der ihn dazu bringt unendlich im Kreis zu drehen, was ein normaler Servo eben nicht macht. Dieser Mod ist zum Beispiel hier ganz gut beschrieben und würde hier den Rahmen sprengen.
- Schritt 2 – Servo an Spender montieren
Man muss dafür sorgen, dass der Servomotor am Spenderrad dreht, wenn er angetriggert wird. Das habe ich gelöst, indem ich an der Futterspenderachse den Knopf abgenommen habe und den Servokopf mit Heißkleber daran befestigt habe. Damit der Servo nun nicht am vorderen Ende des Futterautomats sichtbar ist, habe ich den Servo auf die Rückseite (also Richtung Standfuß) des Automats verlagert. Das macht auch die Verkabelung maßgeblich einfacher. Auf den Bildern sieht man ebenfalls, dass ich am Gehäuse des Spenders ein bisschen Plastik aussparen musste.
- Schritt 3 – Platine mit Piezo, Knopf und Servo löten
Jetzt muss man nur noch den Knopf, das Piezo Element und den Servo auf der Lochrasterplatine zusammenlöten und fertig.
Es sei gesagt, dass ich in meinem Beispiel in den Bildern unten einen alten Raspberry Pi mit kleiner GPIO Gruppe verwendet habe. Die neue GPIO Gruppe mit 40 Pins unterscheidet sich in den ersten 26 Pins nicht vom alten Modell und kann deshalb genau so wieder umgesetzt werden.
Ich habe mit den Stiftleisten einen kleinen Socket gelötet für das Flachbandkabel. Wichtig ist, dass man auf der Leiterplatine zwischen dem Socket die Leiterbahnen trennt, damit es nicht zum Kurzschluss kommen kann. Das kann man mit einem Messer machen oder auch mit einem kleinen Bohrer.
Dann habe ich Lötbrücken für 5V und Masse erstellt und habe schließlich via Kabelbrücke die Ein- und Ausgänge für Taster, Piezo-Element und Servo vom Socket weg, auf die Platine gebracht. Für den Servo habe ich ein 3 Pin Socket mit der Stiftleiste gelötet, sodass der Servo auf die Platine aufgesteckt werden kann, ohne dass man den Originalstecker abzwicken muss.
Alle Elemente bekommen gemeinsam eine Masse. Der Beeper bekommt 5V auf einem Ausgang (Pin 18 auf dem Board – GPIO 24) und der Taster kommt auf einen Eingang (Pin 11 auf dem Board – GPIO 17). Auf der Masseseite des Tasters ist noch ein Widerstand eingelötet.
Der Servo bekommt ebenfalls 5V und Masse und außerdem kommt seine Steuerleitung auf den PWM Pin am Raspberry Pi (Pin 12 auf dem Board – GPIO 18).
Zur Erklärung der Schaltung folgendes, vereinfachtes Schaltbild:
Profitipps: Klebt euren Piezo Pieper mit einem Taschentuch ab. Er wird sonst viel zu laut piepen. Außerdem kann man die Platine in Elektrikertape einwickeln:
- Schritt 4 – Alles in den Standfuß einbringen
Nun muss man nur noch alles in den Standfuß einbringen und den Automat zusammensetzen. Es hilft ein Schraubendreher, Heißkleber, Holz oder was man so zur Hand hat. Wie man auf den Bildern sieht, ist es auch sinnvoll ein Case für den Raspberry Pi zu verwenden. Ich habe meines mit Klettband am Standfuß des Spenders befestigt.
- Schritt 5 (optional) – Spender in erhöhter Position anbringen und Rutsche montieren
Ich musste den Automaten auf einen Schrank stellen und eine Rutsche montieren. Denn schon kurz nachdem ich den Automaten befüllt auf den Boden gestellt habe, hat sich mein Tiger darüber hergemacht und ihn aufgeknackt. Ich erwischte sie bei dem Versuch das gesamte Essen in einem Rutsch zu essen.
Das Herzstück – Der Code
Jetzt muss unser technisches Wunderwerk nur noch programmiert werden. Hierzu benötigen wir den Raspberry Pi mit installiertem Debian. Am besten nimmt man die originale Version der Foundation, gerne auch in der Lite Variante. Wichtig ist, dass man die GPIO Librarys installiert hat, damit man überhaupt mit der Technik interagieren kann. Voraussetzung ist natürlich auch Netzwerkanbindung, entweder per Lankabel oder auch per WLAN.
Der Code ist ein Python Script. Zuerst werden Imports und Definitionen vorgenommen und dann erfolgt eine Endlosschleife die prüft, ob der Knopf gedrückt ist oder ob es Fütterungszeit ist:
#Imports from RPIO import PWM import time import datetime import RPi.GPIO as GPIO import logging #Loggingdefinitionen logger = logging.getLogger('FeederPi') hdlr = logging.FileHandler ('/var/log/FeederPi.log') formatter = logging.Formatter ('%(asctime)s %(levelname)s %(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(logging.INFO) #Definitionen Pins ServoPin=18 BeeperPin=24 ButtonPin=17 #Setup der GPIO Pins fuer Beeper und Button GPIO.setmode(GPIO.BCM) GPIO.setup(BeeperPin, GPIO.OUT) GPIO.setup(ButtonPin, GPIO.IN) servo = PWM.Servo() #Definitionen Funktionen def servo_CW(ServoPin,SleepTime): servo.set_servo(ServoPin, 1200) time.sleep(SleepTime) servo.stop_servo(ServoPin) time.sleep(.25) def servo_CCW(ServoPin,SleepTime): servo.set_servo(ServoPin, 2000) time.sleep(SleepTime) GPIO.output(BeeperPin, False) print "Ok, Essen ist auf dem Weg" time.sleep(.75) servo_CW(ServoPin,FeedTime) servo_CCW(ServoPin,.2) def feed_time(Feed_hour,Feed_minute,FeedTime): if time.strftime("%H") == "Feed_hour" and time.strftime("%M") == "Feed_minute": print "Fuetterungszeit" feed(FeedTime) time.sleep(1.5) #Eigentliche Schleife, die Input erwartet while True: now = datetime.datetime.now() time.sleep(1) # wird der Knopf gedrueckt? if ( GPIO.input(ButtonPin) == True): feed(.7) logger.info('Fuetterung per Knopf') # Trifft eine Zeitkondition zu? if time.strftime("%H") == "06" and time.strftime("%M") == "00": print "Fuetterungszeit volle Portion" logger.info('Geplante Fuetterung - ganze Portion') feed(.6) time.sleep(60) if time.strftime("%H") == "12" and time.strftime("%M") == "00": print "Fuetterungszeit volle Portion" feed(.6) logger.info('Geplante Fuetterung - ganze Portion') time.sleep(60) # Sollte keine Kondition zutreffen geht die Schleife von vorne los, bis ein Kondition zutrifft
Servicedefinition unter „/etc/init.d/feederpi“:
#!/bin/sh # /etc/init.d/feederpi ### BEGIN INIT INFO # Provides: feederpi # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: FeederPi # Description: FeederPi fuettert meine Katze. ### END INIT INFO start() { echo "Starting feederpi" python /root/feederpi.py >/dev/null 2>&1 & } stop() { echo "Stopping feederpi" kill -9 $(pidof python) >/dev/null 2>&1 } case "$1" in start) start ;; stop) stop ;; restart) stop start ;; *) echo "Usage: $0 {start|stop|restart}" ;; esac exit 0
Dann noch mit „update-rc.d feederpi defaults“ dafür sorgen, dass der Service „feederpi“ beim boot gestartet wird und fertig.
Die Optik – MJPG Stream mit Webcam
Damit wir unseren geliebten Stubentiger nun noch beim Fressen beobachten können, benötigen wir eine Webcam-Übertragung. Es gibt fertige Lösungen für Linux, wie zum Beispiel Motion, die ich für meine Überwachungskameras auch gerne einsetze. Diese Lösungen jedoch sind meist sehr ressourcenintensiv. Damit aber der Futterautomat so stabil wie möglich läuft, verwende ich hierfür etwas „kleineres“. Und zwar den (schon etwas veralteten) MJPG Streamer aus dieser Quelle.
Diesen lasse ich im Autostart (/etc/init.d/feedercam) mit folgender Konfiguration hochlaufen:
#!/bin/sh # /etc/init.d/feedercam ### BEGIN INIT INFO # Provides: mjpg_streamer # Required-Start: $all # Required-Stop: $all # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: MJPG-Streamer # Description: MJPG-Streamer takes JPGs from Linux-UVC compatible webcams and streams them as M-JPEG via HTTP. ### END INIT INFO start() { echo "Starting mjpg-streamer..." /usr/bin/mjpg_streamer -i "/usr/lib/input_uvc.so -d /dev/video0 -r 800x600 -f 10 -l off" -o "/usr/lib/output_http.so -w /var/www/mfeedercam -p 8090" >/dev/null 2>&1 & } stop() { echo "Stopping mjpg-streamer..." kill -9 $(pidof mjpg_streamer) >/dev/null 2>&1 } case "$1" in start) start ;; stop) stop ;; restart) stop start ;; *) echo "Usage: $0 {start|stop|restart}" ;; esac exit 0
Man sieht, dass der Script den MJPG Streamer startet und als Input „/dev/video0“ verwendet. Außerdem verwendet er als Output das Modul http auf Port 8090 mit dem Pfad „/var/www/mfeedercam“. Dort befindet sich eine index.html, die vom MJPG Streamer mitgeliefert wird:
So streamt er mir im lokalen Netz einen MJPG Stream, den ich dann von jedem Endgerät im Netzwerk anschauen kann:
![Blick durch die Webcam der Raspberry Pi Futtermaschine](https://blog.to.com/wp-content/uploads/2016/06/webcam-300x227.jpg)
Die Fehler – Was könnte besser funktionieren?
Es ist bekannt, dass der Raspberry Pi keine Real-Time Clock hat. Da unser Script aber für die Pulsweitenmodulierung des Servos mit einer Zeit arbeiten muss, bedeutet das, dass die ausgeworfene Futterportion unterschiedlich groß sein kann. Je nachdem wie ausgelastet der Raspberry Pi gerade ist, variiert die Mengenausgabe. Das jedoch ist gar nicht so schlecht, da die Katze in freier Wildbahn auch nicht immer eine gleich große Maus findet.
Ansonsten habe ich in den 2 Jahren, in denen ich den Automat betreibe, keine weiteren Fehler entdeckt.
Die Kür – Wie kann man denn jetzt noch einen draufsetzen?
Der Futterautomat und auch meine Überwachungskameras sind in meinem Heimnetzwerk geschützt durch eine Sophos UTM. Die Webinterfaces des Automaten und der Überwachungskameras sind veröffentlicht via Webserverprotection mit Reverse Authentication und 2-Faktor-Authentizierung. So kann ich auch von unterwegs nachsehen, ob es meinem Stubentiger gut geht und die Sicherheit leidet auch nicht darunter.
Und weils so schön ist
Es gibt nur noch eines, was schöner ist als ein Bild von einer Katze im Internet, nämlich ein Video:
Aufgepasst!
Es wird hier in der Zukunft noch weitere Beiträge im Rahmen der Serie „Raspberry Pi als Helferchen“ geben. Also stay tuned.
Euer Patrick
Hallo, ich finde das super und möchte es für meine Tochter ( sie hat zwei Katzen) nachbauen. Wo gibt es denn den Futterspender/Müslispender.
Hi
Danke für coole Anleitung!
Ich versuche das Ding nachzubauen.
bei der Schleife kommt eine Meldung das feed nicht definiert ist. soweit ich das sehe fehlt das feed effektiv im Code.
Kann es sein das hier was fehlt in der Anleitung?
Vielen Dank & schöne Grüsse
Jürg
Unglaublich cooles Teil!
Du solltest das in Serie geben 😉