Spisu treści:
2025 Autor: John Day | [email protected]. Ostatnio zmodyfikowany: 2025-01-13 06:58
W tych bardzo krótkich Instruktażach dostroisz swojego GiggleBot, aby podążał za czarną linią. W tym innym samouczku GiggleBot Line Follower zakodowaliśmy na stałe wartości dostrajania, aby działały zgodnie z tym scenariuszem. Możesz chcieć, aby zachowywał się lepiej, wymyślając inne korzyści.
W tym samouczku pokazujemy 2 skrypty, które można załadować do różnych BBC micro:bits, tak aby jeden z nich został umieszczony w GiggleBot, a drugi, 2 przyciski służą do przechodzenia przez menu i dostrajania różnych parametry. Wysyłanie tych zaktualizowanych parametrów odbywa się drogą radiową.
Krok 1: Wymagane składniki
Będziesz potrzebować:
- Robot GiggleBot dla micro:bit.
- 3 baterie AA
- x2 BBC micro:bits - jeden dla GiggleBota, a drugi pełniący funkcję pilota do strojenia parametrów.
- Bateria do BBC micro:bit - taka jak ta, która znajduje się w pakiecie BBC micro:bit.
Pobierz tutaj robota GiggleBot dla BBC micro:bit
Krok 2: Konfiguracja torów i środowiska
Musisz także faktycznie zbudować swoje ścieżki (pobrać, wydrukować, wyciąć i nagrać płytki), a następnie skonfigurować środowisko (IDE i środowisko wykonawcze).
Ponieważ ten samouczek jest bardzo powiązany z tym innym samouczkiem zatytułowanym GiggleBot Line Follower, po prostu idź tam i wykonaj kroki 2 i 3, a następnie wróć tutaj.
Jeśli chodzi o IDE, możesz użyć edytora Mu, a do uruchomienia musisz pobrać GiggleBot MicroPython Runtime. Środowisko wykonawcze można pobrać z jego dokumentacji tutaj. Przejdź do rozdziału dokumentacji Pierwsze kroki i postępuj zgodnie z instrukcjami dotyczącymi konfigurowania środowiska. Od tego momentu używana jest wersja v0.4.0 środowiska wykonawczego.
Krok 3: Konfigurowanie GiggleBot
Przed flashowaniem środowiska wykonawczego do GiggleBot upewnij się, że wybrałeś żądaną prędkość i częstotliwość aktualizacji dla GiggleBot: domyślnie prędkość jest ustawiona na 100 (zmienna base_speed), a częstotliwość aktualizacji na 70 (zmienna update_rate).
Biorąc pod uwagę obecną implementację, najwyższa szybkość aktualizacji, jaką można osiągnąć, wynosi 70, a jeśli run_neopixels jest ustawione na True, można osiągnąć tylko 50. W pewnym sensie można więc powiedzieć, że domyślna częstotliwość aktualizacji jest na granicy tego, co może zrobić BBC micro:bit.
Dla przypomnienia, czujnik śledzenia linii może zwracać aktualizacje 100 razy na sekundę.
Uwaga: w poniższym skrypcie może brakować białych znaków i wydaje się, że jest to spowodowane pewnym problemem z wyświetlaniem GitHub Gist. Kliknij treść, aby przejść do strony GitHub, gdzie możesz skopiować i wkleić kod.
GiggleBot PID Line Follower Tuner (wymaga pilota do strojenia) - xjfls23
z importu mikrobitów* |
z importu gigglebot* |
z utime importuj sleep_ms, ticks_us |
importuj radio |
importuj ustruktur |
# inicjalizuj radio i neopiksele GB |
radio.on() |
neo = init() |
# wyczucie czasu |
aktualizacja_rate = 70 |
# domyślne wartości wzmocnienia |
Kp = 0,0 |
Ki = 0,0 |
Kd = 0,0 |
wartość zadana =0,5 |
punkt_wyzwalania =0.0 |
min_speed_percent = 0,2 |
prędkość_bazowa =100 |
ostatnia pozycja = wartość zadana |
całka =0,0 |
run_neopixels =Fałsz |
center_pixel =5# gdzie środkowy piksel uśmiechu znajduje się na GB |
# turkus = tuple(map(lambda x:int(x/5), (64, 224, 208))) # kolor do narysowania błędu za pomocą neopikseli |
# turkus = (12, 44, 41) # czyli dokładnie ten turkus skomentowany powyżej |
error_width_per_pixel =0.5/3# maksymalny błąd podzielony przez liczbę segmentów pomiędzy każdym neopikselem |
defupper_bound_linear_speed_reducer(błąd_abs, punkt_wyzwalania, górna_granica, najmniejsza_moc_silnika, najwyższa_moc_silnika): |
globalna prędkość bazowa |
jeśli abs_error >= trigger_point: |
# x0 = 0,0 |
# y0 = 0,0 |
# x1 = górna granica - punkt_wyzwalania |
# y1 = 1,0 |
# x = błąd_abs - punkt_wyzwalania |
# y = y0 + (x - x0) * (y1 - y0) / (x1 - x0) |
# taki sam jak |
y = (błąd_abs - punkt_wyzwalania) / (granica górna - punkt_wyzwalania) |
moc_silnika = prędkość_podstawowa * (najmniejsza_moc_silnika + (1-y) * (najwyższa_moc_silnika - najmniejsza_moc_silnika)) |
powrót moc_silnika |
w przeciwnym razie: |
zwróć prędkość_podstawową * najwyższa_moc_silnika |
uruchom =Fałsz |
poprzedni_błąd = 0 |
całkowity_czas = 0,0 |
całkowita_liczba = 0 |
podczas gdy prawda: |
# jeśli przycisk a zostanie naciśnięty, zacznij podążać |
jeśli button_a.is_pressed(): |
uruchom =prawda |
# ale jeśli przycisk b zostanie naciśnięty, zatrzymaj podążającego za linią |
jeśli button_b.is_pressed(): |
uruchom =Fałsz |
całka =0,0 |
poprzedni_błąd = 0,0 |
display.scroll('{} - {}'.format(całkowity_czas, całkowita_liczba), opóźnienie=100, czekaj=False) |
całkowity_czas = 0,0 |
całkowita_liczba = 0 |
wył_piksele() |
zatrzymać() |
sen_ms(500) |
jeśli run is True: |
# odczytaj czujniki linii |
start_time = ticks_us() |
# sprawdź czy zaktualizowaliśmy zyski Kp/Kd za pomocą pilota |
próbować: |
Kp, Ki, Kd, trigger_point, min_speed_percent = ustruct.unpack('ffffff', radio.receive_bytes()) |
zestaw_oczy() |
z wyjątkiem błędu typu: |
przechodzić |
prawo, lewo = read_sensor (LINE_SENSOR, BOTH) |
# linia jest po lewej stronie, gdy pozycja < 0,5 |
# linia jest po prawej stronie, gdy pozycja > 0,5 |
# linia jest w środku, gdy pozycja = 0.5 |
# to ważona średnia arytmetyczna |
próbować: |
pozycja = prawo /float(lewo + prawo) |
z wyjątkiem ZeroDivisionError: |
pozycja = 0.5 |
jeśli pozycja ==0: pozycja =0.001 |
jeśli pozycja ==1: pozycja =0.999 |
# użyj kontrolera PD |
błąd = pozycja - wartość zadana |
całka += błąd |
korekta = Kp * błąd + Ki * całka + Kd * (błąd - poprzedni_błąd) |
poprzedni_błąd = błąd |
# obliczyć prędkości silnika |
prędkość_silnika = górna_granica_liniowej_reduktora_prędkości(abs(błąd), nastawa * punkt_wyzwalania, nastawa, min_prędkość_procent, 1.0) |
leftMotorSpeed = prędkość_silnika + korekta |
rightMotorSpeed = prędkość_silnika - korekta |
# rozświetl neopiksele, aby pokazać, w którym kierunku ma iść GiggleBot |
jeśli run_neopixels isTrue i total_counts %3==0: |
dla i inb'\x00\x01\x02\x03\x04\x05\x06\x07\x08': |
neo = (0, 0, 0) |
dla i inb'\x00\x01\x02\x03': |
ifabs(błąd) > szerokość_błędu na piksel * i: |
jeśli błąd <0: |
neo[center_pixel + i] = (12, 44, 41) |
w przeciwnym razie: |
neo[center_pixel - i] = (12, 44, 41) |
w przeciwnym razie: |
procent =1- (szerokość_błędu_na_piksel * i -abs(błąd)) / szerokość_błędu_na_piksel |
# podświetl bieżący piksel |
jeśli błąd <0: |
# neo[center_pixel + i] = krotka(map(lambda x: int(x * procent), turkus)) |
neo[center_pixel + i] = (int(12* procent), int(44* procent), int(41* procent)) |
w przeciwnym razie: |
# neo[center_pixel - i] = krotka(map(lambda x: int(x * procent), turkus)) |
neo[center_pixel - i] = (int(12* procent), int(44* procent), int(41* procent)) |
przerwa |
neo.pokaż() |
próbować: |
# przypnij silniki |
jeśli lewyMotorSpeed >100: |
lewa prędkość silnika =100 |
rightMotorSpeed = rightMotorSpeed - leftMotorSpeed +100 |
jeśli prawyPrędkość silnika >100: |
prawa Prędkość Silnika =100 |
leftMotorSpeed = leftMotorSpeed - rightMotorSpeed +100 |
jeśli lewyMotorSpeed <-100: |
lewa prędkość silnika =-100 |
jeśli prawyMotorSpeed <-100: |
prawa Prędkość Silnika =-100 |
# uruchomić silniki |
set_speed(lewaPrędkośćMotora, prawaPrędkośćMotora) |
prowadzić samochód() |
# print((błąd, prędkość silnika)) |
z wyjątkiem: |
# na wypadek, gdybyśmy mieli jakiś problem, którego nie da się naprawić |
przechodzić |
# i utrzymuj częstotliwość pętli |
end_time = ticks_us() |
delay_diff = (end_time - start_time) /1000 |
całkowity_czas += opóźnienie_różnic |
total_counts +=1 |
if1.0/ update_rate - delay_diff >0: |
sen (1.0/ częstotliwość_aktualizacji - różnica_opóźnień) |
zobacz rawgigglebot_line_follower_tuner.py hostowany z ❤ przez GitHub
Krok 4: Konfigurowanie tunera (zdalne)
Następną rzeczą, którą musimy zrobić, jest flashowanie runtime + skryptu do drugiego BBC micro:bit. Ten drugi micro:bit będzie działał jako pilot do GiggleBot, który będzie używany do dostrajania następujących parametrów:
- Kp = wzmocnienie proporcjonalne dla regulatora PID.
- Ki = wzmocnienie całkowania dla regulatora PID.
- Kd = wzmocnienie różniczkujące dla regulatora PID.
- trigger_point = punkt wyrażony w procentach między minimalną a maksymalną prędkością GiggleBot, przy której prędkość zaczyna się zmniejszać liniowo, aż osiągnie prędkość minimalną.
- min_speed_percent = minimalna prędkość wyrażona w procentach maksymalnej prędkości.
Pozostałe 2 pozostałe zmienne, które można dostroić, są bezpośrednio zakodowane w skrypcie znajdującym się na GiggleBot: update_rate i base_speed, które reprezentują maksymalną prędkość. Jak opisano w dokumentacji, maksymalna prędkość, jaką można ustawić dla GiggleBot to 100, co jest również wartością domyślną dla naszego GiggleBot.
Uwaga: w poniższym skrypcie może brakować białych znaków i wydaje się, że jest to spowodowane pewnym problemem z wyświetlaniem GitHub Gist. Kliknij treść, aby przejść do strony GitHub, gdzie możesz skopiować i wkleić kod.
GiggleBot Remote PID Line Follower Tuner (wymaga drugiej części) - xjfls23
z importu mikrobitów* |
z utime importuj sleep_ms |
importuj radio |
importuj ustruktur |
# 1 element to wzmocnienie Kp |
# Drugim elementem jest wzmocnienie Ki |
# 3 element to wzmocnienie Kd |
# Czwarty element to punkt_wyzwalania dla silników, aby obniżyć prędkość (0 -> 1) |
# Piąty element to minimalna prędkość silników wyrażona w procentach (0 -> 1) |
zyski = [0,0, 0,0, 0,0, 1,0, 0,0] |
rozmiar kroku = 0,1 |
# 0 i 1 dla pierwszego elementu |
# 2 i 3 dla drugiego elementu |
obecneUstawienie =0 |
defshowMenu(): |
display.scroll('{} - {}'.format(currentSetting, gains[int(currentSetting /2)]), delay=100, wait=False) |
radio.on() |
Pokaż menu() |
podczas gdy prawda: |
zaktualizowano = Fałsz |
jeśli button_a.is_pressed(): |
CurrentSetting = (currentSetting +1) % (2*5) |
zaktualizowano = Prawda |
jeśli button_b.is_pressed(): |
jeśli obecneUstawienie %2==0: |
# zwiększ wzmocnienie, gdy currentSetting wynosi 0 lub 2 lub.. |
ifint(currentSetting /2) w [0, 2]: |
zyski[int(currentSetting /2)] +=10* stepSize |
w przeciwnym razie: |
zyski[int(currentSetting /2)] += stepSize |
w przeciwnym razie: |
# zwiększ wzmocnienie, gdy currentSetting wynosi 1 lub 3 lub.. |
ifint(currentSetting /2) w [0, 2]: |
zyski[int(currentSetting /2)] -=10* stepSize |
w przeciwnym razie: |
zyski[int(currentSetting /2)] -= stepSize |
radio.send_bytes(ustruct.pack('fffff', *zyski)) |
zaktualizowano = Prawda |
jeśli zaktualizowany: |
Pokaż menu() |
sen_ms(200) |
wyświetl rawgigglebot_line_follower_configurator.py hostowany z ❤ przez GitHub
Krok 5: Dostrajanie GiggleBot
Umieść GiggleBot na torze, włącz go i pozwól mu działać. W międzyczasie będziesz musiał ciągle umieszczać go z powrotem na torze i dostrajać wzmocnienia/parametry za pomocą drugiego micro:bit BBC, który trzymasz w dłoni.
Aby uruchomić GiggleBot, naciśnij przycisk A na BBC micro:bit GiggleBota, a aby go zatrzymać, a tym samym zresetować jego stan, naciśnij przycisk B.
Na zdalnym BBC micro:bit naciśnięcie przycisku A spowoduje przejście przez każdą opcję w jego menu, a przycisk B zwiększy/zmniejszy odpowiednią wartość. To jak ustawienie zegara na desce rozdzielczej starego samochodu. Opcje są takie:
- Opcje 0-1 dotyczą wzmocnienia Kp.
- 2-3 opcje są dla wzmocnienia Ki.
- 4-5 opcji dotyczy wzmocnienia Kd.
- Opcje 6-7 służą do ustawienia wartości zadanej na moment, w którym silniki zaczną zwalniać.
- 8-9 opcji służy do ustawienia minimalnej prędkości.
Pamiętaj, że liczby parzyste w menu służą do zwiększania odpowiednich wartości, a nieparzyste jest dokładnie odwrotnie.
Ponadto, po naciśnięciu przycisku B na BBC micro:bit GiggleBot, zobaczysz na ekranie wykonanym z Neopixela liczbę milisekund, które upłynęły od ostatniego resetu oraz liczbę cykli, które przeszedł robot - z tymi 2 możesz obliczyć częstotliwość aktualizacji robota.
Na koniec i co najważniejsze, wymyśliłem 2 stroje dla GiggleBot. Jedna z nich służy do wyłączania diod Neopixel, a druga do sytuacji, gdy jest inaczej. Diody LED Neopixel służą do wskazywania kierunku, w którym nagromadził się błąd.
Pierwszy zestaw dostrajania parametrów (z wyłączonymi diodami NeoPixel)
- Kp = 32,0
- Ki = 0,5
- Kd = 80,0
- trigger_setpoint = 0,3 (czyli 30%)
- min_speed_percent = 0,2 (czyli 20%)
- base_speed = 100 (czyli maksymalna prędkość)
- update_rate = 70 (działa przy 70 Hz)
2 zestaw dostrajania parametrów (z włączonymi diodami NeoPixel)
- Kp = 25,0
- Ki = 0,5
- Kd = 35,0
- trigger_setpoint = 0,3 (czyli 30%)
- min_speed_percent = 0,3 (czyli 30%)
- base_speed = 70 (czyli maksymalna prędkość)
- update_rate = 50 (działa przy 50 Hz)
- Ponadto zmienna run_neopixels musi być ustawiona na True w skrypcie, który jest ładowany do BBC micro:bit GiggleBot. Spowoduje to, że diody NeoPixel będą migać w taki sposób, aby wskazywały kierunek kumulacji błędu.
Krok 6: GiggleBot działa z wyłączonymi NeoPixels
To jest przykład uruchomienia GiggleBota z pierwszymi parametrami strojenia znalezionymi w poprzednim kroku. W tym przykładzie diody LED NeoPixel są wyłączone.
Krok 7: GiggleBot działa z włączonymi neopikselami
To jest przykład uruchomienia GiggleBot z drugim zestawem parametrów strojenia znalezionym w kroku 5. Ten przykład ma włączone diody NeoPixel.
Zauważ, że w tym przykładzie GiggleBot ma trudności z podążaniem za linią - to dlatego, że diody Neopixel "zjadają" czas procesora BBC micro:bit. Dlatego musieliśmy zmniejszyć częstotliwość aktualizacji z 70 do 50.