Szukaj kodu

Kurs Lekcja 9 z 10: Unikanie przeszkód za pomocą inteligentnego samochodu 4WD Raspberry Pi Pico

Ta lekcja jest częścią: Raspberry Pi Pico 4WD Smart Car

Kurs Lekcja 9 z 10: Unikanie przeszkód za pomocą inteligentnego samochodu 4WD Raspberry Pi Pico

Wprowadzenie

Ten przewodnik, oparty na lekcji 9 z 10 kursu Robojax, pokazuje, jak zbudować robota omijającego przeszkody przy użyciu zestawu SunFounder Raspberry Pi Pico 4WD Smart Car. Projekt łączy serwomechanizm z czujnikiem ultradźwiękowym oraz sterowanie silnikami, tworząc robota, który potrafi autonomicznie poruszać się w swoim otoczeniu. Poprzez skanowanie otoczenia czujnikiem jak radar, samochód wykrywa przeszkody i inteligentnie wybiera wolną drogę, co stanowi doskonałe wprowadzenie do robotyki, integracji czujników i nawigacji autonomicznej.

Konfiguracja Sunfounder_Pico4DW-09-Obstacle-avoidance z przeszkodą na podłodze

Ten projekt to nie tylko zabawka; to fundament dla wielu praktycznych zastosowań. Oto kilka pomysłów, które mogą Cię zainspirować:

  • Autonomiczny robot eksploracyjny: Zbuduj robota, który potrafi mapować i eksplorować pomieszczenie lub obszar na zewnątrz bez ingerencji człowieka.
  • Inteligentny odkurzacz: Wykorzystaj te same zasady, aby stworzyć robota, który porusza się po pomieszczeniu, omijając meble i ściany podczas sprzątania.
  • Robot patrolujący: Zaprogramuj samochód do patrolowania obwodu i użyj czujnika ultradźwiękowego do wykrywania i zgłaszania nieoczekiwanych przeszkód lub intruzów.
  • Platforma edukacyjna dla AI: Wykorzystaj ten projekt jako krok do nauki bardziej złożonych algorytmów, takich jak znajdowanie ścieżki oraz jednoczesna lokalizacja i mapowanie (SLAM).

Ta lekcja skupia się na podstawowej logice i kodzie, które umożliwiają samochodowi podejmowanie decyzji. Samochód używa serwomechanizmu do obracania czujnika ultradźwiękowego, działającego jak radar, mierzącego odległości od 0 do 180 stopni. Kod analizuje te dane, aby znaleźć najszerszą wolną ścieżkę i kieruje samochodem do przodu, w lewo lub w prawo. Film demonstruje cały proces, od testowania poszczególnych komponentów po uruchomienie finalnego algorytmu omijania przeszkód w rzeczywistym labiryncie.

Sprzęt/Komponenty

Ten projekt opiera się na zestawie SunFounder Raspberry Pi Pico 4WD Smart Car. Niezbędne komponenty użyte w tej lekcji to:

  • Płytka mikrokontrolera Raspberry Pi Pico
  • Podwozie SunFounder 4WD Smart Car z czterema silnikami
  • Płytka sterownika silników
  • Czujnik odległości ultradźwiękowej (typ HC-SR04)
  • Serwomechanizm (do obracania czujnika ultradźwiękowego)
  • Zasilanie (baterie do samochodu)

Schemat połączeń

Zestaw SunFounder jest zaprojektowany z myślą o łatwym montażu, a połączenia są zazwyczaj wstępnie podłączone przez dedykowaną płytkę rozszerzeń. Czujnik ultradźwiękowy jest zamontowany na serwomechanizmie, który jest następnie podłączony do głównej płytki sterującej. Taka konfiguracja pozwala na obracanie czujnika w celu skanowania otoczenia. Aby uzyskać szczegółowy schemat połączeń specyficzny dla Twojego zestawu, zapoznaj się z oficjalną dokumentacją SunFounder.

Główne połączenia obejmują piny trigger i echo czujnika ultradźwiękowego oraz pin sygnałowy serwomechanizmu, wszystkie podłączone do określonych pinów GPIO na Raspberry Pi Pico. Sterownik silników jest również podłączony do Pico, aby kontrolować cztery silniki napędowe. Film wspomina, że pełna dokumentacja, w tym schematy połączeń, jest dostępna do pobrania wraz z zestawem.

Sunfounder_Pico4DW-09-Obstacle-avoidance_gdy czujnik ultradźwiękowy wykrywa przeszkodę

Wyjaśnienie kodu

Ta lekcja skupia się na logice zawartej w przykładzie `obstacle_avoid`. Kod jest napisany w MicroPython. Chociaż pełny program jest dostępny do pobrania, skupimy się na kluczowych, konfigurowalnych przez użytkownika parametrach, które kontrolują zachowanie samochodu. Zazwyczaj znajdują się one na początku skryptu.

Oto główne zmienne, które możesz dostosować, aby precyzyjnie wyregulować działanie swojego robota:


# Parametry radaru i ruchu
radar_reference = 20  # Minimalna odległość w cm uznawana za bezpieczną
step_angle = 10       # Przyrost kąta dla każdego kroku skanowania radaru
forward_speed = 30    # Prędkość silników podczas jazdy do przodu (0-100)
turn_speed = 50       # Prędkość silników podczas skręcania (0-100)
forward_scan_angle = 50  # Kąt skanowania serwomechanizmu, gdy nie wykryto przeszkody
  • radar_reference: To kluczowa bezpieczna odległość w centymetrach. Jeśli przeszkoda zostanie wykryta bliżej niż ta wartość, samochód uzna ją za „zagrożenie” i rozpocznie manewr omijania. W filmie ustawiono to na 20 cm.
  • step_angle: Określa rozdzielczość skanowania radaru. Mniejsza wartość (np. 10 stopni) oznacza bardziej szczegółowe skanowanie, ale trwa dłużej. Większa wartość byłaby szybsza, ale mogłaby pominąć wąskie przeszkody.
  • forward_speed i turn_speed: Kontrolują moc przekazywaną do silników. Możesz je dostosować, aby zmienić ogólną prędkość i zwinność samochodu. Prędkość skręcania jest często ustawiana wyżej, aby zapewnić skuteczne obracanie.
  • forward_scan_angle: Gdy bezpośrednio przed pojazdem nie ma zagrożenia, samochód zawęża skanowanie do tego kąta (wyśrodkowanego na przód), aby częściej sprawdzać przeszkody na swojej drodze, co umożliwia płynniejszą jazdę do przodu.

Film wyjaśnia również główną logikę podejmowania decyzji. Funkcja `get_direction()` analizuje listę odczytów odległości (przekonwertowanych na 1 i 0 dla bezpiecznych/niebezpiecznych), aby znaleźć najszerszą ciągłą ścieżkę "1". Na podstawie tego, gdzie znajduje się ta najszersza ścieżka, funkcja zwraca kierunek: "do przodu", "w lewo" lub "w prawo". Główna pętla następnie wykonuje odpowiednią akcję, skręcając samochodem i ponownie skanując, aż droga przed nim będzie wolna.

Projekt na żywo/Demonstracja

Film zawiera dokładną demonstrację projektu. Zaczyna się od przetestowania samego czujnika ultradźwiękowego, aby pokazać, jak mierzy on odległość i wypisuje wartości w konsoli. Instruktor następnie wyjaśnia algorytm unikania przeszkód za pomocą schematu blokowego, szczegółowo opisując proces podejmowania decyzji dotyczący skręcania w lewo i w prawo. Na koniec samochód zostaje umieszczony w małym labiryncie zbudowanym z pudełek, aby zademonstrować pełne zachowanie unikania przeszkód w praktyce. Samochód z powodzeniem porusza się po labiryncie, skręcając w lewo i w prawo, aby znaleźć wolną drogę do przodu.

Rozdziały filmu

  • [00:00] Wprowadzenie do unikania przeszkód
  • [01:31] Przegląd zestawu SunFounder Smart Car Kit i jego funkcji
  • [02:47] Jak działa funkcja unikania przeszkód
  • [03:34] Testowanie czujnika ultradźwiękowego
  • [07:45] Wyjaśnienie algorytmu unikania przeszkód i schematu blokowego
  • [12:49] Analiza głównego kodu unikania przeszkód
  • [15:43] Demonstracja na żywo logiki unikania przeszkód
  • [22:53] Finalna demonstracja z labiryntem przeszkód
  • [24:35] Podsumowanie i kolejne kroki

Obrazy

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
Język: 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()

Rzeczy, których możesz potrzebować

Zasoby i odniesienia

Brak zasobów.

Pliki📁

Kod Raspberry Pi