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.

Bild 1. Anordnung der Ampeln 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.

Bild 2. Blockdiagramm des Projekts.
Bild 3. Schaltplan des Projekts. 

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.

Listing 1. Das Programm traffic.py  

#--------------------------------------------------------------------
#                     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“.

Bild 4. Beispiel für die Anzeige auf dem LCD.

(200381-01)

 

----------------------------------------------------------------------------------------------------------------------

Wollen Sie weitere Elektor-Artikel lesen? Jetzt Elektor-Mitglied werden und nichts verpassen!

----------------------------------------------------------------------------------------------------------------------