.. include:: /index.rst
:start-after: start_hello_message
:end-before: end_hello_message
.. _py_fun_traffic_light:
4.9 Ampelsimulation
==============================
**Einführung**
Dieses Projekt demonstriert den Einsatz von LEDs und einer 4-stelligen 7-Segment-Anzeige, um ein reales Ampelsystem zu simulieren. Die LEDs repräsentieren die roten, gelben und grünen Länder, während die 7-Segment-Anzeige die verbleibende Zeit für jede Lichtphase herunterzählt. Es bietet eine anschauliche Möglichkeit, GPIO-Steuerung, Zeitabläufe und 7-Segment-Anzeigen in einem lehrreichen oder prototypischen Umfeld kennenzulernen.
----------------------------------------------
**Was Sie benötigen**
Für dieses Projekt werden die folgenden Komponenten benötigt:
.. list-table::
:widths: 30 20
:header-rows: 1
* - KOMPONENTENBESCHREIBUNG
- KAUFLINK
* - :ref:`cpn_breadboard`
- |link_breadboard_buy|
* - :ref:`cpn_wires`
- |link_wires_buy|
* - :ref:`cpn_resistor`
- |link_resistor_buy|
* - :ref:`cpn_led`
- |link_led_buy|
* - :ref:`cpn_4_digit`
- \-
* - :ref:`cpn_74hc595`
- |link_74hc595_buy|
* - :ref:`cpn_fusion_hat`
- \-
* - Raspberry Pi
- \-
----------------------------------------------
**Schaltplan**
Nachfolgend ist der schematische Schaltplan für das Projekt zur Ampelsimulation dargestellt:
.. image:: img/fzz/4.1.9_sch.png
:width: 90%
:align: center
----------------------------------------------
**Verdrahtungsdiagramm**
Verwenden Sie das Verdrahtungsdiagramm, um die Komponenten korrekt aufzubauen:
.. image:: img/fzz/4.1.9_bb.png
:width: 80%
:align: center
----------------------------------------------
**Beispiel ausführen**
Der gesamte in diesem Tutorial verwendete Beispielcode befindet sich im Verzeichnis ``ai-lab-kit``.
Führen Sie die folgenden Schritte aus, um das Beispiel auszuführen:
.. raw:: html
.. code-block:: shell
cd ~/ai-lab-kit/python/
sudo python3 4.9_TrafficLight.py
----------------------------------------------
**Code**
Hier ist das Python-Skript für die Ampelsimulation:
.. raw:: html
.. code-block:: python
#!/usr/bin/env python3
from fusion_hat.pin import Pin, Mode
import threading
# Setup GPIO pins for 74HC595 shift register
SDI = Pin(17,mode=Mode.OUT) # Serial Data Input
RCLK = Pin(4,mode=Mode.OUT) # Register Clock
SRCLK = Pin(27,mode=Mode.OUT) # Shift Register Clock
# Define GPIO pins for digit selection on the 7-segment display
placePin = [Pin(pin,mode=Mode.OUT) for pin in (23, 24, 25, 12)]
# Segment codes for numbers 0-9 on 7-segment display
number = (0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90)
# Setup GPIO pins for traffic light LEDs
ledPinR = Pin(5,mode=Mode.OUT) # Red LED
ledPinG = Pin(6,mode=Mode.OUT) # Green LED
ledPinY = Pin(13,mode=Mode.OUT) # Yellow LED
# Duration settings for traffic lights
greenLight = 30
yellowLight = 5
redLight = 60
# Traffic light color names
lightColor = ("Red", "Green", "Yellow")
# Initialize state variables
colorState = 0
counter = 60
timer1 = None
def setup():
""" Initialize the traffic light system and start the timer. """
global timer1
timer1 = threading.Timer(1.0, timer)
timer1.start()
def clearDisplay():
""" Clear the 7-segment display. """
for _ in range(8):
SDI.high()
SRCLK.high()
SRCLK.low()
RCLK.high()
RCLK.low()
def hc595_shift(data):
""" Shift data to the 74HC595 shift register for digit display. """
for i in range(8):
SDI.value(0x80 & (data << i))
SRCLK.high()
SRCLK.low()
RCLK.high()
RCLK.low()
def pickDigit(digit):
""" Select a specific digit to display on the 7-segment display. """
for pin in placePin:
pin.low()
placePin[digit].high()
def timer():
""" Handle the timing for traffic light changes. """
global counter, colorState, timer1
timer1 = threading.Timer(1.0, timer)
timer1.start()
counter -= 1
if counter == 0:
counter = [greenLight, yellowLight, redLight][colorState]
colorState = (colorState + 1) % 3
print(f"counter : {counter} color: {lightColor[colorState]}")
def lightup():
""" Update the traffic light LED based on the current state. """
global colorState
ledPinR.low()
ledPinG.low()
ledPinY.low()
[ledPinR, ledPinG, ledPinY][colorState].high()
def display():
""" Display the current counter value on the 7-segment display. """
global counter
for i in range(4):
digit = counter // (10 ** (3 - i)) % 10
if i == 0 and digit == 0:
continue
clearDisplay()
pickDigit(i)
hc595_shift(number[digit])
def loop():
""" Main loop to continuously update display and lights. """
while True:
display()
lightup()
def destroy():
""" Clean up resources when the script is terminated. """
global timer1
timer1.cancel()
ledPinR.low()
ledPinG.low()
ledPinY.low()
try:
setup()
loop()
except KeyboardInterrupt:
destroy()
----------------------------------------------
**Code verstehen**
1. **Initialisierung:**
* Richtet die GPIO-Pins für das Schieberegister, die 7-Segment-Anzeige und die LEDs der Ampel ein.
* Definiert Konstanten für die Dauer der einzelnen Lichtphasen und initialisiert Zustandsvariablen.
2. **Funktionen für die 7-Segment-Anzeige:**
* ``clearDisplay``: Löscht alle Segmente auf der Anzeige.
* ``hc595_shift``: Sendet Daten an das Schieberegister, um die Anzeigesegmente zu steuern.
* ``pickDigit``: Aktiviert eine bestimmte Ziffer für das Multiplexing.
3. **Timer-Funktion:**
* Verarbeitet den Countdown und steuert die Übergänge zwischen den einzelnen Ampelphasen.
4. **Ampelsteuerung:**
* Aktualisiert die LEDs entsprechend dem aktuellen Zustand der Ampel.
5. **Hauptschleife:**
* Aktualisiert kontinuierlich die Anzeige und die LEDs.
6. **Bereinigung (Cleanup):**
* Stellt sicher, dass alle Ressourcen beim Beenden des Programms ordnungsgemäß freigegeben werden.
----------------------------------------------
**Fehlerbehebung**
1. **Ampel-LEDs funktionieren nicht**:
- **Ursache**: Falsche Verdrahtung oder defekte LEDs.
- **Lösung**:
- Überprüfen Sie, ob die LEDs korrekt mit den GPIO-Pins 5 (Rot), 6 (Grün) und 13 (Gelb) verbunden sind.
- Testen Sie jede LED einzeln mit einem einfachen GPIO-Steuerskript.
2. **7-Segment-Anzeige zeigt keinen Countdown an**:
- **Ursache**: Fehlerhafte Verdrahtung oder falsche Konfiguration des Schieberegisters.
- **Lösung**:
- Stellen Sie sicher, dass die Pins ``SDI``, ``RCLK`` und ``SRCLK`` des Schieberegisters korrekt mit GPIO 17, 4 und 27 verbunden sind.
- Überprüfen Sie, ob die Ziffernauswahl-Pins mit der Konfiguration von ``placePin`` übereinstimmen.
3. **Countdown-Timer bleibt stehen**:
- **Ursache**: Der Timer-Thread wird nicht korrekt neu gestartet.
- **Lösung**: Stellen Sie sicher, dass die Funktion ``timer()`` den Aufruf ``timer1.start()`` enthält, um den Timer-Thread neu zu starten.
4. **Falsche Lichtdauer**:
- **Ursache**: Falsche Dauerwerte oder fehlerhafte Zustandswechsel.
- **Lösung**:
- Überprüfen Sie die Werte für ``redLight``, ``greenLight`` und ``yellowLight``.
- Kontrollieren Sie die Logik in der Funktion ``timer()``, um korrekte Zustandswechsel sicherzustellen.
----------------------------------------------
**Erweiterungsideen**
1. **Fußgängerüberweg**: Fügen Sie einen Fußgänger-Taster hinzu, der den Ampelzyklus kurz unterbricht, damit Fußgänger sicher die Straße überqueren können.
.. code-block:: python
from fusion_hat import Pin
pedestrian_button = Pin(22, Pin.IN, Pin.PULL_DOWN)
def handle_pedestrian():
global colorState, counter
if colorState == 1: # If Green Light
counter = 5 # Shorten green light duration
pedestrian_button.when_activated = handle_pedestrian
2. **Adaptive Zeitsteuerung**: Passen Sie die Dauer der Ampelphasen dynamisch an die aktuelle Verkehrsdichte an.
3. **Ereignisprotokollierung**: Speichern Sie Änderungen des Ampelzustands mit Zeitstempel in einer Datei zur späteren Analyse:
.. code-block:: python
with open("traffic_log.txt", "a") as log_file:
log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {lightColor[colorState]} light\n")
----------------------------------------------
**Fazit**
Dieses Projekt simuliert ein Ampelsystem und vermittelt praktische Erfahrungen mit GPIO-Steuerung, Schieberegistern und 7-Segment-Anzeigen. Es ist eine unterhaltsame und lehrreiche Möglichkeit, Elektronik und Programmierung zu erkunden und gleichzeitig eine reale Anwendung nachzubilden. Versuchen Sie, das System weiter auszubauen, um es noch interaktiver zu gestalten!