aiuto pratico self balancing robot.

Buongiorno a tutti!
Vorrei chiedere un favore grandissimo: vorrei chiedere se qualcuno con esperienza su PID, arduino, ed ancora meglio su robot autobilancianti potesse darmi un aiuto pratico per riuscire finalmente a fare stare "in piedi" in pseudoequilibrio il mio robot self_balancing di cui vi allego una foto :slight_smile:

è davvero molto tempo che cerco di settare con cognizione di causa i parametri che concorrono alla non riuscita del progetto... Ma fin ora non sono ancora riuscito ad ottenere risultati quantomeno decenti purtroppo =( =(

Quindi chiedo a voi... Se a qualcuno, che abita o si trova nelle vicinanze di Milano o Monza avesse voglia di darmi una mano ci potremmo incontrare e magari anche bere un bel caffè insieme...
Sono davvero disperato, più volte ho postato il codice in cerca di un aiuto ma non ho mai ricevuto risposte =(
Io sono in periodo esami in università quindi sarei libero anche al mattino; se qualcuno fosse interessato, lo ringrazio moltissimo fin da adesso.

Grazie mille per la pazienza, e ciao a tutti :%

Phanto:
Vorrei chiedere un favore grandissimo: vorrei chiedere se qualcuno con esperienza su PID, arduino, ed ancora meglio su robot autobilancianti potesse darmi un aiuto pratico per riuscire finalmente a fare stare "in piedi" in pseudoequilibrio il mio robot self_balancing di cui vi allego una foto :slight_smile:

In effetti non è una cosa risolvibile con dei post su un forum, il problema è abbastanza complesso, che sensori utilizzi per la IMU ?
Hai calcolato/stimato la costante di tempo del robot ?
Senza questa il pid non lo regolerai mai, sopratutto il pid è implementato nel corretto modo ?

Ciao Astrobeed!
leggere il tuo messaggio di aiuto mi riempie di speranza x_x
la IMU che utilizzo è la MPU-6050 che inoltre tu stesso mi consigliasti in fase di progettazione/acquisto componenti :slight_smile:

Per quanto riguarda la stima della costante di tempo, temo di non averla stimata =( posso chiederti meglio cosa si intende per costante di tempo?
Inoltre non so davvero come comprendere se il PID è implementato nel corretto modo... Ho studiato la teoria sia del sistema idealizzato del pendolo inverso; sia compreso il funzionamento del controllore PID; inoltre mi sono confrontato con molti altri sketch volti allo stesso scopo; e questo penso mi abbia permesso di implementare il PID nel modo corretto... Tuttavia... Alla tua domanda :"il pid è implementato nel corretto modo ?" non risponderei di si giocandomi una mano sul fuoco =(

qui sotto allego il codice se può servire:

Ti ringrazio molto per la tua risposta.

P.S.

Nello sketch è inizializzato anche un magnetometro (GY-271) che servirà per svolgimenti futuri; ma che al momento non è utilizzato xD

Self_Balancing_Robot_ver4_sperimentale.ino (11.1 KB)

Phanto:
la IMU che utilizzo è la MPU-6050 che inoltre tu stesso mi consigliasti in fase di progettazione/acquisto componenti :slight_smile:

Perfetto :slight_smile:

Per quanto riguarda la stima della costante di tempo, temo di non averla stimata =( posso chiederti meglio cosa si intende per costante di tempo?

Puoi ottenerla in due modi, analiticamente o strumentalmente, il secondo modo è quello più semplice.
La costante di tempo, semplificando al massimo la cosa, è il tempo che il robot ci mette per cadere sdraiato partendo dalla posizione verticale a 90*, la puoi misurare facilmente con Arduino, usa la micros() come base dei tempi, due switch per dare lo start e stop, ovviamente azionati dal movimento della caduta.
Quando hai ottenuto la costante di tempo il pid deve lavorare con un periodo di almeno 1:20, ma non superiore a 1:50 altrimenti vai facilmente in overshoot , del valore calcolato/trovato.
Esempio pratico se la costante di tempo vale 65ms (valore abbastanza realistico) il pid deve lavorare con un periodo non maggiore di 3.25 ms e non minore di 1.3 ms.
Attualmente quanto dura il periodo del tuo pid ?
Sopratutto è costante senza jitter ?

grazie astrobeed, sei davvero gentilissimo!
Procedo a raccogliere i dati che mi hai chiesto e ti faccio sapere!
Grazie

Eccomi, mi sono cimentato nella raccolta dati richiesti;
ho creato un sistema con due endstops uno posizionato nella condizione di equilibrio del robot; ed uno posizionato esattamente alla fine della caduta; in modo che l'angolo di arrivo sia 0/1 grado.
lo sketch che sono riuscito a scrivere è questo; (esisteranno sicuramente modi migliori di scriverlo; ma tutto sommato svolge egregiamente il suo scopo) :slight_smile:

float TempoCaduta;
void setup() {
  Serial.begin(9600);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
  
}
 
void loop() {
  ancoraqui:
      int sensorValue1 = digitalRead(8);

      if (sensorValue1 == 1){ 
      goto ancoraqui;
      }
                                   
      if (sensorValue1 == 0){ 
      float  StartTime = micros(); 
      int sensorValue1 = digitalRead(8);
            if (sensorValue1 == 0){
            goto ancoraqui;}
            if (sensorValue1 == 1){
            qui: 
            int sensorValue1 = digitalRead(8);
            int sensorValue2 = digitalRead(9);
            if (sensorValue1 == 0){
            goto ancoraqui;}
                       if (sensorValue2 == 1){
                       float EndTime = micros();
                       TempoCaduta = (EndTime-StartTime);
               
                       
                       Serial.println(TempoCaduta );
                       delay(5000); } //caduto il robot piccola pausa
                       if (sensorValue2 == 0){
                       goto qui;}
                       
}
}
}

Il senso è che: il robot rimanendo fermo preme un endstop che rimane in quella condizione finchè il robot non declina di circa mezzo grado verso la caduta; cambia così lo stato del pin 8 ed inizia il conteggio in microsecondi; il quale viene interrotto con la caduta, quando il robot impatta contro l'altro endstop; collegato al pin9.
Ritengo di aver costruito un sistema sufficientemente stabile; e ne sono prova i risultati molto coerenti fra loro :slight_smile:
Risultati:
1171432.00
1202112.00
1219104.00
1352032.00
1134592.00
1010592.00
1113536.00
1183552.00
1139712.00
1064916.00
1009656.00
1045072.00

la cui media è: 1132978 microsecondi. che quindi possiamo assumere come "costante di tempo".

Ho poi modificato lo sketch che fin ora stavo adoperando sul robot stesso, e che ho allegato qualche messaggio fa, in modo che stampasse sul serialmonitor il valore "intervallo" (in microsecondi però) che rappresenta il tempo impiegato da Arduino per compiere un intero ciclo; tale valore è risultato assumere valori fra 17 e 19 microsecondi; .con un campione di 1000 valori, la media è risultata essere 17,78696 microsecondi.

Quindi... Uhm... con costante di tempo di 1'132'978 microsecondi... Dovrei fare in modo che ogni ciclo duri dai 1132978/50= 22659,56 microsecondi... Ai 1132978/20=56648,9 microsecondi... :fearful: :fearful: :fearful: tutto questo è corretto? Quindi ho un sistema troppo rapido? =( =(

Grazie nuovamente

Il fatto è che non saprei proprio in che modo rallentare la durata di ogni ciclo... (ammesso che sia effettivamente ciò a cui ambire...)
Dovrei inserire un delay da qualche parte? oppure esistono metodi differenti e più... Non so come dire... "fini"?

Mille grazie

Phanto:
Eccomi, mi sono cimentato nella raccolta dati richiesti;

Qualcosa non quadra, una costante di tempo di 1.13 s è decisamente troppo alta, un valore realistico è compreso tra 50 e 100 ms.

Ciao Astro;
ripeterò il sondaggio del tempo di caduta; tuttavia tale tempo so essere dipendente dall'altezza del robot (tanto più è alto, tanto più tempo impiegherà a raggiungere il suolo in caduta) e dalla distribuzione del peso lungo l'altezza del robot... E se pur non ho attuato calcoli teorici che confermino la veridicità dei dati precedentemente raccolti; considerando che il robot ha altezza, (comprese le ruote) di 37cm; e considerando che la maggior parte del peso è distribuita nella parte inferiore del robot (se pur comunque al di sopra del mozzo dei motori) potrebbe così spiegarsi un tempo tanto lungo di caduta?

Ad ogni modo procedo immediatamente a ripetere la raccolta dati.

Grazie per il tuo tempo e per la smisurata gentilezza e disponibilità; te ne sono davvero grato.

Eccomi:
Ho ricostruito il sistema per stimare il tempo impiegato nella caduta; ed ho sostituito entrambi gli endstops.
I risultati mi sembrano, nonostante le variazioni strutturali del sistema, coerenti fra loro e con i dati riscontrati in precedenza; aspettp che, assumendo per corretto lo sketch su arduino, ci consente di affermare che la deviazione è davvero aleatoria; e non dettata da problemi connessi al sistema di misura.

Di seguito i nuovi risultati:

979340
962752
1106144
1096704
965216
1086592
1000416
1137248
1011392
1029504
1062592

Media: 1039809,091 microsecondi;

Media precedente-Media attuale= 1137192,33 - 1039809,09= 97383,24
cioè differiscono di 97 millisecondi.

Proprio per non farsi mancare niente...
Ho provato ad approssimare (parecchio) il problema ed a risolverlo teoricamente; ed il risultato sembrerebbe non negare la durata effettiva riscontrata empiricamente...

Anche credendo senza basi che quello sia il tempo effettivo di caduta; il nostro ?t... Come sistemo lo sketch affinché rispetti le proporzioni che mi hai insegnato qualche post fa? Riusciresti a darmi qualche dritta? sto navigando in un mare di nebbia... Mi basta inserire il delay relativo in modo che ogni ciclo impieghi il tempo voluto a compiersi?

:slight_smile: Grazie mille, spero davvero di riuscire ad insegnare a camminare alla mia "creatura" :slight_smile: :slight_smile: :slight_smile:

Buongiorno a tutti!
Dopo molto tempo provo a fare una domanda un po' più mirata... Riassumendo quanto detto nei post precedenti:

Phanto:
Quindi... Uhm... con costante di tempo di 1'132'978 microsecondi... Dovrei fare in modo che ogni ciclo duri dai 1132978/50= 22659,56 microsecondi... Ai 1132978/20=56648,9 microsecondi... :fearful: :fearful: :fearful: tutto questo è corretto? Quindi ho un sistema troppo rapido? =( =(
...

Assumendo per corretti i ragionamenti antecedenti che ci hanno permesso di raggiungere la tesi che il sistema risponde troppo rapidamente rispetto alle necessità...
Basterebbe agire sulla parte che segue? dove vengono trattate delle frequenze forse? chiedo perhè è una parte che non mi è molto chiara del codice, spero possiate aiutarmi :sob:

Wire.begin();
  TWBR = ((F_CPU / 400000L) - 16) / 2; // Set I2C frequency to 400kHz

  i2cData[0] = 7; // Set the sample rate to 1000Hz - 8kHz/(7+1) = 1000Hz
  i2cData[1] = 0x00; // Disable FSYNC and set 260 Hz Acc filtering, 256 Hz Gyro filtering, 8 KHz sampling
  i2cData[2] = 0x00; // Set Gyro Full Scale Range to ±250deg/s
  i2cData[3] = 0x00; // Set Accelerometer Full Scale Range to ±2g
  while (i2cWrite(0x19, i2cData, 4, false)); // Write to all four registers at once
  while (i2cWrite(0x6B, 0x01, true)); // PLL with X axis gyroscope reference and disable sleep mode

P.S ricordo che lo sketch completo è inserito in uno dei messaggi precedenti

Vi ringrazio oltremodo per l'attenzione,
saluti a tutti

Sono davvero demoralizzato, mi sto dedicando molto alla ricerca dei parametri PID necessari a far permanere in equilibrio il robot, ed è davvero mortificante non riuscire a vedere un minimo miglioramento...
Ho studiato a fondo l'influenza di ciascun suddetto parametro sulla risposta... Ma nel momento della regolazione non riesco a giungere alla condizione di fantomatico "equilibrio dinamico" questo sarebbe solo il punto di partenza dato che poi vorrei inserire molte altre funzioni nel robot...
Quindi vi chiedo...
... Perchè mi sembra davvero l'unica possibilità di apprendere qualcosa ed apportare miglioramenti al progetto giunto a questo punto...

Nessuno del politecnico di Milano o appassionato già cimentatosi in questo mio problema delle zone limitrofe... sarebbe disponibile ad incontrarci un giorno e provare a cercare insieme una soluzione?

Vi ringrazio

Ciao Phanto, non demoralizzarti perchè far stare in piedi un robot non è per niente facile ! Io ci sono riuscito dopo un paio di mesi abbondanti di prove e controprove (Self Balancing Robot 2.0 - YouTube) !!
Comunque complimenti per la struttura meccanica. E' davvero ben fatta !!

Appena posso analizzerò il codice che hai postato ma, nel frattempo, vorrei chiederti alcune cose e fare una considerazione di base:

  • quali sono i valori di coppia e di velocità angolare (RPM) dei motori ?
  • qual è il diametro delle ruote ?

Considerazione di base: un self balancing robot altro non è che un pendolo inverso ovvero un pendolo con il baricentro posto più in alto del punto di rotazione. Il periodo di oscillazione, in entrambi i tipi di pendolo, è sempre proporzionale alla lunghezza del pendolo e contribuisce a dare stabilità (maggiore lunghezza -> maggior periodo -> maggiore stabilità). Nella tua applicazione mi sembra di capire che la batteria si trovi lungo l'asse di rotazione delle ruote. Prova a posizionarla sul ripiano più in alto in modo da alzare il baricentro.

Per la taratura del PID il procedimento euristico è (a parole) abbastanza semplice:

  • comincia con P,I e D pari a zero
  • aumenta P finche la struttura comincia a muoversi
  • aumenta ancora P finchè la struttura entra in oscillazione con periodo costante (reggila con le mani)
  • setta P al 60% del valore precedente
  • aumenta I finchè l'errore a regime tende ad annullarsi (la struttura resta ferma)
  • aumenta ancora I finchè la struttura tende nuovamente ad oscillare
  • riduci I fino a rientrare nei margini di stabilità
  • aumenta leggermente D finchè la risposta del sistema diventa abbastanza veloce e i margini di stabilità sono ancora garantiti

Ciao e ancora complimenti per la costruzione,
Giancarlo

Molto bella la realizzazzione

Giancarlo_De_Viti:
Nella tua applicazione mi sembra di capire che la batteria si trovi lungo l'asse di rotazione delle ruote. Prova a posizionarla sul ripiano più in alto in modo da alzare il baricentro.

Come suggerito posiziona la batteria sul primo ripiano in alto e l'elettronica in quello intermedio. Dovrai allungare i cavi. :wink:

Ragazzi, vi ringrazio moltissimo!
apprezzo moltissimo il vostro aiuto

BUONE NOTIZIEEEEE !!!!

Grazie al vostro aiuto e dopo svariati tentativi sono riuscito nell'intento! ebbene si! sono felicissimo!
il motivo della non riuscita precedente è risultato essere la posizione nella quale avevo allocato il sensore MPU6050; infatti si trovava circa 4 cm al di sopra dell'asse di rotazione delle ruote; (sciocco io, ma non pensavo fosse così rilevante come distanza) ed invece... non appena ho costruito un supportino che tenesse la batteria sotto al primo piano di plexigliass e che mi permetta di fissare saldamente il sensore MPU6050 esattamente in corrispondenza dell'asse di rotazione delle ruote... ECCO FATTO "Artur" :slight_smile: era in grado di reggersi in equilibrio!!! e con qualche aggiustamento ai guadagni del PID tramite i tre potenziometri... eccolo lì, fiero e pochissimo barcollante (oscillazioni di circa 3cm avanti ed indietro) :slight_smile: :slight_smile: :slight_smile: :slight_smile: :smiley: :smiley: ;D ;D ;D :grin: :grin: :grin:

sono felicissimo
a breve mi dedicherò alla fase di programmazione android per poterlo controllare tramite bluetooth; ho conosciuto ieri "App Inventor" ed ora appena trovo un po' di tempo libero mi dedicherò alla sua scoperta

grazie nuovamente a tutti quanti per la grande disponibilità
a presto aggiornamenti

buona giornata :slight_smile: