Code Struktur
Bisher haben wir unseren gesamten Code in der main.py geschrieben. Und die Bibliotheken für die Sensoren lagen im gleichen Ordner.
Das funktioniert für kleine Projekte gut, aber wenn der Code wächst, wird es schnell unübersichtlich.
In diesem Kapitel schauen wir uns an, wie wir unseren Code sinnvoll auf mehrere Dateien und Ordner aufteilen können.
Warum Struktur wichtig ist
Abschnitt betitelt „Warum Struktur wichtig ist“Stellen Sie sich vor, Sie suchen einen Fehler in Ihrem Code. Wenn alle 300 Zeilen in einer einzigen main.py stecken, ist das wie die Suche nach einer Nadel im Heuhaufen.
Gute Code-Struktur bringt folgende Vorteile:
- Übersichtlichkeit – Sie finden sofort, was Sie suchen.
- Wiederverwendbarkeit – Einzelne Module können in anderen Projekten genutzt werden.
- Teamarbeit – Mehrere Personen können gleichzeitig an unterschiedlichen Modulen arbeiten.
- Testbarkeit – Einzelne Teile lassen sich gezielt testen.
Empfohlene Verzeichnisstruktur
Abschnitt betitelt „Empfohlene Verzeichnisstruktur“Für ein Micromouse-Projekt empfehlen wir folgende Aufteilung:
micromouse/│├── main.py # Einstiegspunkt – startet das Programm├── controller.py # State Machine & Hauptschleife├── config.py # Zentrale Konfiguration (Pins, Konstanten)│├── lib/ # Drittanbieter-Treiber (unverändert übernommen)│ ├── hcsr04.py│ └── mpu6050.py│└── components/ # Eigene Logikklassen ├── motor.py # DCMotor – Motoransteuerung └── sensor.py # UltrasonicSensor, IMUSensor, ...Die Idee dahinter ist eine klare Trennung in drei Ebenen:
| Ebene | Ordner | Inhalt |
|---|---|---|
| Steuerung | / (root) | main.py, controller.py, config.py |
| Eigene Logik | components/ | Ihre eigenen Klassen für Motoren und Sensoren |
| Fremde Treiber | lib/ | Unveränderte Bibliotheken von Drittanbietern |
Was kommt wohin?
Abschnitt betitelt „Was kommt wohin?“main.py – Der Startpunkt
Abschnitt betitelt „main.py – Der Startpunkt“Die main.py ist die erste Datei, die nach dem Booten ausgeführt wird. Sie sollte so kurz wie möglich sein und nur das Nötigste tun:
- Den Controller importieren
- Eine Instanz erstellen
- Den Controller starten
from controller import Controller
robot = Controller()robot.run()Mehr gehört hier nicht rein. Die eigentliche Logik liegt in controller.py.
config.py – Die Konfiguration
Abschnitt betitelt „config.py – Die Konfiguration“Alle Pin-Nummern, Schwellwerte und Konstanten gehören in eine zentrale Konfigurationsdatei. So müssen Sie bei einer Änderung der Verkabelung nur eine Datei anpassen.
# --- Motor Pins (IN1, IN2) ---LEFT_MOTOR_PINS = (5, 18)RIGHT_MOTOR_PINS = (19, 21)
# --- Sensor Pins (TRIGGER, ECHO) ---FRONT_SENSOR_PINS = (26, 25)
# --- Schwellwerte ---WALL_DISTANCE_CM = 15 # Ab wann gilt eine Wand als vorhanden?BASE_SPEED = 40000 # Standard-Fahrgeschwindigkeit (0–65535)controller.py – State Machine & Steuerzentrale
Abschnitt betitelt „controller.py – State Machine & Steuerzentrale“Der Controller ist das Herzstück Ihres Roboters. Er kennt alle Komponenten und koordiniert ihr Zusammenspiel.
Die Hauptschleife fragt in jedem Durchlauf den aktuellen Zustand ab und entscheidet, was als nächstes passiert – das nennt man eine State Machine.
from components.motor import DCMotorfrom components.sensor import UltrasonicSensorfrom config import LEFT_MOTOR_PINS, RIGHT_MOTOR_PINS, FRONT_SENSOR_PINS
class Controller: def __init__(self): self.left_motor = DCMotor(*LEFT_MOTOR_PINS) self.right_motor = DCMotor(*RIGHT_MOTOR_PINS) self.sensor = UltrasonicSensor(*FRONT_SENSOR_PINS)
def run(self): while True: self._update()
def _update(self): pass # Hier kommt die State Machine hincomponents/motor.py – Die Motorsteuerung
Abschnitt betitelt „components/motor.py – Die Motorsteuerung“Die DCMotor-Klasse für diese Datei haben Sie bereits im Kapitel Motoren ansteuern kennengelernt. Legen Sie sie einfach als components/motor.py auf Ihrem Gerät ab.
components/sensor.py – Die Sensorik
Abschnitt betitelt „components/sensor.py – Die Sensorik“Alle eigenen Sensorklassen kommen in diese Datei. Sie importieren die rohen Treiber aus lib/ und fügen darüber eine saubere, einheitliche Schnittstelle hinzu – z.B. Fehlerbehandlung oder Einheitenumrechnung.
from lib.hcsr04 import HCSR04from lib.mpu6050 import MPU6050
class UltrasonicSensor: def __init__(self, trigger_pin, echo_pin): self._sensor = HCSR04(trigger_pin=trigger_pin, echo_pin=echo_pin)
def distance_cm(self): try: return self._sensor.distance_cm() except OSError: return 999 # Kein Echo empfangen → Hindernis außer Reichweite
class IMUSensor: def __init__(self, i2c): self._imu = MPU6050(i2c)
def heading(self): """Gibt die aktuelle Ausrichtung in Grad zurück.""" return self._imu.heading()lib/ – Drittanbieter-Treiber
Abschnitt betitelt „lib/ – Drittanbieter-Treiber“In diesem Ordner landen alle Bibliotheken, die Sie von außen übernehmen – zum Beispiel hcsr04.py oder mpu6050.py. Sie werden unverändert auf das Gerät kopiert und von den Klassen in components/ genutzt.
lib/├── hcsr04.py # Treiber für den Ultraschallsensor HC-SR04└── mpu6050.py # Treiber für das Gyroskop/Beschleunigungssensor MPU-6050Zusammenfassung
Abschnitt betitelt „Zusammenfassung“| Datei / Ordner | Zuständigkeit |
|---|---|
main.py | Einstiegspunkt, startet den Controller |
controller.py | State Machine, Hauptschleife, koordiniert alle Komponenten |
config.py | Pins, Konstanten, Schwellwerte |
components/motor.py | DCMotor – Geschwindigkeit und Richtung |
components/sensor.py | Eigene Sensorklassen mit sauberer Schnittstelle |
lib/ | Unveränderte Drittanbieter-Treiber |
- Ich habe verstanden, dass diese Struktur eine Hilfe sein soll und nicht zwingend so umgesetzt werden muss.