Aiuto sviluppo codice per roving self balancing

gbm:
Piu' che altro ci sono tante considerazioni da fare, per esempio quando il robot va in avanti dovrà essere sempre inclinato indietro rispetto allo 0 di un angolo che varia in rapporto alla sua velocità (deve essere molto inclinato all'indietro al max per evitare di cadere in avanti)...

Questo è il limite di tutti i balancing robot che non usano sensori inerziali, il sensore assoluto di inclinazione realizzato con telemetri, non importa come sono fatti, va benissimo per le condizioni statiche, cioè robot fermo, o di marcia a bassissima velocità, non è sufficiente per farlo muovere sul serio e, sopratutto, per affrontare le pendenze, anche se molto piccole.
L'inclinazione nel senso di marcia serve per compensare la forza derivante dall'accelerazione e varia in funzione di quest'ultima, ovvero maggiore accelerazione comporta un maggiore angolo di inclinazione, una volta raggiunta la velocità di crociera l'inclinazione torna a 0.
Per determinare l'inclinazione ottimale occorre conoscere la posizione del baricentro del robot e la forza che vi agisce sopra, la prima la puoi trovare facilmente in modo sperimentale, per la seconda devi conoscere la massa del robot (basta pesarlo) e l'accelerazione, quest'ultima o la ricavi dai sensori oppure la conosci a priori perché utilizzi motori con encoder, servono quelli veri ad alta risoluzione con motori buoni, controllati da un pid fatto molto bene.
La soluzione ottimale è utilizzare motori con encoder abbinati ad un sensore inerziale ottenuto in sensor fusion dalla combinazione di un accelerometro a due assi montato inclinato sulla verticale di 45° e un giroscopio.

p.s.
Non esiste la massa statica e la massa dinamica, la massa è sempre e solamente la massa, semmai esiste la quantità di moto e la forza/momento d'inerzia, la prima dipende dalla massa e dalla velocità, la seconda dalla massa e dall'accelerazione lineare/angolare.

Non mi intrometto per spammare ma per fare una considerazione.
Leggo:

per esempio quando il robot va in avanti dovrà essere sempre inclinato indietro

A me ciò non torna, nel senso che se quest'affermazione può essere corretta teoricamente, all'atto pratico nel mondo reale succede l'opposto, ossia per bilanciare un oggetto in movimento questo lo si piega in avanti, non indietro. Piegandolo indietro si richiede più energia sia per farlo avanzare sia per tenerlo in equilibrio dato che la gravità tende a farlo cadere, se a ciò aggiungiamo anche l'accelerazione la forza che lo spinge al ribaltamento aumenta l'effetto.

Pensate ad una persona con una pila di piatti. Finché sta ferma non ci sono problemi, ma non appena avanza questa tende a piegare la pila in avanti dato che l'inerzia unita all'accelerazione tende a piegare la pila indietro. E se non si compensa questo spostamento si sa che fine farà la pila :astonished:

leo72:
A me ciò non torna, nel senso che se quest'affermazione può essere corretta teoricamente, all'atto pratico nel mondo reale succede l'opposto, ossia per bilanciare un oggetto in movimento questo lo si piega in avanti, non indietro

Si è così, sicuramente Gio ha fatto, involontariamente, un pochino di confusione mentre scriveva.
Comunque attenzione a non confondere il movimento con l'accelerazione, l'inclinazione serve solo durante l'accelerazione/decelerazione, e comunque non è obbligatoria perché imposta dalla fisica, è solo un modo per sfruttare il peso in modo da compensare le forze senza utilizzare energia aggiuntiva sul motore.
Eventualmente un pochino di inclinazione nel senso di marcia si può usare per compensare la coppia dei motori, dipende molto dalla massa del robot e dalla coppia stessa, per piccoli robot come quello in oggetto è praticamente ininfluente.

Ciao ragazzi, grazie a tutti per la risposta.
Astrobeed ha chiarito un punto che io consideravo diversamente. L'offset angolare che io voglio aggiungere al PID ci sarà solo in momenti di accelerazione o decelerazione.
Questo offset varierà in base alla velocità e alla massa del robot. Per frenare è fondamentale portare il robot in una postura con angolo negativo rispetto al moto, per evitare di ribaltarsi in avanti frenando e per avere un po' di margine per frenate piu repentine (per questo stavo ragionando di tenerlo sempre leggermente in negativo, cosi' da poter frenare in tempi utili in caso ci sia un ostacolo). Stessa cosa per l'accelerazione da fermo, sarà necessario un offset positivo per evitare di ribaltarsi indietro partendo.

Sono d'accordo con te Astrobeed sul sensor fusion, ho gia con successo testato il robot con la IMU main vecchia di sparkfun con un lils e un adx, facendo arco tangente di due assi dell'acc e giro tutto filtrato con kalman, e funziona decisamente meglio di quello con i sensori IR ERER. Solo che la IMU mi serve per l'aeromodello che stiamo testando in volo autonomo :grin: e poi volevo raggiungere un bel risultato cosi' com'è per poter permettere a tutti gli appassionati di farsi un self balancing senza dover spendere 50 euro per la IMU, chiaramente con tutte le limitazioni del caso, che pero' vanno di pari passo con la complessità hardware e software.

Grazie del contributo Joomoon provo a mettermi a scriverla come hai proposto...

gbm:
Questo offset varierà in base alla velocità e alla massa del robot.

No, è solo in base all'accelerazione, non importa se il robot viaggia a 1 cm/s o a 10 m/s, in fase di avanzamento a velocità costante l'assetto sarà sempre verticale, o quasi se si vuole compensare la coppia sfruttando il peso.
L'inclinazione varia in modo proporzionale, con una legge seno/coseno, in funzione dell'accelerazione e del suo segno.

enare è fondamentale portare il robot in una postura con angolo negativo rispetto al moto, per evitare di ribaltarsi in avanti frenando e per avere un po' di margine per frenate piu repentine (per questo stavo ragionando di tenerlo sempre leggermente in negativo, cosi' da poter frenare in tempi utili in caso ci sia un ostacolo).

Questo è un punto dolente, dipende tutto dalla potenza disponibile, cioè i motori devono essere in grado di "ribaltare" nel senso opposto il robot in un tempo minore di quello imposto dal movimento di pendolo dovuto all'accelerazione.
Tali valori sono calcolabili e devono essere tabellati come massima accelerazione sopportabile, se vai oltre non c'è preinclinazione che tenga, il robot casca.

e poi volevo raggiungere un bel risultato cosi' com'è per poter permettere a tutti gli appassionati di farsi un self balancing senza dover spendere 50 euro per la IMU, chiaramente con tutte le limitazioni del caso, che pero' vanno di pari passo con la complessità hardware e software.

Puoi ovviare, parzialmente, alla mancanza della IMU con gli encoder sui motori, almeno sai velocità e accelerazione reali, però non aspettarti grossi risultati, sopratutto se non usi encoder ad alta risoluzione.
Però ultimamente stanno uscendo vari sensori inerziali, accelerometri e giroscopi, che costano pochi Euro, sono per uso sui cellulari, non saranno precisissimi però dovrebbero bastare per un semplice balancing robot a basso costo.
C'è anche l'estensione del Wii Mote, il motion plus, che costa abbastanza poco, mi pare meno di 20 Euro, e dentro c'è un giroscopio a tre assi su bus I2C.

il nunchuck contiene un'accelerometro 3 assi (ADXL330) a 9/15 euro, il motion plus un giroscopio MEMS 2(IDG600)+1(IDG650) assi sempre a 9 euro. Bus i2c, ad alta velocità, puoi modificare le impostazioni di wire.h, e (col nunchuck, il motion plus non ce l'ho) ottieni oltre 2000 letture al secondo.

Questo è un punto dolente, dipende tutto dalla potenza disponibile, cioè i motori devono essere in grado di "ribaltare" nel senso opposto il robot in un tempo minore di quello imposto dal movimento di pendolo dovuto all'accelerazione.
Tali valori sono calcolabili e devono essere tabellati come massima accelerazione sopportabile, se vai oltre non c'è preinclinazione che tenga, il robot casca.

quoto su tutta la linea. Se non erro usando gbm sta usando i servo a rotazione continua, quindi può giocare con le accelerazioni.. ciò è molto utile.

Ciao raga!! Mi fa strapiacere ricevere cosi' tanti consigli, grandi!

Astrobeed scusami, una domanda, io userei il voltaggio presente nel circuito di alimentazione dei motori per desumere la velocità di rotazione, ho usato questo dato integrato nel tempo per desumere lo spazio percorso ed è preciso nell'ordine di un errrore di un centimetro ogni metro percorso, dici che potrebbe bastare?

Altra domanda, in rapporto alla velocità del robot, diminuirà la capacità dei motori di contrastare una eventuale caduta nella stessa direzione del moto, per questo pensavo di imporre al robot un angolo negativo rispetto alla direzione del moto. Cosi' facendo il robot ridurrà la possibilità di cadere in avanti!! A me sembra che sia un sistema che usano tutti!! Dici che non è sensato?

Appena avro' finito l'algoritmo e fatto un bel po' di video / test ed esperimenti con questo sistema, sostituiro' i due sensori ERER con la IMU, per iniziare a fare test di percorrenza su piani inclinati e percorrenza di salite discese!! :grin:

gbm:
Astrobeed scusami, una domanda, io userei il voltaggio presente nel circuito di alimentazione dei motori per desumere la velocità di rotazione,

Si mi ricordo della cosa, però era rimasto tutto in sospeso in attesa di ulteriori prove.

Altra domanda, in rapporto alla velocità del robot, diminuirà la capacità dei motori di contrastare una eventuale caduta nella stessa direzione del moto

Ovviamente si, la coppia diminuisce in modo quasi lineare in funzione degli rpm, qui toccherebbe aprire un bel capitolo dedicato al dimensionamento del robot inteso come potenza necessaria per soddisfare i vari requisiti di marcia.

, per questo pensavo di imporre al robot un angolo negativo rispetto alla direzione del moto
. Cosi' facendo il robot ridurrà la possibilità di cadere in avanti!! A me sembra che sia un sistema che usano tutti!! Dici che non è sensato?

Se imponi un certo angolo negativo mentre marcia non è che ne trai particolari vantaggi in caso di frenata brusca, tanto se i motori non sono in grado di contrastare la decelerazione non c'è angolo preventivo che tenga, il robot casca.
Per contro un angolo negativo durante la marcia impone un superlavoro ai motori per mantenere l'equilibrio visto che ti verresti a trovare costantemente in una situazione di instabilità.

Mi stai facendo venire la voglia di rispolverare il progetto, di massima, del mio Balancing Robot fatto qualche anno fa e poi messo nel cassetto in attesa di trovare il tempo da dedicare alla sua realizzazione :slight_smile:

non sò perchè ma questa cosa mi sembra difficilmente definibile con la meccanica classica ed invece mi inizia a dare più un senso di meccanica lagrangiana... forse perchè in un certo senso è simile al problema del doppio pendolo.
... se solo capissi quello che ho detto.. :stuck_out_tongue:
ma qualcono che fà ingegneria meccanica o fisica ? :smiley:

hehehehe mi fa piacere, raga ho buttato giu un esempio di come potrebbe essere l'algoritmo, devo dire, devo ringraziarvi perchè mi avete chiarito le idee:

void loop() {
 getOrientation();
 angle = frontDistance - backDistance;
 float previousTime = time;
 time = millis();
 interval = time - previousTime;
 acceleration = velocity * interval;
 motionQuantity = acceleration * mass;
 offset = (targetMotionQuantity - motionQuantity) - (velocity / kV);
      P = angle / kP;
      I = I + (P * interval) / kI;
      D = (angle - previousAngle) / interval / kD;
      float PID = P + I + D;
if(P > 90) P = 90; //stop increase or decrease of the value
if(P < -90) P = -90; //costrizione del valore tra 90 e -90
left.write(90 + PID + offset);
right.write(90 - PID + offset); 
previousAngle = angle;
}

fondamentalmente :

offset = (targetMotionQuantity - motionQuantity) - (velocity / kV);

sottraendo la quantità di moto attuale a quella che si vuole ottenere, si ottiene un valore sempre positivo, finchè non si ha raggiunto la quantità di moto richiesta.
Piu' si andrà veloce piu' si otterrà un offset opposto alla direzione del moto grazie alla sottrazione della prima parentesi che tende a 0 e velocità che aumenta.

Se si richiederà lo stop a velocità 10 e quantità di moto 10 otterremo:
offset = (0 - 10) - (10);, in questo caso un angolo negativo, di conseguenza il robot sarà portaro a rallentare per il continuo sbilanciamento indietro, questo porterà la velocità a diminuire, e la prima parentesi a diminuire fino a giungere a 0. Teoricamente sembra funzionare

Se si richiederà la partenza da fermo:
offset = (10 - 0) - (0); otterremo un angolo positivo, quindi lo sbilanciamento del robot in avanti per evitare il ribaltamento indietro, questo angolo tenderà a 0 o <0 in rapporto alla velocità e alla quantità di moto.

Prendiamo il caso di mantemimento del moto:
offset = (10 - 10) - (10); otterremo un leggero sbilanciamento in negativo in rapporto alla velocità a cui sta andando il robot.

:roll_eyes: ma hai provato? funziona?