Multitasking mit Raspberry Pi
Multitasking ist zu einem der wichtigsten Themen bei Mikrocontroller-Systemen geworden, nämlich bei Automatisierungsanwendungen. Mit zunehmender Komplexität der Projekte wird den Systemen mehr Funktionalität abverlangt. Solche Projekte umfassen den Einsatz mehrerer zusammenhängender Aufgaben, die auf demselben System laufen und sich die CPU (oder mehrere CPUs) teilen, um die erforderlichen Operationen zu implementieren. Aus diesem Grund hat die Bedeutung des Multitasking-Betriebs von auf Mikrocontrollern basierenden Anwendungen in den letzten Jahren stetig zugenommen. Viele komplexe Automatisierungsprojekte verwenden heutzutage irgendeine Form eines Multitasking-Kernels. In dem Buch wird die Programmiersprache Python 3 auf dem Raspberry Pi 4 verwendet, aber auch ältere Modelle des Raspberry Pi können ohne Änderung des Codes eingesetzt werden.
Das Buch ist in Projekte eingeteilt. Sein Hauptziel ist es, die grundlegenden Funktionen von Multitasking mit Python auf dem Raspberry Pi zu vermitteln. In dem Buch werden viele vollständig getestete Projekte vorgestellt, in denen das Multitasking-Modul von Python verwendet wird. Jedes Projekt wird ausführlich beschrieben und diskutiert und jedes Projekt ist mit vollständigen Programmlistings versehen. Die Leser sollten in der Lage sein, die Projekte so zu verwenden, wie sie sind, oder sie so zu modifizieren, dass sie ihren eigenen Bedürfnissen entsprechen.
Beispiel Ampelsteuerung
In diesem Projekt wird eine einfache Ampelsteuerung für die Kreuzung der East Street mit der North Street entworfen. Es gibt Ampeln an jeder Ecke der Kreuzung. In der Nähe der Ampeln auf der North Street befinden sich Zebrastreifen und beidseitig der Straße Tasten für Fußgänger. Durch Drücken eines Tasters werden alle Ampeln am Ende ihres Zyklus auf Rot geschaltet und verbleiben für eine Zeit in diesem Zustand. Zudem ertönt ein Summer, der akustisch anzeigt, dass die Fußgänger die Straße sicher überqueren können. Außerdem ist eine LC-Anzeige an das System angeschlossen, dauf der angegeben wird, ob die Kreuzung momentan für Fußgänger oder für den Autoverkehr freigegeben ist. Bild 1 zeigt die Anordnung der „Hardware“ an der Kreuzung.
In diesem Projekt sind für jeden Ampelzyklus und auch für die Dauer der Fußgänger-Freigabe die folgenden festen Zeiten angegeben. Der Einfachheit halber wird angenommen, dass die Ampeln beider Straßen der Kreuzung die gleichen Intervalle aufweisen:
Zeit für Fußgänger: 10 Sekunden
Rot: 19 Sekunden
Rot+Gelb: 2 Sekunden
Grün: 15 Sekunden
Gelb: 2 Sekunden
Die Gesamtzykluszeit der Ampeln in diesem Beispielprojekt ist also auf 38 Sekunden plus 10 Sekunden, wenn die Fußgängertaste gedrückt wurde, eingestellt.
Die Abfolge der einzelnen Ampelphasen ist wie gewohnt: Rot...Rot+Gelb...Grün...Gelb...Rot. Bild 2 zeigt das Blockdiagramm des Projekts, Bild 3 den Schaltplan.
In diesem Projekt werden rote (R), gelbe (A) und grüne (G) LEDs verwendet, um die realen Ampeln darzustellen. Die folgenden Verbindungen werden zwischen dem Raspberry Pi und der Ampelanlage gelegt:
Zu Beginn des Programms traffic.py in Listing 1 (Download siehe unten) werden die Module mit den Namen RPi, time, I2C LCD driver und multiprocessing in das Programm importiert und zwei Queues mit den Namen pedq und lcdq erstellt.
#--------------------------------------------------------------------
# TRAFFIC LIGHTS CONTROLLER
# =========================
#
# This is a traffic lights controller project controlling lights
# at a junction. 6 LEDS are used to represent the traffic lights.
# Additionally a button is used for pedestrian crossing, and an
# LCD shows the state of the traffic lights at any time
#
# Author: Dogan Ibrahim
# File : traffic.py
# Date : May 2020
#----------------------------------------------------------------------
import RPi.GPIO as GPIO # Import RPi
import multiprocessing # Import multiprocessing
import time # Import time
import RPi_I2C_driver # I2C library
LCD = RPi_I2C_driver.lcd() # Import LCD
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM) # GPIO mode BCM
pedq = multiprocessing.Queue() # Create queue
lcdq = multiprocessing.Queue() # Create queue
#
# This function sends data 'state (0 or 1)' to specified port
#
def ONOF(port, state):
GPIO.output(port, state)
#
# This function configures the specified port as output
#
def CONF_OUT(port):
GPIO.setup(port, GPIO.OUT)
#
# Process to control the lights
#
def Lights(): # Process Lights
R1=21; A1=20; G1=16 # LED connections
R2=12; A2=7; G2=8 # LED conenctions
Buzzer=25 # Buzzer connection
CONF_OUT(R1); CONF_OUT(A1); CONF_OUT(G1) # Configure
CONF_OUT(R2); CONF_OUT(A2); CONF_OUT(G2) # Configure
CONF_OUT(Buzzer) # Configure
ONOF(R1,0); ONOF(A1,0); ONOF(G1,0); ONOF(R2,0); ONOF(A2,0); ONOF(G2,0)
ONOF(Buzzer, 0)
RedDuration = 15
GreenDuration = 15
AmberDuration = 2
#
# Control the traffic light sequence
#
while True: # Do forever
ONOF(R1,0); ONOF(A1,0); ONOF(G1,1); ONOF(R2,1); ONOF(A2,0); ONOF(G2,0)
time.sleep(RedDuration)
ONOF(G1,0); ONOF(A1,1)
time.sleep(AmberDuration)
ONOF(A1,0); ONOF(R1,1); ONOF(A2,1)
time.sleep(AmberDuration)
ONOF(A2,0); ONOF(R2,0); ONOF(G2,1)
time.sleep(GreenDuration)
ONOF(G2,0); ONOF(A2,1)
time.sleep(AmberDuration)
ONOF(A2,0); ONOF(A1,1); ONOF(R2,1)
time.sleep(AmberDuration)
while not pedq.empty(): # If ped request
lcdq.put(1)
ONOF(G1,0); ONOF(R1,1); ONOF(A1,0) # Only RED ON
ONOF(G2,0); ONOF(R2,1); ONOF(A2,0) # Only RED ON
d = pedq.get() # Clear ledq
ONOF(Buzzer, 1) # Buzzer ON
time.sleep(10) # Wait 10 secs
ONOF(Buzzer, 0) # Buzzer OFF
d = lcdq.get() # Clear lcdq
def Pedestrian(): # Process Pedestrian
PB1 = 24
GPIO.setup(PB1, GPIO.IN) # PB1 is input
while True: # Do forever
while GPIO.input(PB1) == 1: # PB1 not pressed
pass
pedq.put(1) # Send to Ped queue
while GPIO.input(PB1) == 0: # PB1 not released
pass
#
# Create the processes
#
p = multiprocessing.Process(target = Lights, args = ())
q = multiprocessing.Process(target = Pedestrian, args = ())
p.start()
q.start()
#
# LCD Display control. Display 'Ped Cycle' or 'Traffic Cycle'
#
LCD.lcd_clear() # Clear LCD
LCD.lcd_display_string("TRAFFIC CONTROL", 1) # Heading
while True: # DO forever
if not lcdq.empty():
LCD.lcd_display_string("Ped Cycle ", 2)
else:
LCD.lcd_display_string("Traffic Cycle", 2)
time.sleep(1)
Im Programm werden zwei Funktionen mit den Namen ONOF und CONF_OUT definiert. Die Funktion ONOF hat zwei Argumente: port und state. Diese Funktion sendet den Status (0 oder 1) an den angegebenen GPIO-Port. Die Funktion CONF_OUT besitzt einen Parameter namens port. Diese Funktion konfiguriert den angegebenen GPIO-Port als Ausgang.
Es gibt zwei Prozesse im Programm: Lights und Pedestrian. Zu Beginn des Lights-Prozesses werden die Verbindungen zwischen dem Raspberry Pi und den Ampel-LEDs sowie dem Summer definiert und diese Ports als Ausgänge konfiguriert. Zusätzlich werden all diese Portausgänge auf „0“ gesetzt, so dass alle LEDs und der Summer ausgeschaltet (OFF) sind. Außerdem werden die LEDs in der richtigen Reihenfolge und mit dem richtigen Timing festgelegt. Am Ende der Funktion wird geprüft, ob die Fußgängertaste gedrückt wurde, was der Fall ist, wenn der Queue pedq nicht leer ist. Während des Fussgängerzyklus werden alle Ampeln auf Rot geschaltet, um den Autoverkehr zu stoppen und den Fussgängern eine ungefährliche Überquerung der Straßen zu ermöglichen.
Außerdem wird während des Fussgängerzyklus der Summer für 10 Sekunden aktiviert, um die Fussgänger darüber zu informieren, dass es jetzt sicher ist, die Straße zu überqueren.
Der Fussgängerprozess überwacht kontinuierlich die Taste an PB1. Wenn sie gedrückt wird, wird eine „1“ an den Queue pedq gesendet, so dass der Prozess Lights diese Aktion leicht erkennen und den Fussgängerzyklus starten kann.
Das Hauptprogramm steuert das LCD. Wenn das Programm gestartet wird, wird die Meldung „TRAFFIC CONTROL“ in der ersten Zeile des LCDs angezeigt. In der zweiten Zeile erscheint, wie in Bild 4 zu sehen, der Zustand des Queues lcdq in Form der Meldungen „Ped Cycle“ beziehungsweise „Traffic Cycle“.
(200381-01)
----------------------------------------------------------------------------------------------------------------------
Wollen Sie weitere Elektor-Artikel lesen? Jetzt Elektor-Mitglied werden und nichts verpassen!
----------------------------------------------------------------------------------------------------------------------