Code zoeken

Cursus Les 9 van 10: Obstakelvermijding met behulp van Raspberry Pi Pico 4WD Slimme Auto

Deze les maakt deel uit van: Raspberry Pi Pico 4WD Smart Car

Cursus Les 9 van 10: Obstakelvermijding met behulp van Raspberry Pi Pico 4WD Slimme Auto

Introductie

Deze handleiding, gebaseerd op Cursusles 9 van 10 van Robojax, laat zien hoe je een obstakelvermijdende robot bouwt met behulp van de SunFounder Raspberry Pi Pico 4WD Smart Car-kit. Het project combineert een servogestuurde ultrasone sensor met motorregeling om een robot te creëren die autonoom zijn omgeving kan verkennen. Door de sensor als een radar te laten draaien, detecteert de auto obstakels en kiest hij intelligent een vrije route om verder te gaan, waardoor dit een perfecte introductie is tot robotica, sensorintegratie en autonome navigatie.

Sunfounder_Pico4DW-09-Obstacle-avoidance-opstelling met obstakel op de vloer

Dit project is niet zomaar een speeltje; het is een basis voor veel praktische toepassingen. Hier zijn een paar ideeën om je te inspireren:

  • Autonome verkenningrobot: Bouw een robot die een kamer of buitengebied in kaart kan brengen en verkennen zonder menselijke tussenkomst.
  • Slimme stofzuiger: Gebruik dezelfde principes om een robot te creëren die door een kamer navigeert, meubels en muren vermijdt terwijl hij schoonmaakt.
  • Beveiligingspatrouillebot: Programmeer de auto om een perimeter te patrouilleren en gebruik de ultrasone sensor om onverwachte obstakels of indringers te detecteren en te melden.
  • Educatief platform voor AI: Gebruik dit project als opstapje om te leren over complexere algoritmen zoals padzoeken en gelijktijdige lokalisatie en kartering (SLAM).

Deze les richt zich op de kernlogica en code die de auto in staat stellen beslissingen te nemen. De auto gebruikt een servomotor om een ultrasone sensor te draaien, die als radar fungeert om afstanden van 0 tot 180 graden te meten. De code analyseert deze gegevens om het breedste vrije pad te vinden en stuurt de auto dienovereenkomstig vooruit, links of rechts. De video demonstreert het hele proces, van het testen van de afzonderlijke componenten tot het uitvoeren van het uiteindelijke obstakelvermijdingsalgoritme in een echt doolhof.

Hardware/componenten

Dit project is gebaseerd op de SunFounder Raspberry Pi Pico 4WD Smart Car-kit. De essentiële componenten die in deze les worden gebruikt, zijn:

  • Raspberry Pi Pico-microcontrollerbord
  • SunFounder 4WD Smart Car-chassis met vier motoren
  • Motordriverbord
  • Ultrasone afstandssensor (HC-SR04-type)
  • Servomotor (voor het draaien van de ultrasone sensor)
  • Voeding (batterijen voor de auto)

Bekabelingshandleiding

De SunFounder-kit is ontworpen voor eenvoudige montage en de bedrading is meestal vooraf aangesloten via een speciaal uitbreidingsbord. De ultrasone sensor is gemonteerd op de servomotor, die vervolgens wordt aangesloten op het hoofdregelbord. Deze opstelling maakt het mogelijk de sensor te draaien om de omgeving te scannen. Raadpleeg voor een gedetailleerd bedradingsschema specifiek voor jouw kit de officiële SunFounder-documentatie.

De kernverbindingen omvatten de trigger- en echopinnen van de ultrasone sensor en de signaalpin van de servomotor, die allemaal zijn verbonden met specifieke GPIO-pinnen op de Raspberry Pi Pico. De motordriver is ook verbonden met de Pico om de vier aandrijfmotoren te regelen. De video vermeldt dat de volledige documentatie, inclusief bedradingsschema's, beschikbaar is om te downloaden bij de kit.

Sunfounder_Pico4DW-09-Obstacle-avoidance_wanneer ultrasoon obstakel detecteert

Code-uitleg

Deze les richt zich op de logica binnen het `obstacle_avoid`-voorbeeld. De code is geschreven in MicroPython. Hoewel het volledige programma beschikbaar is om te downloaden, richten we ons op de belangrijkste, door de gebruiker configureerbare parameters die het gedrag van de auto bepalen. Deze staan meestal bovenaan het script.

Hier zijn de belangrijkste variabelen die je kunt aanpassen om de prestaties van je robot te verfijnen:


# Radar- en bewegingsparameters
radar_reference = 20  # Minimale afstand in cm die als veilig wordt beschouwd
step_angle = 10       # De hoektoename voor elke radarscanstap
forward_speed = 30    # Motorsnelheid voor vooruit rijden (0-100)
turn_speed = 50       # Motorsnelheid voor draaien (0-100)
forward_scan_angle = 50  # De hoek die de servo scant wanneer geen obstakel wordt gedetecteerd
  • radar_reference: Dit is de cruciale veiligheidsafstand in centimeters. Als een obstakel dichterbij dan deze waarde wordt gedetecteerd, beschouwt de auto dit als een "gevaar" en start hij een ontwijkingsmanoeuvre. In de video is dit ingesteld op 20 cm.
  • step_angle: Dit definieert de resolutie van de radarscan. Een kleinere waarde (bijv. 10 graden) betekent een gedetailleerdere scan, maar duurt langer. Een grotere waarde zou sneller zijn, maar kan smalle obstakels missen.
  • forward_speed & turn_speed: Deze regelen het vermogen dat naar de motoren wordt gestuurd. Je kunt ze aanpassen om de algehele snelheid en wendbaarheid van de auto te veranderen. De draaisnelheid wordt vaak hoger ingesteld om ervoor te zorgen dat de auto effectief kan draaien.
  • forward_scan_angle: Wanneer er geen direct gevaar vooruit is, verkleint de auto zijn scan naar deze hoek (gecentreerd op vooruit) om obstakels in zijn directe pad vaker te controleren, wat zorgt voor vloeiender vooruit rijden.

De video legt ook de belangrijkste beslissingslogica uit. Een functie `get_direction()` analyseert de lijst met afstandsmetingen (omgezet naar 1-en en 0-en voor veilig/onveilig) om het breedste continue pad van "1-en" te vinden. Op basis van waar dit breedste pad zich bevindt, retourneert de functie een richting: "vooruit", "links" of "rechts". De hoofdloop voert vervolgens de bijbehorende actie uit, draait de auto en scant opnieuw totdat het pad vooruit vrij is.

Live project/demonstratie

De video biedt een grondige demonstratie van het project. Het begint met het afzonderlijk testen van de ultrasone sensor om te laten zien hoe deze afstand meet en de waarden naar de shell print. De instructeur legt vervolgens het obstakelvermijdingsalgoritme uit met behulp van een stroomdiagram, waarbij het besluitvormingsproces voor het draaien naar links en rechts wordt gedetailleerd. Tot slot wordt de auto in een kleine doolhof geplaatst die is gemaakt van dozen om het volledige obstakelvermijdingsgedrag in actie te demonstreren. De auto navigeert succesvol door de doolhof, draait naar links en rechts om een vrij pad vooruit te vinden.

Video-hoofdstukken

  • [00:00] Inleiding tot obstakelvermijding
  • [01:31] Overzicht van de SunFounder Smart Car Kit en functies
  • [02:47] Hoe de obstakelvermijdingsfunctie werkt
  • [03:34] Testen van de ultrasone sensor
  • [07:45] Uitleg van het obstakelvermijdingsalgoritme en stroomdiagram
  • [12:49] Analyse van de belangrijkste obstakelvermijdingscode
  • [15:43] Live demonstratie van de obstakelvermijdingslogica
  • [22:53] Einddemonstratie met een doolhof van obstakels
  • [24:35] Conclusie en volgende stappen

Afbeeldingen

pico-4wd_main
pico-4wd_main
PICOBOARDWHITEANGLE2_1200x857
PICOBOARDWHITEANGLE2_1200x857
Sunfounder_Pico4DW-09-Obstacle-avoidance setup with obstacle on the floor
Sunfounder_Pico4DW-09-Obstacle-avoidance setup with obstacle on the floor
Sunfounder_Pico4DW-09-Obstacle-avoidance_when ultrasonic detects obstacle
Sunfounder_Pico4DW-09-Obstacle-avoidance_when ultrasonic detects obstacle
909-Lesson 9/10 Pi Pico 4WD card Python code: obstacle avoid
Taal: C++
# Lesson 9/10 Pi Car Pico 4WD: Obstacle avoid
# Download and resource page https://robojax.com/RJT631
import pico_4wd as car
import time

car.RADAR_REFERENCE = 20
car.RADAR_STEP_ANGLE = 10
MOTOR_FORWARD_POWER = 30
MOTOR_TURNING_POWER = 50

FORWARD_SCAN_ANGLE = 50

car.set_radar_scan_angle(FORWARD_SCAN_ANGLE)
status = "Danger"

def get_dir(radar_data):
    # get scan status of 0, 1
    # print(radar_data)
    radar_data = [str(i) for i in radar_data]
    radar_data = "".join(radar_data)
    # Split 0, leaves the free path
    paths = radar_data.split("0")
    # print(paths)
    # print("paths: %s" % paths)
    length_list = []
    # Calculate where is the widest
    for path in paths:
        length_list.append(len(path))
    if max(length_list) < 4:
        return "left"
    # Calculate the direction of the widest 
    i = length_list.index(max(length_list))
    pos = radar_data.index(paths[i])
    pos += (len(paths[i]) - 1) / 2
    delta = len(radar_data) / 3
    
    if pos < delta:
        return "left"
    elif pos > 2 * delta:
        return "right"
    else:
        return "forward"

def main():
    global status
    # General
    while True:
        radar_data = car.radar_scan()
        # print("radar_data: %s" % radar_data)
        # If radar data return a int, means scan not finished, and the int is current angle status
        if isinstance(radar_data, int):
            if radar_data == 0 and status != "Danger":
                print("Danger!")
                status = "Danger"
                car.move("stop")
                car.set_radar_scan_angle(180)
            continue
        else:
            status = "Save"
        
        direction = get_dir(radar_data)

        if direction == "left":
            print("turn left")
            distance = car.get_radar_distance_at(-FORWARD_SCAN_ANGLE/2)
            time.sleep(0.5)
            car.move("left", MOTOR_TURNING_POWER)
            while True:
                distance = car.get_radar_distance_at(-FORWARD_SCAN_ANGLE/2)
                status = car.get_radar_status(distance)
                if status == 1:
                    break
            car.move("stop")
            car.set_radar_scan_angle(FORWARD_SCAN_ANGLE)
        elif direction == "right":
            print("turn right")
            distance = car.get_radar_distance_at(FORWARD_SCAN_ANGLE/2)
            time.sleep(0.5)
            car.move("right", MOTOR_TURNING_POWER)
            while True:
                distance = car.get_radar_distance_at(FORWARD_SCAN_ANGLE/2)
                status = car.get_radar_status(distance)
                if status == 1:
                    break
            car.move("stop")
            car.set_radar_scan_angle(FORWARD_SCAN_ANGLE)
        else:
            print("forward")
            car.set_radar_scan_angle(FORWARD_SCAN_ANGLE)
            car.move("forward", MOTOR_FORWARD_POWER)

try:
    main()
finally:
    car.move("stop")
    car.set_light_off()

Dingen die je misschien nodig hebt

Hulpmiddelen en referenties

Nog geen middelen.

Bestanden📁

Raspberry Pi-code