In diesem Tutorial geht es darum, wie man eine Raspberry Pi Kamera mittels eines Buttons auslösen kann. Dazu schließen wir einen Knopf an den GPIOs an und schreiben den entsprechenden Code via Python. Sobald das Bild erstellt wurde, können wir es weiterverarbeiten, z.B. indem wir mit OpenCV eine Farb- oder Gesichtserkennung darüber laufen lassen.
Zubehör
Im Prinzip kann jede USB-Kamera, die am Raspberry Pi erkannt wird, für dieses Tutorial genutzt werden. Die offizielle Raspberry Pi Kamera hat allerdings den Vorteil, dass man keinen USB Anschluss verwendet, sondern nur den CSI Anschluss, der speziell für das Kameramodul angebracht wurde.
Falls du das offizielle Kamera Modul nutzen willst, so gibt es dies in zwei Varianten. Mit und ohne Infrarot Filter. Mehr Informationen zu den Unterschieden findest du hier.
Dieses Zubehör habe ich für das Tutorial verwendet:
- Raspberry Pi (Modell egal, aber ein CSI oder USB Anschluss sollte vorhanden sein)
- Breadboard
- Widerstände (10kΩ)
- Jumper Kabel
- Taster / Druckschalter
Falls du diese Komponenten nicht einzeln erwerben willst, so empfiehlt sich ein Raspberry Pi Starterset. Diese Sind sowohl mit Raspberry Pi, als auch ohne verfügbar.
Raspberry Pi Kamera anschließen und GPIOs verbinden
Die offizielle Raspberry Pi Kamera lässt sich einfach über ein Flachbandkabel an den CSI Anschluss (Camera Serial Interface) anschließen. Die Kamera benötigt keine weitere Stromzufuhr und somit sind wir bereits fertig.
Um den Taster anzuschließen, bauen wir das folgende Schaubild nach. Der 10k Ohm Widerstand wird zwischen Masse (Ground) und dem GPIO 17 (Pin 11) gesetzt. Auf der anderen Seite des Tasters wird die 3.3V Spannung des Raspberry Pi’s angeschlossen (Pin 1):
Hier findest du noch eine gesamte Übersicht, aller GPIO Belegungen. Du kannst natürlich auch jeden anderen freien GPIO nutzen. Vergiss dann aber nicht, den Code entsprechend anzupassen.
Kamera-Software installieren und Python-Skript erstellen
Die Kamera ist standardmäßig deaktiviert und muss erst freigeschaltet werden. Gehe dazu in ein SSH Terminal und gib folgendes ein:
sudo raspi-config
Unter „Interfacing Options“ navigierst du zu „Camera“ und aktivierst diese. Danach kannst du aus dem Konfigurations-Assistenten raus, woraufhin der Raspberry Pi neugestartet werden muss.
Nach dem erfolgreichen Neustart geht es weiter, indem wir einen ersten Test machen. Wir nehmen ein Bild auf:
raspistill -o ~/img.jpg
Im Homeverzeichnis (/home/pi) befindet sich nun ein Bild mit dem Namen „img.jpg“. Du kannst dieses entweder direkt am Raspberry Pi ansehen, oder z.B. via Remotedesktopverbindung.
Hat das soweit geklappt, kommen wir zu unserem Skript. Hier möchten wir also bei jedem Tastendruck (GPIOs) ein Bild aufnehmen. Solltest du noch keine Erfahrung mit den GPIOs haben, ist dieses Tutorial hilfreich.
Python Skript zum Foto schießen per Knopfdruck
Zunächst erstellen wir eine neue Datei, in der wir unseren Python3 Code hinein schreiben. Anschließend führen wir diese aus.
sudo nano camera_button.py
Die Datei bekommt folgenden Inhalt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# -*- coding: utf-8 -*- from RPi import GPIO from datetime import datetime import os, time GPIOPin = 17 def button_callback(gpio_number): print("Button pressed!") datetime_string = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") filename = "/home/pi/img_%s.jpg" % datetime_string os.system("raspistill -o %s" % filename) GPIO.setmode(GPIO.BCM) GPIO.setup(GPIOPin, GPIO.IN, pull_up_down = GPIO.PUD_DOWN) GPIO.add_event_detect(GPIOPin, GPIO.RISING, callback=button_callback) try: while True: time.sleep(0.01) except: GPIO.cleanup() |
Speichere mit STRG+O und beende den Nano Editor mittels STRG+X.
Was haben wir hier nun getan?
- Zeile 1: Das Encoding ist wichtig, falls es mit Python2 ausgeführt wird, aber schadet nicht.
- Zeile 2-4: Wir importieren die Bibliotheken, die wir gleich nutzen werden.
- Zeile 7: Definition des GPIO Pins, an dem der Button angeschlossen ist (siehe Pin Belegung weiter oben).
- In Zeile 9-12 befindet sich die Funktion, die aufgerufen wird, sobald der Button gedrückt wird. Hier kann noch mehr Code stehen, der ausgeführt werden soll. Unter anderem setzen wir einen Dateinamen und führen das Tool raspistill aus, das wir vorher schon getestet haben.
- Zeile 15: Angabe, dass wir die GPIO Nummern statt Board Nummerierung nehmen wollen.
- In Zeile 16 definieren wir den GPIO als Input und setzen einen Pull-Down Widerstand. Das letztere wäre nicht zwingend nötig, da wir das bereits per Schaltung gebaut haben, ist aber auch nicht verkehrt.
- Zeile 17 gibt an, dass die Funktion aufgerufen wird, wenn sich der Status von 0 auf 1 („Rising“) verändert.
- Zeile 19-23: Endlose While Schleife, damit das Skript nicht sofort beendet wird.
Anschließend wollen wir dieses Skript ausführen:
sudo python3 camera_button.py
Wir drücken nun den Taster und sehen, wie eine neue Datei erstellt wird.
Voilà! Im Homeverzeichnis wurde nun eine neue Datei angelegt. Dies kannst du in der Konsole auch herausfinden:
ls /home/pi/
13 Kommentare
Zeile 1: Das Encoding ist wichtig, falls es mit Python2 ausgeführt wird, aber schadet nicht.
Meintest du nicht, Das Encoding ist NICHT wichtig?
Hallo,
erstmal: Ich bin absoluter Raspi-Neuling…., und jetzt zwei Fragen:
1. Board: Nachdem nichts gelötet werden muss, ist mir die Funktion des Boards bei diesem Projekt nicht ganz klar; es geht doch auch ohne, direkt, also: Taster Eins an Pin1, Taster zwei an Pin 11. Gut so?
Dann erübrigt sich, glaube ich, im Programm die Zeile 15?
2. Verstehe ich das richtig: Zwischen den Taster an Pin 11 und Pin 11 kommt ein Widerstand. Richtig?
3. Was muss ich ergänzen, wenn die Fotos der Reihe nach auf USB-Stick gespeichert werden sollen?
4. Gibt es was Ähnliches auch zum Drucken? Also: Tastendruck, und das Foto wird ausgedruckt?
Erstmal vielen, herzlichen Dank und: Bleib(t) gesund! Heinz
Hallo,
erstmal: Ich bin absoluter Raspi-Neuling…., und jetzt zwei (vier, sorry) Fragen:
1. Board: Nachdem nichts gelötet werden muss, ist mir die Funktion des Boards bei diesem Projekt nicht ganz klar; es geht doch auch ohne, direkt, also: Taster Eins an Pin1, Taster zwei an Pin 11. Gut so?
Dann erübrigt sich, glaube ich, im Programm die Zeile 15?
2. Verstehe ich das richtig: Zwischen den Taster an Pin 11 und Pin 11 kommt ein Widerstand. Richtig?
3. Was muss ich ergänzen, wenn die Fotos der Reihe nach auf USB-Stick gespeichert werden sollen?
4. Gibt es was Ähnliches auch zum Drucken? Also: Tastendruck, und das Foto wird ausgedruckt?
Erstmal vielen, herzlichen Dank und: Bleib(t) gesund! Heinz
Hallo Lieber Leser.
Wie kann ich am Programm verhindern , dass 2 Bilder entstehen und wie kann ich die Zeit der Aufnahme ändern?
Danke im voraus für die Antwort.
Mit Grüssen, Georg
Danach einfach ein längeres Sleep setzen. Welche Zeit der Aufnahme meinst du?
Hallo Felix .
zuerst Danke für deine Antwort.
Ich meine die Zeit , in dem das Bild , der Gegenstand, fokussiert wird und dann gespeichert wird.
Mit Gruss, Georg
Hallo Felix.
Ich habe in Sleep , die Zahl in Klammern geändert , aber nichts tut sich
Ich habe die Zeit in Zeile 13 geändet und -t 500 eingegeben , damit werden die beiden Bilder kürzer sichtbar bei der Aufnahme . Jetzt stört mich ,dass 2 Bilder aufgenommen werden. Wie muss das Programm dafür geändert werden??
Zwischen einem Tastendruck und dem Auslösen des Bildes vergehen teilweise bis zu 5 Sekunden – die Zeitspanne ist auch vorhanden, wenn man raspistill direkt aufruft. Kann man das so realisieren, das schnellst möglich ein Foto gemacht wird.
Gruß Udo
Hallo Zusammen,
ich habe eigentlich die gleichen Probleme wie meine Vorredner, zwei Bilder werden immer gemacht und es dauert auch immer ca.5sek. Etwas habe ich mit dem Code schon rumprobiert aber an den beiden Problemen hat sich nicht getan. Ich dachte wenn man bei raspistill den Parameter -t 0 schreibt
wird ohne Zeitverzögerung ein Bild gemacht, scheint hier irgendwie nicht ganz zu klappen. Ich bin dabei mir einen Scanner für Super 8 Filme zu bauen, die Hardware ist zu gut wie fertig. Jetzt wollte ich mal ein paar Bilder aufnehmen und versuchen wie ich das dann im Nachgang bearbeiten kann.
Leider klappt das mit dem Skript nicht so wie ich gehofft habe. Klang im ersten Moment echt einfach, bis dann die beiden etwas störenden Punkte auftauchten. Mit einem anderes kleines Skript was ich gefunden hatte kann man mittel Taster eine LED an und wieder ausschalten, das läuft ohne Probleme. Anfangs dachte ich das mein Taster stark prellt, aber nachdem ich hier lese das andere die gleichen Probleme haben, habe ich jetzt keine Idee mehr.
Hat ja jemand schon was dazu gefunden? Ist schwierig für einen der es nicht so mit Software hat was zu finden.
Ich habe das Skript umgeschrieben, dass ich damit auf Knopfdruck einen Screenprint, den ich mit scrot erstelle, ausdrucken lassen kann. Verwendung soll dies bei der Wiedergabe einer Webseite mit aktuellen Information ohne die Verwendung einer Tastatur finden.
Auch bei mir traten ständig Doppelauslösungen auf. Unabhängig davon, ob ich sleep(0.01) hatte oder auch sleep(5).
Daraufhin habe ich nach weiteren Informationen zu der GPIO.add_event_detect-Methode gegoogelt. Offensichtlich handelt es sich bei den Mehrfachauslösungen um ein Prellen des Tasters.
Neben der Verwendung hochwertigerer Taster wurde von der schaltungstechnischen Seite die Parallelschaltung eines Kondensators empfohlen.
Softwareseitig lässt sich eine Entprellung aber auch installieren. Man kann der Methode nämlich zusätzlich einen Parameter „bouncetime“ für den Zeitraum übergeben, in dem keine Wiederholung der Eingabe erfolgen soll.
Erweitert lautet die Zeile 17 daher bei meinem Skript nun:
GPIO.add_event_detect(GPIOPin, GPIO.RISING, callback=button_callback, bouncetime=200)
Hallo Felix,
danke erst mal für das Tutorial.
Du kommentierst zur Zeile 16, dass es dort eigentlich gar nicht notwendig wäre, die Pulldown-Option zu verwenden, da dies über die Schaltung schon erledigt sei.
Warum setzt du den Taster dann nicht gleich zwischen GPIO 17 und Power, und lässt den Widerstand und das Kabel zur Masse weg? Vor Allem für den Einbau in einem Gehäuse wäre das doch viel einfacher.
Und wenn das Programm nicht läuft, kann es doch völlig wurscht sein, welches Potential an dem Eingang anliegt.
Oder verstehe ich da etwas falsch?
hallo,
wie sieht das dann aus, wenn man 2 buttons verwendet, das mit dem ersten eine viedeoaufnahme für 10min startet und mit dem 2. button nur ein bild aufnimmt?
code-beispiel:
// programmstart
from picamera import PiCamera
from time import sleep
camera = PiCamera()
// wenn button 1 gedrückt wurde
camera.capture(‘/home/pi/Desktop/image.jpg’) #bzw
def button_callback(gpio_number):
print(„Button pressed!“)
datetime_string = datetime.now().strftime(„%Y-%m-%d_%H-%M-%S“)
filename = „/home/pi/img_%s.jpg“ % datetime_string
os.system(„raspistill -o %s“ % filename)
// hier die funktion, wenn button 2 betätigt wird
camera.start_preview()
camera.start_recording(‘/home/pi/Desktop/video.h264’)
sleep(600)
camera.stop_recording()
// programm beenden
camera.stop_preview()