Früher oder später wird man auf einem RPi die GPIO-Pins für die Ansteuerung von externen Geräten nutzen wollen. Einige kleine Fallstricke warten hier (vor allem in Python). Üblich ist der Einsatz von RPi.GPIO unter Python respektive das sehr mächtige und komfortable WiringPi für C. Zusammen mit Kommandozeilentools wie gpio hat man (fast) alles was man brauchen wird.
Inhalt
Python auf dem RPi – Zahlen und Pins
Die grosse Verwirrung um die Pin-Bezeichnungen auf dem Raspberry pi klärt pinout.xyz auf:
Mit gpio readall kann man sich die aktuelle Pinkonfiguration (Input/Output) schön anzeigen lassen. Praktischerweise werden die Pins mit all ihren verschiedene Namen angezeigt.
Schalten mit Python auf dem RPi
Der folgende Code zeigt die Ansteuerung eines Pins (hier: für die Aktivierung einer Pumpe) in Python auf dem Pi-in-the-Sky. Dieser Code funktioniert auch, wenn alle PITS Platinen aktiv sind (also mit LoRa und APRS). Der Pin 13 ist die Internet LED Anzeige auf dem LoRa Board, die man getrost zweckentfremden kann (33 physical). Die Pinbelegung ist wie folgt:
#!/usr/bin/python import os import time import smbus import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) #Variable to enable/disable the pump pumpEnabled = True #Interval between measurements in seconds interval = 10 #Altitude at which the pump is activated in meters minPumpAlt = 20000 #Pin to control the pump / See https://pinout.xyz/# for further information pumpPin = 13 rev = GPIO.RPI_REVISION #Initialize GPIO-Pin for Pump GPIO.setup(pumpPin, GPIO.OUT, initial=GPIO.LOW) def loop(): global pumpEnabled while True: if(pumpEnabled == True): #Turns the pump on GPIO.output(pumpPin,GPIO.LOW) pumpEnabled = False print("LOW") else: #Turns the pump off GPIO.output(pumpPin,GPIO.HIGH) print("HIGH") pumpEnabled = True time.sleep(interval) loop()
This chanel is already in use
Man sollte beim Verlassen des Scripts mit dem Befel GPIO.cleanup() aufräumen, da es sonst bei einem zweiten Start zu Warnungen à la „This cannel is aready in use“ kommen kann. Im Script oben wird unsauber einfach die Warnung mit GPIO.setwarnings(False) deaktiviert. Am besten macht man dies über die Fehlerbehandlung von Python mit try-execpt-finally, da man den Grund für die Beendigung des Scripts ja nicht wissen kann, möglicherweise wird es manuell mit der Tastatur abgebrochen. Eine gute Diskussion dazu findet man zum Beispiel hier im RPi Forum oder im RPi TV RPI.GPIO Basiscs 3.
Interrupts
Ein RPi ist ein ausgewachsener Computer mit einem Betriebssystem. Programme mit genau definiertem Zeitverhalten müssten mit Interrupts erstellt werden; dies ist im Gegensatz zur Programmierung auf Mikrocontrollern auf einem RPi nicht wirklich in Reinkultur möglich. Zuviele Betriebssystem-Prozesse laufen da ständig untendurch. Diese schirmen die Hardware einerseits von der High-Level Programmierung ab, andererseits ist keine garantierte Reaktionszeit gegeben. Mit gewissen Einschränkungen geht es aber doch:
- Teil 3 von Interrupts mit GPIO (Raspi.TV ist generell eine informative Quelle für den RPi)
„We’ve been learning about interrupts this week because of the brand new interrupt capabilities of RPi.GPIO. We covered a simple “wait for” interrupt in part 1, threaded callback interrupt and button debouncing in part 2 and today we’re getting sophisticated with multiple threaded callbacks.“ - Tutorial: Interrupt-Driven Event-Counter on the Raspberry Pi (Smith College)
„The purpose of this tutorial is to illustrate how to implement a user-level interrupt in C on a Raspberry Pi to count events“
Eine andere Library ist pigpio, die hier (zusammen mit anderen) beschrieben ist: Sensor-Signal per Interrupt abfragen.