Nachdem die bisherigen Kapitel dieses Tutorials eher von allgemeiner Natur waren, wird es diesmal etwas Raspberry Pi spezifischer, in dem wir uns den GPIO Pins zu wenden.
Material
Folgendes Material benutze ich in diesem Beitrag
- Raspberry Pi 4 (theoretisch müsste es auch mit dem 3B klappen)
- eine rote Leuchtdiode
- Einen 330 Ohm Vorwiderstand (220 Ohm würden auch reichen, hab ich aber gerade keinen frei)
- Ein Breadboard
- einige Jumper Kabel weiblich-männlich (f-m)
- zwei Jumper-Kabel männlich-männlich (m-m)
- ein Taster zweipolig, quadratisch, steckbar
Falls du lieber eine LED in einer anderen Farbe benutzen möchtest, solltest du den Vorwiderstand mit einer anderen Ohmzahl wählen.
GPIO
Der GPIO Header beim Raspberry Pi 4B besteht aus zwei parallelen 20-poligen Stiftleisten. Die Belegung der Pins haben andere Hersteller von Single Board Computern inzwischen übernommen, so dass man von einem de facto Standard sprechen kann. Das Pinout ist in dieser Grafik dargestellt. Zur besseren Orientierung habe ich mir einen Stacking-Header mit Farbcodierung auf die GPIO Leiste gesteckt. Einige SBC Hersteller machen sowas von Werk aus, ich hoffe, die Raspberry Pi Foundation zieht mit denen gleich.

Uns interessiert in diesem Beispiel vor allem der GPIO Pin 23. Er ist durch nichts anderes belegt und eignet sich für die Ansteuerung einer Leuchtdiode. Ich benutze für diesen Kursteil den Raspberry Pi mit DietPiOS.
Vorbereitung
Zunächst müssen wir die notwendige Bibliothek für Python 3 installieren.
sudo apt install python3-rpi.gpio
Damit der User dietpi Zugriff auf die GPIO Header erhält, muss er in die Gruppe gpio eingetragen werden
sudo usermod -aG gpio dietpi
Wenn du dies mit dem User dietpi ausführst, musst du dich jetzt zunächst einmal aus- und dann wieder einloggen, damit die Modifikation wirksam wird.
Die Schaltung
Für unsere GPIO Versuche wollen wir eine rote LED zum Blinken bringen. Dazu verbinden wir die Kathode der LED über einen Vorwiderstand mit einem der Masse (GND) Pins des Raspberry Pi und die Anode mit dem Pin 23 der GPIO Header (der achte Pin vom äußersten +5V Pin aus gezählt.)

Widerstand
Ein Widerstand ist ein passives Bauelement, dass dafür sorgt, dass bei einer bestimmten Spannung die gewünschte Stromstärke fließt. Die Formel U = R * I auch bekannt als „Ohmsches Gesetz“ ist die bestimmt irgendwann mal zu Ohren gekommen. Der elektrische Widerstand wird in Ohm (Formelzeichen Ω) angegeben.
Damit die LED nicht durch zu viel Strom kaputt geht, schalten wir einen 330Ω Vorwiderstand (220Ω würden rechnerisch auch reichen, ich habe aber gerade 330er da). Die farbigen Ringe auf dem Widerstand geben den Widerstandswert an, orange=3, orange=3, schwarz=0, schwarz= Multiplikator *1, rot= Toleranz ±2%.

Leuchtdiode
Eine Diode ist ein Bauelement nur in einer Richtung passieren lässt. Deshalb ist es wichtig, auf die Polarität zu achten. Bei der Leuchtdiode (LED) ist ein Anschlusskontakt immer länger als der andere. Dies ist die Anode oder + Pol und muss mit dem GPIO Pin des Raspi verbunden werden. Demzufolge ist der kurze Kontakt der -Pol oder Kathode, die auf Masse gelegt wird (Merkregel: kurz ist die Kathode)

Taster
Ein Taster (engl. Button) lässt Strom nur durch, solange er gedrückt wird.Ich benutzen ihn, um das Auslesen von GPIO Pins zu demonstrieren. Ein Taster leitet den Strom nur solange du ihn drückst.

Hardware Zusammenbauen
Nach den Grundlagen geht es jetzt an den Zusammenbau unserer kleinen Schaltung.Mit dem schwarzen Jumperkabel verbindest du einen der GND-Pins (Ich benutze den Dritten von außen) mit der Masse-Schiene des Breadboards. Die LED steckst du mit beiden Kontakten irgendwo in zwei benachbarte Kontakte auf dem Breadboard, du musst dir nur merken, welches die Anode ist.Den einen Draht des Widerstands steckst du in einen weiteren Kontakt auf der Masse-Schiene, den anderen in einen Kontakt in derselben Spalte , in der die Kathode der LED steckt. Zu guter Letzt verbindest du mit einem roten (ich hatte nur orange da) Jumperkabel(m-f) den GPIO Pin 23 mit der Spalte, in der die Anode der LED steckt. Damit ist der Stromkreis geschlossen. Sollte im weiteren Verlauf etwas nicht klappen, dann ist die wahrscheinlichste Ursache, dass die Polarität der LED falsch angeschlossen ist.
Den Taster platzierst über zwei Kontaktreihen des Breadboards.Danach verbindest du mit einem Jumper-Kabel (m-m, schwarz)einen Kontakt des Tasters mit der Masse-schiene des Breadboards. Mit einem weiteren Jumper (f-m, grün) verbindest den anderen Tasterkontakt auf derselben Seite des „Grabens“ mit Pin 16 des Raspberry Pi.

GPIO ansteuern
Das klassische Programmbeispiel für diesen Versuchsaufbau ist es, die LED blinken zu lassen. Bei der Ansteuerung der Pins hilft uns das Package RPi.GPIO
. Sehen wir uns mal folgendes Programm an:
import RPi.GPIO as GPIO
from time import sleep
__PIN__ = 23 # GPIO Pin, den wir nutzen
__WAIT__ = 0.5 # Warten für 0,5 Sekunden
GPIO.setwarnings(False)
# benutze Broadcom Pin Nummerierung
GPIO.setmode(GPIO.BCM)
# Pin 23 als Output schalten.
GPIO.setup(__PIN__,GPIO.OUT)
#Zustand der LED setzen
def setLED(state):
GPIO.output(__PIN__,state)
# Dauerschleife, die die LED im Wechsel ein- und ausschaltet.
# Wird gestoppt mit CTRL-C
def blinkloop():
try:
while True:
# Pin auf HIGH setzen schaltet die LED ein
setLED(GPIO.HIGH)
print('LED ein')
sleep(__WAIT__)
# Pin auf LOW setzen schaltet die LED aus
setLED(GPIO.LOW)
print('LED aus')
sleep(__WAIT__)
except KeyboardInterrupt:
pass
finally:
# Zum schluss immer die LED ausschalten.
setLED(GPIO.LOW)
if __name__ =='__main__':
blinkloop()
GPIO.cleanup(__PIN__)
Dieses Programm schaltet die LED ständig ein und aus mit einer Wartezeit von 0,5 Sekunden dazwischen. Es läuft solange, bis es mit CTRL-C abgebrochen wird. Eine Zeile will ich noch genauer erklären.
GPIO.setmode(GPIO.BCM)
Die GPIO Pins haben unterschiedliche Nummerierungen. In der ersten werden die Pins konsekutiv hintereinander von 1 bis 40 hochgezählt. Die andere wird vom SoC vorgegeben. Wir schalten hier die Nummerierung des Broadcom-SoC ein.
LED-Server
Die LED blinken zu lassen, ist maximal für 2 Minuten spannend.Jetzt will ich dir zeigen, wie du die LED über eine Browser URL schalten kannst.
Im Kapitel Netzwerk hab ich die Socketserver nicht angesprochen, da ich sie hier besser platziert sehe. Socketserver sind in erster Linie dazu da, TCP-Services wie bspw. HTTP oder FTP zu bedienen. Diesen können wir relativ einfach mit einem RequestHandler
koppeln, um den übergebenen URL auszuwerten. Der RequestHandler
stellt Methoden zur Verfügung, die bei den verschiedenen HTTP-Request GET,POST, DELETE aufgerufen werden. Dort implementieren wir dann unseren Code.
#! /usr/bin/python3
from http.server import SimpleHTTPRequestHandler
import socketserver
import logging
from led import setLED
responsehtml = '<html><body> <h3>LED-Server</h3><p> LED ist $ledstate_str</p></body></html>'
logging.basicConfig( format='%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s', level=logging.DEBUG)
# Da http ein stateless Protokoll ist, wird der Handler bei jedem Request neu
# aufgebaut! Deswegen benutzen wir hier setup() statt __init__()
class LEDHttpRequestHandler(SimpleHTTPRequestHandler):
def setup(self):
logging.debug('setting up Handler')
self.ledstate = False
super().setup()
def do_GET(self):
logging.debug(f'path= {self.path}')
logging.debug('GET: empfangen')
self.send_response(200)
self.send_header('Content-Type:','text/html')
# Ende der Header markieren, dass ist wichtig, sonst kommt der Response nicht zurück!
self.end_headers()
#Wenn im Requestpath 'led='on'enthalten ist, schalten wir die LED ein. Bei off aus
if '?led=' in self.path:
if 'on' in self.path:
logging.debug('schalte LED ein')
self.ledstate = True
setLED(self.ledstate)
elif 'off' in self.path:
logging.debug('schalte LED aus')
self.ledstate = False
setLED(self.ledstate)
logging.debug(f'ledstate={self.ledstate}')
response = responsehtml.replace('$ledstate_str',('aus','an')[self.ledstate])
self.wfile.write(response.encode())
class http_server:
def __init__(self):
def handler(*args):
myHandler(*args)
server = HTTPServer(('', 8080), handler)
if __name__ == '__main__':
logging.debug('MAIN: start')
setLED(False) # Beim Start LED ausschalten
#Request-Handler aufbauen
handler = LEDHttpRequestHandler
handler.ledstate = False
#Socketserver mit unserem Handler starten
with socketserver.TCPServer(('',8080),handler) as httpd:
logging.info('SERVER: start')
try:
#Server läuft bis CTRL-C gedrückt wird.
httpd.serve_forever()
except KeyboardInterrupt:
pass
finally:
setLED(False)
GPIO auslesen
Zu guter Letzt wollen wir noch den Zustand des Tasters am Pin 16 auslesen. Wenn Strom durch den gedrückten Taster geleitet wird, geht Pin 16 auf HIGH
#! /usr/bin/python3
import RPi.GPIO as GPIO
from time import sleep
import logging
__PIN__ = 16 # GPIO Pin, für den Taster
__WAIT__ = 0.5 # Warten für 0,5 Sekunden
logging.basicConfig( format='%(asctime)-15s [%(levelname)s] %(funcName)s: %(message)s', level=logging.DEBUG)
if __name__ =='__main__':
GPIO.setwarnings(False)
# benutze Broadcom Pin Nummerierung
GPIO.setmode(GPIO.BCM)
logging.debug(f'konfiguriere Pin ${__PIN__} als Input.')
# Pin 16 als Input mit Pull-Up-Widerstand schalten.
GPIO.setup(__PIN__, GPIO.IN, pull_up_down=GPIO.PUD_UP)
pressed = False
logging.debug('Start der Schleife.')
try:
while True:
if not GPIO.input(__PIN__):
if not pressed:
logging.info('Button wurde gedrückt.')
pressed = True
else:
logging.debug('Button nicht gedrückt.')
pressed = False
sleep(__WAIT__)
except KeyboardInterrupt:
logging.debug('Abbruch durch Benutzer.')
finally:
pass

Mir hat die Arbeit an diesem Kapitel viel Spaß gemacht. Im nächsten Teil kümmern wir uns um das wichtige Thema Testing.