Sommario:
- Passaggio 1: componenti richiesti
- Passaggio 2: configurazione delle tracce e dell'ambiente
- Passaggio 3: configurazione di GiggleBot
- Passaggio 4: configurazione del sintonizzatore (remoto)
- Passaggio 5: messa a punto di GiggleBot
- Passaggio 6: GiggleBot in esecuzione con i NeoPixel spenti
- Passaggio 7: GiggleBot in esecuzione con i Neopixel accesi
2025 Autore: John Day | [email protected]. Ultima modifica: 2025-01-13 06:57
In questo brevissimo Instructables adatterai il tuo GiggleBot per seguire una linea nera. In questo altro tutorial GiggleBot Line Follower, abbiamo codificato i valori di ottimizzazione per funzionare in base a quello scenario. Potresti voler farlo comportare meglio trovando altri vantaggi.
In questo tutorial, ti mostriamo 2 script che possono essere entrambi caricati su diversi micro:bit BBC in modo che uno di essi venga inserito nel GiggleBot e con l'altro i 2 pulsanti siano utilizzati per scorrere un menu e sintonizzare diversi parametri. L'invio di questi parametri aggiornati avviene via radio.
Passaggio 1: componenti richiesti
Avrai bisogno di quanto segue:
- Un robot GiggleBot per il micro:bit.
- x3 batterie AA
- x2 BBC micro:bits - uno per GiggleBot e l'altro che funge da telecomando per la regolazione dei parametri.
- Una batteria per un BBC micro:bit, come quella inclusa nel pacchetto BBC micro:bit.
Ottieni il robot GiggleBot per il micro:bit della BBC qui
Passaggio 2: configurazione delle tracce e dell'ambiente
Devi anche creare effettivamente le tue tracce (scaricare, stampare, tagliare e registrare i riquadri) e quindi impostare l'ambiente (l'IDE e il runtime).
Poiché questo tutorial è molto correlato a questo altro tutorial intitolato GiggleBot Line Follower, vai lì e segui i passaggi 2 e 3 e poi torna qui.
Per quanto riguarda l'IDE, puoi utilizzare l'editor Mu e per il runtime, devi scaricare GiggleBot MicroPython Runtime. Il runtime può essere scaricato dalla sua documentazione qui. Vai al capitolo della documentazione per iniziare e segui le istruzioni sulla configurazione dell'ambiente. A partire da questo momento, viene utilizzata la versione v0.4.0 del runtime.
Passaggio 3: configurazione di GiggleBot
Prima di eseguire il flashing del runtime su GiggleBot, assicurati di aver scelto la velocità e la frequenza di aggiornamento desiderate per GiggleBot: per impostazione predefinita, la velocità è impostata su 100 (variabile base_speed) e la frequenza di aggiornamento è impostata su 70 (variabile update_rate).
Data l'implementazione attuale, la massima velocità di aggiornamento che può essere raggiunta è 70 e se run_neopixels è impostato su True, è possibile ottenere solo 50. Quindi, in un certo senso, potresti dire che la frequenza di aggiornamento predefinita è proprio al limite di ciò che può fare il micro: bit della BBC.
Solo per la cronaca, il sensore line follower può restituire aggiornamenti 100 volte al secondo.
Nota: il seguente script potrebbe avere spazi bianchi mancanti e ciò sembra essere dovuto a qualche problema nella visualizzazione di GitHub Gists. Fai clic sull'essenza per portarti alla sua pagina GitHub dove puoi copiare e incollare il codice.
GiggleBot PID Line Follower Tuner (richiede un telecomando per sintonizzarlo) - xjfls23
dall'importazione di microbit* |
da importazione gigglebot* |
da utime import sleep_ms, ticks_us |
importare radio |
import usstruct |
# inizializza la radio e i neopixel GB |
radio.on() |
neo = inizia() |
# tempi |
update_rate =70 |
# valori di guadagno predefiniti |
Kp =0.0 |
Ki =0.0 |
Kd =0.0 |
setpoint =0,5 |
trigger_point =0.0 |
min_speed_percent =0.2 |
base_speed =100 |
ultima_posizione = setpoint |
integrale =0.0 |
run_neopixels =Falso |
center_pixel =5# dove il pixel centrale del sorriso si trova sul GB |
# turchese = tuple(map(lambda x: int(x / 5), (64, 224, 208))) # colore da usare per disegnare l'errore con i neopixel |
# turchese = (12, 44, 41) # che è esattamente il turchese sopra commentato sopra questo |
error_width_per_pixel =0.5/3# errore massimo diviso per il numero di segmenti tra ogni neopixel |
defupper_bound_linear_speed_reducer(abs_error, trigger_point, upper_bound, più piccolo_motor_power, più alto_motor_power): |
base_speed globale |
if abs_error >= trigger_point: |
# x0 = 0.0 |
# y0 = 0.0 |
# x1 = limite_superiore - trigger_point |
# y1 = 1.0 |
# x = abs_error - trigger_point |
# y = y0 + (x - x0) * (y1 - y0) / (x1 - x0) |
# uguale a |
y = (abs_error - trigger_point) / (upper_bound - trigger_point) |
potenza_motore = velocità_base * (potenza_motore_minima + (1- y) * (potenza_motore_massima - potenza_motore_minima)) |
restituire motor_power |
altro: |
return base_speed *high_motor_power |
corri = falso |
errore_precedente = 0 |
tempo_totale =0.0 |
total_counts = 0 |
mentreVero: |
# se viene premuto il pulsante a, inizia a seguire |
if button_a.is_pressed(): |
corri = Vero |
# ma se viene premuto il pulsante b ferma il line follower |
if button_b.is_pressed(): |
corri = falso |
integrale =0.0 |
errore_precedente =0.0 |
display.scroll('{} - {}'.format(total_time, total_counts), delay=100, wait=False) |
tempo_totale =0.0 |
total_counts = 0 |
pixels_off() |
fermare() |
sleep_ms(500) |
se run isTrue: |
# leggi i sensori di linea |
start_time = ticks_us() |
# controlla se abbiamo aggiornato i guadagni Kp/Kd con un telecomando |
Tentativo: |
Kp, Ki, Kd, trigger_point, min_speed_percent = ustruct.unpack('fffff', radio.receive_bytes()) |
set_occhi() |
eccezioneTipoErrore: |
passaggio |
destra, sinistra = read_sensor(LINE_SENSOR, BOTH) |
# la riga è a sinistra quando la posizione < 0,5 |
# la linea è a destra quando la posizione > 0,5 |
# la linea è al centro quando posizione = 0,5 |
# è una media aritmetica ponderata |
Tentativo: |
posizione = destra / float (sinistra + destra) |
tranneZeroDivisionError: |
posizione =0,5 |
se posizione ==0: posizione =0.001 |
se posizione ==1: posizione =0.999 |
# usa un controller PD |
errore = posizione - setpoint |
integrale += errore |
correzione = Kp * errore + Ki * integrale + Kd * (errore - errore_precedente) |
errore_precedente = errore |
# calcola le velocità del motore |
motor_speed = upper_bound_linear_speed_reducer(abs(error), setpoint * trigger_point, setpoint, min_speed_percent, 1.0) |
leftMotorSpeed = motor_speed + correzione |
rightMotorSpeed = motor_speed - correzione |
# accendi i neopixel per mostrare in quale direzione deve andare il GiggleBot |
se run_neopixels isTrueand total_counts %3==0: |
per i inb'\x00\x01\x02\x03\x04\x05\x06\x07\x08': |
neo = (0, 0, 0) |
per i inb'\x00\x01\x02\x03': |
ifabs(errore) > error_width_per_pixel * i: |
se errore <0: |
neo[center_pixel + i] = (12, 44, 41) |
altro: |
neo[center_pixel - i] = (12, 44, 41) |
altro: |
percent =1- (error_width_per_pixel * i -abs(error)) / error_width_per_pixel |
# illumina il pixel corrente |
se errore <0: |
# neo[center_pixel + i] = tuple(map(lambda x: int(x * percentuale), turchese)) |
neo[center_pixel + i] = (int(12* percento), int(44* percento), int(41* percento)) |
altro: |
# neo[center_pixel - i] = tuple(map(lambda x: int(x * percentuale), turchese)) |
neo[center_pixel - i] = (int(12* percento), int(44* percento), int(41* percento)) |
rottura |
neo.mostra() |
Tentativo: |
# agganciare i motori |
se sinistraMotorSpeed >100: |
leftMotorSpeed =100 |
rightMotorSpeed = rightMotorSpeed - leftMotorSpeed +100 |
se destraMotorSpeed >100: |
rightMotorSpeed =100 |
leftMotorSpeed = leftMotorSpeed - rightMotorSpeed +100 |
se sinistraMotorSpeed <-100: |
sinistraMotorSpeed =-100 |
se rightMotorSpeed <-100: |
RightMotorSpeed =-100 |
# azionare i motori |
set_speed(leftMotorSpeed, rightMotorSpeed) |
unità() |
# print((errore, velocità_motore)) |
tranne: |
# nel caso dovessimo riscontrare qualche problema irrisolvibile |
passaggio |
# e mantenere la frequenza del loop |
end_time = ticks_us() |
delay_diff = (end_time - start_time) /1000 |
total_time += delay_diff |
total_counts +=1 |
if1.0/ update_rate - delay_diff >0: |
sleep(1.0/ update_rate - delay_diff) |
visualizza rawgigglebot_line_follower_tuner.py ospitato con ❤ da GitHub
Passaggio 4: configurazione del sintonizzatore (remoto)
La prossima cosa che dobbiamo fare è eseguire il flashing dello script runtime + nel secondo micro: bit della BBC. Questo secondo micro:bit fungerà da telecomando per GiggleBot, che verrà utilizzato per regolare i seguenti parametri:
- Kp = guadagno proporzionale per il controllore PID.
- Ki = guadagno integrale per il controller PID.
- Kd = guadagno derivativo per il controllore PID.
- trigger_point = il punto espresso in percentuale tra la velocità minima e massima del GiggleBot in cui la velocità inizia a diminuire linearmente fino a raggiungere la velocità minima.
- min_speed_percent = la velocità minima espressa in percentuale della velocità massima.
Le altre 2 variabili rimanenti che possono essere sintonizzate sono direttamente codificate nello script che si trova su GiggleBot: update_rate e base_speed che rappresenta la velocità massima. Come descritto nella documentazione, la velocità massima che può essere impostata per il GiggleBot è 100, che è anche il valore predefinito per il nostro GiggleBot.
Nota: il seguente script potrebbe avere spazi bianchi mancanti e ciò sembra essere dovuto a qualche problema nella visualizzazione di GitHub Gists. Fai clic sull'essenza per portarti alla sua pagina GitHub dove puoi copiare e incollare il codice.
GiggleBot Remote PID Line Follower Tuner (richiede l'altra parte) - xjfls23
dall'importazione di microbit* |
da utime import sleep_ms |
importare radio |
import usstruct |
# Il primo elemento è il guadagno Kp |
# Il secondo elemento è il guadagno Ki |
# 3° elemento è il guadagno Kd |
# 4th elemento è il trigger_point per i motori per abbassare la velocità (0 -> 1) |
# 5° elemento è la velocità minima dei motori espressa in percentuale (0 -> 1) |
guadagni = [0.0, 0.0, 0.0, 1.0, 0.0] |
passoSize =0.1 |
# 0 e 1 per il primo elemento |
# 2 e 3 per il 2° elemento |
impostazionecorrente =0 |
defshowMenu(): |
display.scroll('{} - {}'.format(currentSetting, gains[int(currentSetting /2)]), delay=100, wait=False) |
radio.on() |
mostraMenu() |
mentreVero: |
aggiornato = Falso |
if button_a.is_pressed(): |
impostazionecorrente = (impostazionecorrente +1) % (2*5) |
aggiornato = Vero |
if button_b.is_pressed(): |
if currentSetting %2==0: |
# aumenta il guadagno quando CurrentSetting è 0 o 2 o.. |
ifint(impostazionecorrente /2) in [0, 2]: |
gains[int(currentSetting /2)] +=10* stepSize |
altro: |
gains[int(currentSetting /2)] += stepSize |
altro: |
# aumenta il guadagno quando l'impostazione corrente è 1 o 3 o.. |
ifint(impostazionecorrente /2) in [0, 2]: |
gains[int(currentSetting /2)] -=10* stepSize |
altro: |
gains[int(currentSetting /2)] -= stepSize |
radio.send_bytes(ustruct.pack('ffffff', *guadagni)) |
aggiornato = Vero |
se aggiornato: |
mostraMenu() |
sleep_ms(200) |
visualizza rawgigglebot_line_follower_configurator.py ospitato con ❤ da GitHub
Passaggio 5: messa a punto di GiggleBot
Posiziona il GiggleBot sulla pista, accendilo e lascialo funzionare. Nel frattempo, dovrai costantemente rimetterlo in pista e sintonizzare i guadagni/parametri con l'altro micro:bit BBC che tieni in mano.
Per avviare il GiggleBot, premere il pulsante A sul micro:bit BBC di GiggleBot e per fermarlo e quindi ripristinare il suo stato premere il pulsante B.
Sul telecomando BBC micro:bit, premendo il pulsante A si passa attraverso tutte le opzioni del suo menu e il pulsante B aumenta/diminuisce il valore corrispondente. È come impostare l'orologio sul cruscotto di una vecchia macchina. Le opzioni sono così:
- Le opzioni 0-1 sono per il guadagno Kp.
- 2-3 opzioni sono per il guadagno Ki.
- 4-5 opzioni sono per il guadagno Kd.
- Le opzioni 6-7 servono per impostare il setpoint per il momento in cui i motori iniziano a rallentare.
- 8-9 opzioni servono per impostare la velocità minima.
Tieni presente che i numeri pari nel menu servono per aumentare i valori corrispondenti e per quelli dispari è esattamente l'opposto.
Inoltre, quando premi il pulsante B sul micro:bit BBC di GiggleBot, vedrai sul suo schermo realizzato in Neopixel il numero di millisecondi trascorsi dall'ultimo reset e il numero di cicli che il robot ha attraversato - con questi 2 puoi calcolare la velocità di aggiornamento del robot.
Infine, e soprattutto, ho trovato 2 accordature per GiggleBot. Uno di questi è per quando i LED Neopixel sono spenti e l'altro è per quando è diversamente. I LED Neopixel vengono utilizzati per mostrare in quale direzione si è accumulato l'errore.
1° set di tuning dei parametri (con led NeoPixel spenti)
- Kp = 32.0
- Ki = 0,5
- Kd = 80.0
- trigger_setpoint = 0,3 (che è il 30%)
- min_speed_percent = 0,2 (che è il 20%)
- base_speed = 100 (ovvero velocità massima)
- update_rate = 70 (in esecuzione a 70Hz)
2° set di tuning dei parametri (con i led NeoPixel accesi)
- Kp = 25,0
- Ki = 0,5
- Kd = 35,0
- trigger_setpoint = 0,3 (che è il 30%)
- min_speed_percent = 0,3 (che è il 30%)
- base_speed = 70 (ovvero velocità massima)
- update_rate = 50 (in esecuzione a 50Hz)
- Inoltre, la variabile run_neopixels deve essere impostata su True nello script che viene caricato sul micro:bit BBC di GiggleBot. Questo farà lampeggiare i LED NeoPixel in modo tale da indicare verso quale direzione si accumula l'errore.
Passaggio 6: GiggleBot in esecuzione con i NeoPixel spenti
Questo è un esempio di esecuzione di GiggleBot con i primi parametri di ottimizzazione trovati nel passaggio precedente. Questo esempio ha i LED NeoPixel spenti.
Passaggio 7: GiggleBot in esecuzione con i Neopixel accesi
Questo è un esempio di esecuzione di GiggleBot con il secondo set di parametri di ottimizzazione trovato nel passaggio 5. Questo esempio ha i LED NeoPixel accesi.
Nota come in questo esempio, GiggleBot ha più difficoltà a seguire la linea, perché i LED Neopixel "mangiano" il tempo della CPU del micro:bit BBC. Ecco perché abbiamo dovuto ridurre la frequenza di aggiornamento da 70 a 50.