Intelligente Hinderniserkennung

Für den Ultraschallsensor des Joy-Cars gibt es eine alternative Bauweise, die eine intelligente Hinderniserkennung ermöglicht. Dabei wird der Ultraschallsensor auf einem Servomotor montiert, der es dem Sensor erlaubt, sich nach links und rechts zu bewegen.

Diese Konstruktion erweitert die Funktionalität des Ultraschallsensors erheblich, da er nicht nur die Distanz direkt vor dem Joy-Car messen kann, sondern auch Hindernisse in einem breiteren Sichtfeld erfasst. Der Servomotor kann den Sensor in verschiedene Winkel drehen, wodurch eine Art "Radar-Scan" entsteht. Diese Methode verbessert die Navigation und Hindernisvermeidung des Joy-Cars und eignet sich besonders für Anwendungen, bei denen eine präzisere Umgebungswahrnehmung erforderlich ist.

Im folgenden Codebeispiel wird eine intelligente Hindernisvermeidung implementiert, bei der ein Servomotor und ein Ultraschallsensor zusammenarbeiten. Der Ultraschallsensor ist dabei an einem Servomotor montiert, der sich in verschiedene Richtungen bewegen kann. Dies ermöglicht es dem Sensor, Hindernisse in unterschiedlichen Winkeln zu detektieren, indem er regelmäßig Messungen ausführt.

Sobald der Ultraschallsensor ein Hindernis in einer bestimmten Richtung erkennt, wird die entsprechende Richtung auf der LED-Matrix des micro:bit visualisiert. Dies bietet eine intuitive Anzeige, die zeigt, aus welcher Richtung das Hindernis kommt. Die Bewegungen des Servomotors und die Messungen des Sensors werden synchron gesteuert, um eine effiziente Abdeckung des gesamten Bereichs zu gewährleisten.

Das Beispiel ist so programmiert, dass es Hindernisse im linken, rechten oder mittleren Bereich erkennt und diese Richtungen auf der LED-Matrix durch entsprechende Symbole oder Muster darstellt. Die Umsetzung umfasst die Steuerung des Servomotors, die Erfassung von Distanzmessungen und die Verarbeitung der Ergebnisse, um eine Echtzeitanzeige der Hindernisse zu ermöglichen.

Intelligente Hinderniserkennung

Diese Funktion gibt einen Wert wieder, welcher angibt, ob etwas erkannt wurde und auch aus welcher Richtung das Hindernis erkannt wurde.

 

Rückgabewert Richtung
0 nichts erkannt
1 links
2 vorne
3 rechts

Codebeispiel

let orientation = 0
JoyCar.initJoyCar(RevisionMainboard.OnepThree)
basic.forever(function () {
    orientation = JoyCar.collisionDetection()
    if (orientation == 1) {
        basic.showLeds(`
            . # . . .
            . # . . .
            . # . . .
            . # . . .
            . # # # .
            `)
    } else if (orientation == 2) {
        basic.showLeds(`
            # . . . #
            # # . # #
            # . # . #
            # . . . #
            # . . . #
            `)
    } else if (orientation == 3) {
        basic.showLeds(`
            . # # # .
            . # . # .
            . # # # .
            . # # . .
            . # . # .
            `)
    } else if (orientation == 0) {
        basic.showLeds(`
            . . . . .
            . . . . .
            . . . . .
            . . . . .
            . . . . .
            `)
    }
})

Intelligente Hinderniserkennung

Diese Funktion gibt einen Wert wieder, welcher angibt, ob etwas erkannt wurde und auch aus welcher Richtung das Hindernis erkannt wurde.

 

Rückgabewert Richtung
0 nichts erkannt
1 links
2 vorne
3 rechts

 

# Methode zur intelligenten Hinderniserkennung
# Variable für die Methode, um zu vergleichen, wann der Servo sich zuletzt bewegt hat
last_obstcl_act = running_time()
# Array mit möglichen Servo Positionen & Index
servo_pos = [0, 45, 90, 135, 180]
servo_pos_index = 0
def intelligent_detection():
    # um die globale Variable ändern zu können
    global last_obstcl_act, servo_pos_index
    # Garbage Collector aktivieren
    gc.collect()
    # Aktivierung/Deaktivierung des Servos nach 500 ms
    if running_time() - last_obstcl_act >= 500:
        # erhöhe Index
        servo_pos_index += 1
        # Falls Index die Länge des Arrays übersteigt, Index zurücksetzen
        if servo_pos_index == len(servo_pos):
            servo_pos_index = 0
        # Servo in Position bewegen
        servo(1,servo_pos[servo_pos_index])
        sleep(200)
        # Globale Variable auf aktuelle Laufzeit setzen
        last_obstcl_act = running_time()
    # Distanz mit Ultraschallsensor messen
    distance = get_distance()
    # Falls Distanz kleiner als 20 cm ist
    if distance < 20:
        # falls dies auf der rechten Seite passiert 3 zurückgeben
        if servo_pos_index == 0 or servo_pos_index == 1:
            return 3
        # falls dies in der Mitte passiert 2 zurückgeben
        elif servo_pos_index == 2:
            return 2
        # falls dies auf der linken Seite passiert 1 zurückgeben
        else:
            return 1
    # Falls nichts erkannt wird 0 zurückgeben
    else:
        return 0

Codebeispiel

# Notwendige Bibliotheken importieren
from microbit import *
import gc
from machine import time_pulse_us

# Definiere deine Joy Car Mainboard Revision
joycar_rev = 1.3

# Initialisierung der I2C-Schnittstelle für das Joy Car Mainboard
i2c.init(freq=400000, sda=pin20, scl=pin19)

# Pins für Servomotor einrichten
pin1.set_analog_period(10)
pin13.set_analog_period(10)

# Pins für Ultraschallsensor definieren
trigger = pin8
echo = pin12

# Initialisierung der Pins für den Ultraschallsensor
trigger.write_digital(0)
echo.read_digital()

# Methode zur Berechnung der Entfernung vom Ultraschallsensor
def get_distance():
    # Garbage Collector aktivieren
    gc.collect()
    # kurzen Impuls auf den Trigger-Pin setzen
    trigger.write_digital(1)
    trigger.write_digital(0)
    # Messung der Zeit, bis der Echo-Pin hoch wird
    duration = time_pulse_us(echo, 1)
    # Entfernung berechnen
    distance = ((duration / 1000000) * 34300) / 2
    # Rückgabe der Entfernung, gerundet auf 2 Dezimalstellen
    return round(distance, 2)

# Methode zur Positionsänderung bei Servomotoren
def servo(channel, position):
    # Methode zur Skalierung von 0-180 (°) auf 100-200 (us)
    def scale(num, in_min, in_max, out_min, out_max):
        # Rückgabe des auf eine ganze Zahl gerundeten Werts
        return (round((num - in_min) * (out_max - out_min) /
                (in_max - in_min) + out_min))
    # Prüfen, ob die Position im Bereich liegt
    if position < 0 and position > 180:
        return "position not in range"
    # Position an den ausgewählten Kanal senden
    if channel == 1:
        pin1.write_analog(scale(position, 0, 180, 100, 200))
    elif channel == 2:
        pin13.write_analog(scale(position, 0, 180, 100, 200))

# Methode zur intelligenten Hinderniserkennung
# Variable für die Methode, um zu vergleichen, wann der Servo sich zuletzt bewegt hat
last_obstcl_act = running_time()
# Array mit möglichen Servo Positionen & Index
servo_pos = [0, 45, 90, 135, 180]
servo_pos_index = 0
def intelligent_detection():
    # um die globale Variable ändern zu können
    global last_obstcl_act, servo_pos_index
    # Garbage Collector aktivieren
    gc.collect()
    # Aktivierung/Deaktivierung des Servos nach 500 ms
    if running_time() - last_obstcl_act >= 500:
        # erhöhe Index
        servo_pos_index += 1
        # Falls Index die Länge des Arrays übersteigt, Index zurücksetzen
        if servo_pos_index == len(servo_pos):
            servo_pos_index = 0
        # Servo in Position bewegen
        servo(1,servo_pos[servo_pos_index])
        sleep(200)
        # Globale Variable auf aktuelle Laufzeit setzen
        last_obstcl_act = running_time()
    # Distanz mit Ultraschallsensor messen
    distance = get_distance()
    # Falls Distanz kleiner als 20 cm ist
    if distance < 20:
        # falls dies auf der rechten Seite passiert 3 zurückgeben
        if servo_pos_index == 0 or servo_pos_index == 1:
            return 3
        # falls dies in der Mitte passiert 2 zurückgeben
        elif servo_pos_index == 2:
            return 2
        # falls dies auf der linken Seite passiert 1 zurückgeben
        else:
            return 1
    # Falls nichts erkannt wird 0 zurückgeben
    else:
        return 0


# Bilder definieren, die auf der LED-Matrix angezeigt werden sollen
left = Image("09000:"
              "09000:"
              "09000:"
              "09000:"
              "09990")
middle = Image("90009:"
             "99099:"
             "90909:"
             "90009:"
             "90009")
right = Image("09990:"
              "09090:"
              "09990:"
              "09900:"
              "09090")
none = Image("00000:"
              "00000:"
              "00000:"
              "00000:"
              "00000")

while True:
    # Intelligente Hinderniserkennung aufrufen und Rückgabewert speichern
    orientation = intelligent_detection()
    # wenn kein Hindernis erkannt wird
    if orientation == 0:
        display.show(none)
    # wenn links ein Hindernis erkannt wird
    elif orientation == 1:
        display.show(left)
    # wenn vorne ein Hindernis erkannt wird
    elif orientation == 2:
        display.show(middle)
    # wenn rechts ein Hindernis erkannt wird
    elif orientation == 3:
        display.show(right)
    sleep(500)