GPIO-Pins
Die großen "Bastelfunktionen" des Raspberry liegen sicher an den generischen IO-Pins. die als Eingang oder Ausgang missbraucht werden können. Allerdings sind nicht alle Ports "immer" frei, da sie teilweise mehrere Funktionen haben.
P1-Anschlussport
Auch wenn bis zu 17 GPIO-Pins bereit stehen, sind einige Pins "besonders", da sie für andere Funktionen nutzbar sind. Zudem sollten Sie genau hinschauen, da die Nummerierung der GPIO-Pins nicht mit der Nummerierung des P1-Anschlusses auf dem RaspBerryPI übereinstimmt. Ich habe mir folgende Ports ausgesucht.
GPIO | P1-Port (Revision 2) | Beschreibung |
---|---|---|
3,3 Volt |
01 |
Stromversorgung |
5 Volt |
02 |
Stromversorgung |
2 |
03 |
SDA, I2C-Bus mit internem 1k8 Pullup Wiederstand |
3 |
05 |
SCL, I2C-Bus mit internem 1k8 Pullup Wiederstand |
GND |
06 |
Masse (Ground) |
4 |
07 |
CPCLK, Teilweise als 1-Wire Port mit "w1-gpio" genutzt. |
7 |
26 |
SPI CE1 Verfügbar |
8 |
24 |
SPI CE0 Verfügbar |
9 |
21 |
SPI MISO Verfügbar |
10 |
19 |
SPI MOSI Verfügbar |
11 |
23 |
SPI SCLK Verfügbar |
14 |
08 |
Aktiv: RS232-Schnittstelle TxD |
15 |
10 |
Aktiv: RS232-Schnittstelle RxD |
17 |
11 |
Frei |
18 |
12 |
PCM Clock Audio |
22 |
15 |
Frei |
23 |
16 |
Frei |
24 |
18 |
Frei |
25 |
22 |
Frei |
27 |
13 |
Frei |
Nach einen Reset sind nur Port 14/15 als serieller Port aktiv und können zu GPIO-Ports umgeschaltet werden. Alle anderen Ports sind per Default in der Betriebsart GPIO. Wenn man sich aber keine andere Funktionen verbauen möchte, sollte erst einmal die freien GPIO-Ports verplanen:
Quelle:
http://elinux.org/Rpi_Low-level_peripherals#GPIO_hardware_hacking
Stand Aug 2013
Beachten Sie unbedingt, dass die Eingänge nicht "Safe" sind, sondern direkt die Beinchen des Prozessors sind und nicht mehr als 3,3V und auch nur bedingt Ströme vertragen. Alles über einer LED sollten Sie mit Transistoren oder Optokopplern o.ä. verstärken. Eingänge sollten zudem gegen zu viel Strom geschützt werden. Ein in Reihe geschalteter 1kOhm Widerstand hilft hier gegen Überlast. Aus dem 3,3V-Pin dürfen maximal 50mA gezogen werden, während aus dem 5V Pin (Rev-B) max. 300mA gezogen werden dürfen.
GPIO im Dateisystem
Unter Unix sind IOs fast immer über das Dateisystem möglich, z.B. viele Geräte sehen einfach wie ein Pfad oder eine Datei im Dateisystem aus. Selbst Systemdaten sind so einfach zu erreichen: Ein paar Beispiele
#Ausgabe der Ethernet Link
Geschwindigkeit
cat /sys/class/net/eth0/speed
#Ausgabe der Temperatur des bcm2835
cat /sys/class/thermal/thermal_zone0/temp
cat /sys/class/thermal/thermal_zone0/type
Durch einfaches Schreiben und Lesen in Verzeichnisse und Dateien können die GPIO-Pins angesteuert werden. für generischen GPIO-Pins ist das /sys/class/gpio/. Hier gibt es pro GPIO-Pin ein Verzeichnis mit Werten und Konfiguration, aber nur, wenn der Port auch "exportiert" ist.
# GPIO 24 (P1 Pin 18) auf Ausgang setzen und einschalten if test ! -d /sys/class/gpio/gpio24; then echo 24 > /sys/class/gpio/export; fi echo out > /sys/class/gpio/gpio24/direction echo 1 > /sys/class/gpio/gpio24/value if test ! -d /sys/class/gpio/gpio17; then echo 17 > /sys/class/gpio/export; fi echo in > /sys/class/gpio/gpio17/direction echo 1 > /sys/class/gpio/gpio17/value if test ! -d /sys/class/gpio/gpio17; then echo 17 > /sys/class/gpio/export; fi echo out > /sys/class/gpio/gpio17/direction echo 0 > /sys/class/gpio/gpio17/value echo 1 > /sys/class/gpio/gpio17/value echo 0 > /sys/class/gpio/unexport
Aktuell scheitern diese einfachen Ausgaben bei mir noch daran, dass ich keine Rechte habe und ein SuDO nicht hilft. Der wirkt nur auf den ECHO aber nicht auf die Umleitung auf eine Datei
Wer mag kann natürlich auch über eine X11 GuI diese Strukturen sehen
Das folgende WiringPi macht einiges einfacher und wenn damit die Ports exportiert werden, dann können sie ebenfalls im Dateisystem erreicht werden
wiringPI
Die Problematik mit SuDO und Root-rechten kann man recht einfach umgehen, wenn man die WiringPI-Library installiert. Dazu muss zuerst einmal GIT installiert werden, wenn noch nicht vorhanden um dann das Paket zu laden
# GIT Core Paket installieren sudo apt-get install git-core # wiringPI per HTTp aus dem Internet herunter laden git clone git://git.drogon.net/wiringPi # ggfls ein Update pruefen cd /home/pi/wiringPi/ git pull origin # cd wiringPi # kompilieren des Code ./build
Danach gibt es das Programm GPIO, welches direkt die Pins schalten kann.
Die Anwendung ist denkbar einfach. Zuerst wird definiert, welche Pins als Ausgang und welche als Eingang fungieren sollen. Passend auf mein Selbstbauboard Raspberry - IOBoard sind das:
$ gpio export 23 out $ gpio export 24 out $ gpio export 25 out $ gpio export 17 in $ gpio export 27 in
Und dann kann ich recht einfach die Ports setzen und wieder auslesen.
gpio write 23 1 pi@raspberrypi ~/wiringPi $ gpio write 23 0 pi@raspberrypi ~/wiringPi $ gpio write 24 1 pi@raspberrypi ~/wiringPi $ gpio write 24 0 pi@raspberrypi ~/wiringPi $ sudo shutdown -Ph now
Auch eine Information über das Board selbst und alle Ports ist recht einfach möglich
gpio readall
- Download and Install
https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/
Python und GPIO
Eine Programmiersprache des Raspberry ist Python, die als Skript als auch interaktiv ausgeführt werden kann. Die wichtige Dinge, die für Programmierer vielleicht ungewohnt sind:
- Case Sensible
PowerShell und VBScript beachten z.B.: nicht die Schreibweise von Variablen - Blockbildung durch Einrücken
Es gibt keine Klammerung wie bei PowerShell und C# oder "Begin/End"-Worte wie bei VBScript. Bei Python definiert die Einrückung einen Block. Sie ist also nicht nur "Kosmetik" sondern Basis - SuDO-Rechte
Wann immer man aber direkt auf Ports zugreifen will, muss das Skript als SuperUser laufen. - Interpreter und Shell
Python-Skripte können einfach wie PowerShell und VBScript gestartet werden. Python ist aber auch eine eigene LaufzeitUmgebung wie PowerShell, d.h. man kann interaktiv auch Code eingeben und ausführen lassen.
Also los in die ersten Versuche.
sudo phyton
# Python Sample fuer einfache IOs print("Starting Sample GPIO-Control für BerryClip compatible deviucs") import RPi.GPIO as GPIO import time print("GPIO.VERSION="+GPIO.VERSION) print("GPIO.VERSION="+str(GPIO.RPI_REVISION)) # use P1 header pin numbering convention GPIO.setmode(GPIO.BOARD) # Set up the GPIO channels für intport in (16,18,22): print("Setup Port " +str(intport)+" as output") GPIO.setup(intport, GPIO.OuT) print("Setup Port 11/13 as input") GPIO.setup(11, GPIO.IN) GPIO.setup(13, GPIO.IN) # Reading Input input_value11 = GPIO.input(11) input_value13 = GPIO.input(13) # Writing Output while True: für intport in (16,18,22): print("Port " +str(intport)+" High") time.sleep(0.1) GPIO.output(intport, GPIO.HIGH) für intport in (16,18,22): print("Port " +str(intport)+" Low") time.sleep(0.1) GPIO.output(intport, GPIO.LOW) while GPIO.input(11) == 1: print("Input 11 is 1 .pausing") while GPIO.input(13) == 0: print("Input 13 is 0 .blinking light 16") GPIO.output(intport, GPIO.HIGH) time.sleep(0.1) GPIO.output(intport, GPIO.LOW) time.sleep(0.1) # Cleanup end GPIO.cleanup()
Dies ist ein sehr einfacher Code um die Funktion zu demonstrieren aber gerade das Einlesen ist nicht ganz zuverlässig. Die GPIOs sind eingehend nämlich nicht entprellt. Ein Taster schließt oder öffnet einen Stromkreis nicht zwingend "binär", da Kontaktflächen nie eben sind und selbst zwischen Leiterbahnen Kapazitäten vorhanden sind. Mit dem Auge sind solche Preller nicht zu sehen aber eine CPU, die zigtausendfach pro Sekunde den Status einlesen kann, sieht so etwas schon. Solche ein Prellen kann man mit einem Schmitt-Trigger in Hardware lösen. Aber billiger ist eine Softwarelösung, die einfach einen Port mehrfach mit einer Pause dazwischen einliest und so das Ergebnis richtig macht. Hier mal zwei mögliche Ansätze
' Auf eine Änderung warten und quasi die erste Änderung in einem Zeitfenster nutzten count = 0 old_input = 0 while count < 10 : #take a reading input = GPIO.input(26) # trick to trigger on change and not on state if ((not old_input) and input): print("Button pressed") #update previous input old_input = input #slight pause to debounce time.sleep(0.05) if count >= 5: break ' Einfach z.B. 10 Messwerte in einer Zeit lesen und anhand des Mittelwerts entscheiden. input=0 für count in (1..10): input = input + GPIO.input(26) time.sleep(0.05) input = input + GPIO.input(26) time.sleep(0.05) input = input + GPIO.input(26) if (input > 2)
- http://code.google.com/p/raspberry-gpio-python/wiki/Basicusage
- Python für Programmers
http://wiki.python.org/moin/BeginnersGuide/Programmers - http://www.laub-home.de/wiki/Raspberry_Pi_Sensoren_auslesen
- http://www.laub-home.de/wiki/Raspberry_Pi
- Raspberry Pi Sensoren auslesen
http://www.laub-home.de/wiki/Raspberry_Pi_Sensoren_auslesen - Python Tools für Visual
Studio
http://pytools.codeplex.com/
GPIO Ports und Siri
Wer sagt denn, dass die Ports immer nur per Skript oder Webseite geschaltet werden müssen ?. Es gibt Leute die mittels SiriProxy auf dem RasPi auch per Sprache einen Port schalten und z.B. Garagen und Rolläden steuern.
SiriProxy ist ein Proxy, der auf dem iPhone unter SIRI eingetragen werden muss. Alle SIRI-Anfragen gehen dann zu diesem Proxy, der sie zu Apple weiter gibt und die Antworten wieder bekommt. Also Proxy kann er natürlich "reinschauen" und die Antworten auswerten und darauf reagieren.
Damit ist auch klar, dass ihr iPhone zwingend mit dem SiriProxy sprechen muss und das in der Regel nur "intern" geht. Ich ehe nicht davon aus, dass jemand wirklich einen intern installierte SiriProxy aus dem Internet mit einem DNS-Namen oder festen IP-Adresse erreichbar machen will. Eine Variante wäre noch ein VPN nach "Hause". Dennoch ist SiriProxy natürlich zumindest für Internet eine nette Spielerei und zeigt das Potential und die Machbarkeit auf.
Sobald sie aber den zweiten oder mehr RasPIs installieren wollen, klappt das aktuell natürlich nicht mehr, da auf dem IPhone ja nur ein SiriProxy eingetragen sein kann. Die Aufgabe besteht dann darin, die RasPi's miteinander zu verschalten, damit ein zentraler SiriProxy dann eben per LAN den anderen RasPi das Signal gibt.
- SiriProxy
https://GitHub.com/plamoni/SiriProxy - GitHub:elvisimprsntr
Entwickler rund um SiriProxy
https://GitHub.com/elvisimprsntr - Youtube User
http://www.youtube.com/User/TheElvisImprsntr
SiriProxy on Raspberry Pi
Home Automation Control
http://www.youtube.com/watch?v=PXmCiaRc9Xu
- Watch this guy use a
Raspberry Pi and Siri to control
his garage door, alarm,
thermostat, lights, and even TV
http://thenextweb.com/shareables/2013/02/06/watch-this-guy-use-a-raspberry-pi-and-siri-to-control-his-garage-door-alarm-thermostat-lights-and-even-tv/ - Open Your Garage Door with
Siri and a Raspberry Pi
http://lifehacker.com/5967715/open-your-garage-door-with-siri-and-a-raspberry-pi - Siri schaltet Funksteckdose
http://www.electronics-fun.de/siri-schaltet-funksteckdose/ - Home Automation mit dem
Raspberry Pi: 3. Software auf
dem Raspberry Pi -
GPIO-Ansteuerung und Webserver
http://www.xn--c-lmb.net/2012/12/home-automation-mit-dem-raspberry-pi-3.html
Interrupts
Auf die Dauer ist es natürlich müßig immer wieder die Ports abzufragen, wenn sich nicht tut. Interessanter ist es, wenn der RasPi selbst aktiv wird, wenn sich Pegel eines Eingangs ändert. Auch das geht, wobei das entsprechende Programm natürlich schon gestartet und aktiv bleiben muss. Aber es enthält eine Funktion, die durch den Interrupt außer der Reihe aufgerufen wird. Das eigentlich Hauptprogramm kann daher immer "schlafen".
Hier ein Beispiel, bei dem Port 17 und 27 mit einer eigenen Routine quasi gleichzeitig behandelt werden.
print "-- GPIO InterruptTest gestartet" print "-- Erforderliche Module einbinden" import RPi.GPIO as GPIO import time print "-- Variable definieren" count17 = 0 count27 = 0 print "-- SoC als Pinreferenz waehlen" GPIO.setmode(GPIO.BCM) print "-- Pin 17 vom SoC (P1:11-Anschluss) als Input deklarieren" GPIO.setup(17, GPIO.IN) print "-- Pin 27 vom SoC (P1:13-Anschluss) als Input deklarieren" GPIO.setup(27, GPIO.IN) # bei minimierter externer Beschaltung kann der interne Pull-Down Widerstand aktiviert werden. # GPIO.setup(17, GPIO.IN, pull_up_down = GPIO.PuD_DOWN) # GPIO.setup(27, GPIO.IN, pull_up_down = GPIO.PuD_DOWN) print "-- Interrupt Service Routine. Diese Funktion wird beim Interrupt aufgerufen" def isrcount17(channel): # Zugriff auf globale Variable global count17 count17 = count17 + 1 print "Add count17:" + str(count17) def isrcount27(channel): # Zugriff auf globale Variable global count27 count27 = count27 + 1 print "Add count27:" + str(count27) print "-- Interrupt Event anlegen Pin 17, auf steigende Flanke reagieren" GPIO.add_event_detect(17, GPIO.RISING, callback = isrcount17, bouncetime = 200) GPIO.add_event_detect(27, GPIO.RISING, callback = isrcount27, bouncetime = 200) # Endlosschleife print "-- Interrupttest gestartet. Stop with CTRL-C" try: while True: time.sleep(1) print "Ist count17:" + str(count17) + "Ist count27:" + str(count27) except KeyboardInterrupt: print "-- CTRL-C detected. exiting..." print "-- Events deregistrieren" GPIO.remove_event_detect(17) GPIO.remove_event_detect(27) print "-- GPIO InterruptTest beendet"
Der time.sleep hält nicht die CPU an, sondern nur das Programm, damit der CPU andere Dinge tun kann. Die 200ms "Bouncetime" verhindern einen erneuten Trigger innerhalb der Zeit. Sie können so maximal 5 Events pro Sekunden verarbeiten.
Selbst dann habe ich bemerkt, dass mancher Tastendruck trotzdem zwei Signale auslöst. Das kann aber durchaus an meinem selbstgebauten IOBoard liegen, obwohl ich sauber mit 10k Pulldown/Pullup) arbeite. Vielleicht sollte man doch noch einen 0,1yF-Kondensator an die Leitung klemmen.
Achtung: Auch wenn Sie das Python-Skript im Interpreter "beenden", sind die Interrupts und Serviceroutinen immer noch aktiv bis Sie diese entweder wie im Beispiel deaktivieren oder die Python-Shell beenden.
-
raspberry-gpio-python: Inputs
http://code.google.com/p/raspberry-gpio-python/wiki/Inputs - Raspberry Pi Interrupt
http://www.roboternetz.de/community/threads/61650-Raspberry-Pi-Interrupt -
Kampis Elektroecke - Interrupts
http://kampis-elektroecke.de/?page_id=3740
Weitere Links
Raspberry Pi GPIO - The
Easy Way
http://www.youtube.com/watch?v=0i2C3Qagosc
- RPi Low-level peripherals
http://elinux.org/Rpi_Low-level_peripherals#GPIO_hardware_hacking -
BCM2835 GPIO functions
http://elinux.org/RPi_BCM2835_GPIOs#GPIO0 - RaspberryPI
http://wiringpi.com/news/ - Cheat Sheet Basic GPIO
Access Setup
http://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/robot/cheat_sheet/ - Getting Started with
Raspberry Pi GPIO and Python
http://openmicros.org/index.php/articles/94-ciseco-product-documentation/raspberry-pi/217-getting-started-with-raspberry-pi-gpio-and-python - Raspberry PI: GPIO
http://www.rn-wissen.de/index.php/Raspberry_PI:_GPIO - http://elinux.org/i_Low-level_peripherals
-
GPIO Interfaces
https://www.kernel.org/doc/Documentation/gpio.txt -
GPIO schalten
http://kampis-elektroecke.de/?page_id=1659 -
Raspberry PI: GPIO
http://www.rn-wissen.de/index.php/Raspberry_PI:_GPIO -
GPIO-Pins schalten und auslesen
http://www.elektronx.de/tutorials/schalten-der-gpio-ein-und-ausgange/ -
FHEM: Raspberry
Pi: GPIOs schalten
http://www.fhemwiki.de/wiki/Raspberry_Pi:_GPIOs_schalten