Esp32 e mpu6050 per inclinometro - non torna a zero dopo alcune rotazioni

Buongiorno a tutti!

stavo cercando di realizzare un inclinometro usando un mpu6050 moltiplicando la velocità angolare per il tempo di esecuzione dell'istruzione, in modo da ottenere la posizione.

il processo avviene dopo una taratura iniziale in quanto l'accelerometro mostra una velocità angolare diversa da zero pur essendo completamente immobile. Dopo la taratura, il sensore mantenuto fermo consente al programma di restituire effettivamente un angolo di inclinazione nullo fino a che non avviene una rotazione.
Se però dopo una serie di rotazioni il sensore viene nuovamente lasciato immobile, segna un valore molto diverso rispetto a quello che aveva prima delle rotazioni, da fermo: dopo sole quattro rotazioni, da 0° il programma restituisce -41°.

Secondo voi come posso sistemare?

int i =0;
float az0=0;
float t= 0;
float k=0;
Serial.print("Calcolo valore medio =");
for (i=0;i<5000;i++){
  mpu.getEvent(&a, &g, &temp);
  az0=az0+g.gyro.z;
}
az0/=5000;
Serial.println(az0,12);
delay(7000);
while(1){

  t = micros();
  mpu.getEvent(&a, &g, &temp);
 
  angolo_z=angolo_z+(g.gyro.z-az0)*(micros()-t)/1000000/1.5*90;
  Serial.print("\t\t angolo z = ");
  Serial.println(angolo_z,10);

  myservo.write(angolo_z+90);
// Servo motor pin
}

Grazie mille!

Mah, non so, non capisco bene come tu voglia ricavare l'angolo dal giroscopio usando un approccio "inerziale"...

Però prima chiarisci bene di quale sensore parliamo: magari se avessi un link all'esatto articolo sarebbe meglio, perché credo che ce ne siano di vari tipi con caratteristiche diverse.

Ad esempio io da qualche parte dovrei avere ancora un modulo che usa l'MPU56050 (dovrei cercare ma non prima di stasera) forse un GY521 se non ricordo male, che usava l'I2C. Dato che tu poi hai postato solo uno spezzone di codice non sappiamo né quale libreria hai usato né quale sia esattamente il tipo di sensore...

Ciao e grazie per la risposta!
Hai perfettamente ragione: ho usato un MPU6050 montato su un modulo GY521 e nel programma lo gestisco tramite la libreria di Adafruit, Adafruit_MPU6050 (GitHub - adafruit/Adafruit_MPU6050: Arduino library for MPU6050).

L'idea era quella di usare la variazione di velocità angolare tramite integrazione:

ho la velocità angolare ω = dα / dt , lo moltiplico per dt e dovrei ottenere la variazione dell'angolo di inclinazione avvenuta nell'intervallo dt. Sommandola alla variazione precedente, dovrei ottenere l'angolo di inclinazione del sensore una volta trascorsa una somma di dt, ovvero in qualunque istante successivo alla calibrazione del sensore.

Ho visto però che occorre utilizzare un filtro complementare (me l'ha suggerito chat GPT), così ho modificato il codice aggiungendo tra i parametri anche l'angolo tra l'accelerazione di gravità e il sensore calcolato come l'arcotangente della prima fratto la seconda ed ora sembrerebbe funzionare.

ecco il codice:

currentTime = micros();
  dt = (currentTime - previousTime) / 1000000.0;
  previousTime = currentTime;

  // Ottieni i dati del sensore
  mpu.getEvent(&a, &g, &temp);

  // Integrazione della velocità angolare del giroscopio
  gyroAngoloZ += (g.gyro.z - az0) * dt;

  // Calcolo dell'angolo con l'accelerometro (per la stabilità a lungo termine)
  accAngoloZ = atan2(a.acceleration.x, a.acceleration.z) * 180 / PI;

  // Filtro complementare
  angolo_z = alpha * (angolo_z + (g.gyro.z - az0) * dt) + (1.0 - alpha) * accAngoloZ;

  // Stampa dell'angolo calcolato
  Serial.print("\t\t angolo z = ");
  Serial.println(angolo_z, 10);

// Movimento del servo in base all'angolo
  myservo.write(angolo_z);

L?unico problema è che il servo "impazzisce": reagisce in ritardo alla rotazione del sesore, fa dei piccoli scatti anche se il sensore esegue un movimento fluido e, soprattutto, inizia a girare di 360° continuamente (come fosse un semplice motore, per intenderci) nonostante l'angolo che viene passato alla funzione myservo.write() della libreria ESP32Servo sia sempre compreso tra 0 e 180 (lo vedo da seriale).

Quindi è un servo a rotazione continua, i normali servo si fermano alle 2 estremità.

Per quel tipo di servo non decidi l'angolo con il parametro, ma il verso e la velocità.

Ciao, Ale.

Si ma per favore, in un progetto si dovrebbero descrivere (magari con link all'esatto articolo acquistato) TUTTI i componenti che usi: di quale servo stiamo parlando esattamente? Se dici che gira continuamente è, come ha detto giustamente @ilguargua, uno a rotazione continua quindi lo devi gestire in modo diverso, oppure devi cambiare servo...

A parte questo discorso dei 360 gradi, scusa se lo chiedo, hai detto che devi realizzare un "inclinometro" ma per quale applicazione pratica ti serve questa cosa? Perché dalla tua descrizione mi sembra che tu voglia realizzare qualcosa che è abbastanza comune, ossia un gimbal, un qualcosa che in base all'inclinazione rilevata vada a muovere un servo per "fare qualcosa" (ovviamente dipende dall'algoritmo che implementi, ossia muovere il servo di un verto valore partendo dall'angolo rilevato). Se così fosse perché non vedi i vari progetti che ci sono in giro, tipo questo (ma non è l'unico, e poi per descrizioni migliori puoi cercare anche su Instructables)?

Ringrazio entrambi per le risposte, siete stati molto gentili.
Il servocomando che sto usando è un SG90 e non dovrebbe essere a rotazione continua, quindi il fatto che in condizioni non così facilmente regolari e riproducibili si comporti come se lo fosse è uno dei motivi per cui vi ho chiesto, perplesso, delucidazioni in questa discussione :slight_smile:
in contesti più in controllo, invece, si comporta normalmente: imposto, ad esempio, un angolo tramite seriale e il servo compie la rotazione per raggiungerlo.

Il sistema che sto realizzando è analogo a questo:

Curiosamente, comunque, con il codice inviato sopra il servo mi pare che si muova più lentamente rispetto a prima nonostante le istruzioni che precedono quella della sua rotazione all'interno del while() vengano eseguite sempre in meno di 30 microsecondi, quindi credo sia abbastanza trascurabile

Confermo, è un servo a 180 gradi.

No, non può fisicamente andare oltre i 180 gradi dalla partenza, quindi spiega cosa intendi con "come se lo fosse". O non è proprio così e a te sembrava andasse a ruotare, oppure quel servo è difettoso ossia non ha lo stop meccanico (rotto? hackerato?) e quindi dovresti cambiarlo.
Nel caso fai uno sketch che lo muove avanti e indietro da 0 a 180 gradi, e vedi che succede (nel caso fai un piccolo video e postaci qui il link). Una cosa tipo questa (presa da un mio vecchio test di anni fa...):

/* 
Collegare il servo:
Marrone <--> GND
Rosso <--> 5V
Arancione <-->Pin 9
*/
#include <Servo.h> 
 
Servo servo;
 
int pos = 0;    // variable to store the servo position 
 
void setup() 
{ 
  Serial.begin(9600);
  servo.attach(9);
  servo.write(0);
} 
 
void loop() 
{ 
  delay(1000);
  for(pos = 0; pos <= 180; pos += 2)
  {
    servo.write(pos);
    delay(15);
  } 
  for(pos = 180; pos>=0; pos-=2)
  {                                
    servo.write(pos);
    delay(15);
  } 
}

Se il servo gira dalla posizione 0 a 180 gradi (metti una delle asticelle in plastica per vedere la posizione) e viceversa e senza cambiare spostamenti strani, ok, se invece ne va "per cavoli suoi", ha qualche problema.
Una volta capito il funzionamento del servo e verificato che risponde al comando, puoi iniziare a pensare al programma vero e proprio e quindi fare i calcoli che occorrono.

Ho visto il video, ed in pratica è lo stesso principio del gimbal, per cui in base all'assetto (ossia l'inclinazione su un asse) devi muovere il servo di conseguenza per bilanciare l'aereo. Ovviamente la tua posizione iniziale sarà 90 gradi, e non credo che arriverai mai a 0 o a 180, i movimenti saranno comunque relativamente leggeri, forse sui 10-15 gradi secondo me.
Non ho mai realizzato una cosa del genere quindi potrei trascurare qualche aspetto che mi sfugge, ma non so perché abbia fatto (e tu stia facendo) tutti quei calcoli, una volta ottenuta l'inclinazione (come per i gimbal) io credo che l'unico eventuale parametro sia un fattore di moltiplicazione della distanza dall'assetto orizzontale, per muovere quello che in un aereo classico di fatto è lo stabilizzatore.

In ogni caso allegato al video ci sono anche tutti i sorgenti, se carichi quelli (eventualmente adattando la configurazione dei pin ad esempio) ti funziona o no?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.