Comprendere il sensore GY-521 (giroscopio+accellerometro).. e' dura..

Ciao a tutti! ho aquistato l'accellerometro/gyro GY-521 e devo dire che mi sto ritrovando in una palude di sabbie mobili.. :confused:

Spero che qualcuno di voi abbia esperienze a riguardo e possa aiutarmi perche' non riesco ad uscirne!

Ecco qualche domanda:

  1. Il sensore funziona, riesco ad ottenere i valori "raw" sia dell'accellerometro sia del giroscopio ma ho notato che la spia nel sensore e' rossa e in tutti i video che ho trovato questa spia e' verde.. secondo voi e' tutto ok?

  2. I dati "raw" del giroscopio sono la cosa piu' distante rispetto a dei chiari valori che rappresentino le inclinazioni del sensore nei suoi assi XYZ.. qualcuno sa come trasformare questi valori in valori facilmente utilizzabili per comprendere come e' inclinato il sensore?

  3. Ho letto che per ottenere i dati da me richiesti c'e' da modificare i valori di "rates" (presumo la velocita' di rotazione che viene "sentita" dal giroscopio e c'e' da escludere il "drift"... sapete qualcosa a riguardo? ecco cosa mi hanno scritto nel forum inglese:

You have a rate gyro, which measures the rates at which the sensor is turning, not the orientation angles. You have to integrate the rates to get the angles, but all rate gyros drift, so for accurate results you have to remove the drift first.

Ecco 2 video di persone che sono riusciti ad ottenere perfettamente i dati del giroscopio, tanto da far roteare un oggetto 3D quando si rotea il sensore!:

Grazie in anticipo ragazzi, spero davvero che possiate aiutarmi perche' da solo non credo di avere speranze.

ciao
così su due piedi potrebbero avere cambiato il colore del led, altro hai controllato bene il datasheet soprattutto per quello che riguarda la tensione di alimentazione e la polarità?

Ciao stefa, i collegamenti li ho presi da fonti sicure, tant'e' che il sensore funziona! Oltretutto i valori forniti dall'accellerometro sono perfetti e facilmente comprensibili. Il problema sono i valori del giroscopio che al momento non sono utilizzabili per avere l'inclinazione XYZ del sensore :frowning:
Devono essere a quanto pare interpretati e maneggiati.. solo a quel punto otterrei gli angoli di inclinazione.. purtroppo attualmente non sono in grado :frowning: aiuto..

serve il datasheet e lo sketch che stai utilizzando

aldoz:
Il problema sono i valori del giroscopio che al momento non sono utilizzabili per avere l'inclinazione XYZ del sensore :frowning:

Il giroscopio fornisce la velocità angolare e non l'angolo di inclinazione.
Per ottenere l'assetto dal MPU6050 ti serve, come minimo, un oggetto matematico complesso che si chiama DCM, su Arduino puoi implementare solo questa in quanto la soluzione ottimale, che è l'EKF (Extended Kalman Filter), non è implementabile su Arduino in modo che giri sufficientemente veloce.

ragazzi innanzi tutto grazie davvero per l'aiuto!

allora, lo sketch e il datasheet:

    #include<Wire.h>
    const int MPU=0x68;  // I2C address of the MPU-6050
    int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
    void setup(){
      Wire.begin();
      Wire.beginTransmission(MPU);
      Wire.write(0x6B);  // PWR_MGMT_1 register
      Wire.write(0);     // set to zero (wakes up the MPU-6050)
      Wire.endTransmission(true);
      Serial.begin(9600);
    }
    void loop()
    {
      Wire.beginTransmission(MPU);
      Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission(false);
      Wire.requestFrom(MPU,14,true);  // request a total of 14 registers
      AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    
      AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
      AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
      Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
      GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
      GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
      GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

      Serial.print("AcX = "); Serial.print(AcX);
      Serial.print(" | AcY = "); Serial.print(AcY);
      Serial.print(" | AcZ = "); Serial.print(AcZ);
      Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);  //equation for temperature in degrees C from datasheet
      Serial.print(" | GyX = "); Serial.print(GyX);
      Serial.print(" | GyY = "); Serial.print(GyY);
      Serial.print(" | GyZ = "); Serial.println(GyZ);
      

      delay(333);
    }

DATASHEET:

@astrobeed:
Ahh molto, molto interessante. (in questo momento sembro la scimmia di 2001 odissea nello spazio che tocca il monolite..)
Posso chiederti se questo oggetto matematico DCM e' un modello matematico che posso scrivere da codice giusto?
Praticamente questo oggetto matematico ha il compito di manipolare e convertire i dati grezzi forniti dal sensore in modo da ottenere gradi di rotazione dei 3 assi?

Confermo quanto detto da Astrobeed, anche se pure stavolta non ha specificato che si tratta di giroscopio elettronico e non elettromeccanico. ho anche io accelerometri e giroscopi elettronici, gli accelerometri forniscono una buona lettura, mentre i giroscopi non forniscono un valore assoluto, insomma non ti danno i gradi di inclinazione come quelli elettromeccanici, per semplificarla danno dei riferimenti rispetto alla posizione precedente, piu o meno.

mmm allora, sto piano piano comprendendo.
Ditemi se ci sono vicino:

  1. Questi giroscopi (gy521) calcolano la velocita' angolare del sensore.

  2. La velocita' angolare e' la velocita' con cui un corpo rotea in un asse.

  3. Per trovare quindi i gradi di inclinazione del sensore dovro', utilizzando la velocita' angolare (cioe' la velocita' di rotazione), prendere un lasso di tempo specifico e quindi sapendo che in quel lasso di tempo la velocita' di rotazione era TOT e avendo in precedenza memorizzato la posizione di partenza dell' INIZIO rotazione, arrivero' a sapere "quanta strada ha fatto" il sensore dalla posizione di inizio rotazione al momento attuale; cioe' di quanti gradi ha roteato.

Ditemi che piu' o meno ci sono per favore.... :fearful:

si

triac60:
anche se pure stavolta non ha specificato che si tratta di giroscopio elettronico e non elettromeccanico

Peccato che ho detto chiaramente MPU6050, il che elimina ogni dubbio, in tutti i casi nel mondo di Arduino non esistono giroscopi meccanici, solo elettronici.

insomma non ti danno i gradi di inclinazione come quelli elettromeccanici,

Nemmeno i giroscopi meccanici forniscono direttamente l'inclinazione, sono dispositivi che tendono a mantenere costante la loro posizione e si oppongono al movimento con una forza legata alla massa e alla velocità di rotazione.
C'è pure il piccolo dettaglio che i giroscopi meccanici quando vengono perturbati su un asse rispondono con uno sfasamento di 90°, si chiama precessione giroscopica, cosa che complica non poco la meccanica per il loro montaggio e rilevazione dei movimenti.

aldoz:

  1. Questi giroscopi (gy521) calcolano la velocita' angolare del sensore.

GY520 è solo il nome della schedina, il sensore vero e proprio è l'MPU6050 di Invensense.

  1. La velocita' angolare e' la velocita' con cui un corpo rotea in un asse.
  1. Per trovare quindi i gradi di inclinazione del sensore dovro',

In pratica dovresti fare l'integrale della velocità angolare per ottenere il valore dell'inclinazione.
Però questo tipo di operazione è da evitare perché l'integrale porta sempre ad un errore cumulativo incrementale, poi c'è il naturale drift dei giroscopi elettronici a introdurre ulteriore errore, in pochi secondi la lettura dell'inclinazione diventa inutilizzale per eccesso di errore.
L'unico modo per ottenere l'assetto su i tre assi con una IMU 6 d.o.f., perché questo è l'MPU6050, è applicare la DCM, su Arduino non c'è altra via praticabile per via della poca potenza di calcolo e la poca ram.
Questo è un esempio di quanto si può ottenere con un MPU6050 e la robustezza della misura in presenza di forti perturbazioni, nel video uso un dsPIC e la E.K.F., con Arduino e la DCM non riesci ad ottenere gli stessi risultati però ti ci puoi avvicinare abbastanza, sicuramente quanto basta per il tuo scopo.

Mamma mia astrobeed il video che hai messo su youtube e' spettacolare ed'e' esattamente cio' che cerco da questo sensore! e seppur stai usando il E.K.F, da quel che dici utilizzando il DCM non si avrebbe un risultato troppo male.

Il discorso del drift che porta ad accumulare errori nei valori e' una cosa che mi mette KO.. per non parlare della complessita' dello scrivere un pezzo di codice che implementi il DCM.......

Scusami se te lo chiedo ma hai per caso un codice che gia' implementa la DCM su arduino e che fornisce dei valori di rotazione dei 3 assi?

Ieri mi sono sbattuto come un tappeto ottocentesco cercando di capire/utilizzare un modello matematico DCM ma la cosa e' realmente al di fuori della mia portata matematico/Cerebrale :frowning:
Avro' fatto una quarantina di prove, una più fallimentare dell'altra...

Ti sarei davvero grato se mi scrivessi giusto un piccolo codice d'esempio, anche brutto e scarno, anche qualcosa di non testato eh, che possa fornirmi questi dannati 3 assi di rotazione.

Intanto ti ringrazio tantissimo per l'aiuto, sto facendo passi da gigante ma devo, purtroppo, fare i conti sopratutto con i miei limiti matematici.. ;ci sto tentando con tutte le mie forze ma, come da titolo, e' dura...

Ce l'ho fatta :slight_smile:

Ecco lo sketch che permette di trasformare i dati grezzi dell'MPU6050 in gradi di rotazione XY e Z!

ho dovuto rimuovere il codice, superavo i 9000 caratteri

Dovete utilizzare la libreria I2Cdev!

Ci mette qualche secondo a inizializzarsi correttamente; dopo qualche secondo i valori rimangono stabili e pronti ad essere modificati da tutte le rotazioni che desiderate :slight_smile:

aldoz:
Ce l'ho fatta :slight_smile:

Bene, comunque se cerchi Arduino MPU6050 trovi abbastanza materiale con tanto di DCM già implementata, sopratutto se cerchi nei software per i multicotteri visto che è una IMU abbastanza utilizzata.

astrobeed:
Bene, comunque se cerchi Arduino MPU6050 trovi abbastanza materiale con tanto di DCM già implementata, sopratutto se cerchi nei software per i multicotteri visto che è una IMU abbastanza utilizzata.

Sisi infatti mi sono messo disperatamente a spulciare codici nei vari tutorials; il problema che molti implementavano l'uso di software esterni (per visualizzare oggetti 3D) che non mi permettevano di capirci una mazza!
Anche nell'utilizzo delle nuove librerie stavo mettendole nel posto sbagliato e continuavo a beccare errori su errori...
Finalmente ora e' tutto ok!

Grazie davvero per le risposte e per le spiegazioni astrobeed, sei stato utilissimo!!

aldoz:
...
ho dovuto rimuovere il codice, superavo i 9000 caratteri
...

Limiti del forum ... se vuoi allegare roba piu grossa, devi zipparla (zip o rar) ed allegarla come file, oppure se e' troppo grossa anche per quello, caricarla su qualche host gratuito esterno e postare il link ...

#include "I2Cdev.h"

#include "MPU6050_6Axis_MotionApps20.h"
//#include "MPU6050.h" // not necessary if using MotionApps include file

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
   #include "Wire.h"
#endif

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
//MPU6050 mpu(0x69); // <-- use for AD0 high

/* =========================================================================
  NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
  depends on the MPU-6050's INT pin being connected to the Arduino's
  external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
  digital I/O pin 2.
* ========================================================================= */

/* =========================================================================
  NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error
  when using Serial.write(buf, len). The Teapot output uses this method.
  The solution requires a modification to the Arduino USBAPI.h file, which
  is fortunately simple, but annoying. This will be fixed in the next IDE
  release. For more info, see these links:

  http://arduino.cc/forum/index.php/topic,109987.0.html
  http://code.google.com/p/arduino/issues/detail?id=958
* ========================================================================= */



// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual
// quaternion components in a [w, x, y, z] format (not best for parsing
// on a remote host such as Processing or something though)
//#define OUTPUT_READABLE_QUATERNION

// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles
// (in degrees) calculated from the quaternions coming from the FIFO.
// Note that Euler angles suffer from gimbal lock (for more info, see
// http://en.wikipedia.org/wiki/Gimbal_lock)
//#define OUTPUT_READABLE_EULER

// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/
// pitch/roll angles (in degrees) calculated from the quaternions coming
// from the FIFO. Note this also requires gravity vector calculations.
// Also note that yaw/pitch/roll angles suffer from gimbal lock (for
// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_YAWPITCHROLL

// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration
// components with gravity removed. This acceleration reference frame is
// not compensated for orientation, so +X is always +X according to the
// sensor, just without the effects of gravity. If you want acceleration
// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.
//#define OUTPUT_READABLE_REALACCEL

// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration
// components with gravity removed and adjusted for the world frame of
// reference (yaw is relative to initial orientation, since no magnetometer
// is present in this case). Could be quite handy in some cases.
//#define OUTPUT_READABLE_WORLDACCEL

// uncomment "OUTPUT_TEAPOT" if you want output that matches the
// format used for the InvenSense teapot demo
//#define OUTPUT_TEAPOT



#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '

, 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };

// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
   mpuInterrupt = true;
}

// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================

void setup() {
   // join I2C bus (I2Cdev library doesn't do this automatically)
   #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
       Wire.begin();
       TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
   #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
       Fastwire::setup(400, true);
   #endif

// initialize serial communication
   // (115200 chosen because it is required for Teapot Demo output, but it's
   // really up to you depending on your project)
   Serial.begin(115200);
   while (!Serial); // wait for Leonardo enumeration, others continue immediately

// NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
   // Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
   // the baud timing being too misaligned with processor ticks. You must use
   // 38400 or slower in these cases, or use some kind of external separate
   // crystal solution for the UART timer.

// initialize device
   Serial.println(F("Initializing I2C devices..."));
   mpu.initialize();

// verify connection
   Serial.println(F("Testing device connections..."));
   Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  // wait for ready
   Serial.println(F("\nSend any character to begin DMP programming and demo: "));
   while (Serial.available() && Serial.read()); // empty buffer
   while (!Serial.available());                 // wait for data
   while (Serial.available() && Serial.read()); // empty buffer again

   // load and configure the DMP
   Serial.println(F("Initializing DMP..."));
   devStatus = mpu.dmpInitialize();

   // supply your own gyro offsets here, scaled for min sensitivity
   mpu.setXGyroOffset(220);
   mpu.setYGyroOffset(76);
   mpu.setZGyroOffset(-85);
   mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

   // make sure it worked (returns 0 if so)
   if (devStatus == 0) {
       // turn on the DMP, now that it's ready
       Serial.println(F("Enabling DMP..."));
       mpu.setDMPEnabled(true);

       // enable Arduino interrupt detection
       Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
       attachInterrupt(0, dmpDataReady, RISING);
       mpuIntStatus = mpu.getIntStatus();

       // set our DMP Ready flag so the main loop() function knows it's okay to use it
       Serial.println(F("DMP ready! Waiting for first interrupt..."));
       dmpReady = true;

       // get expected DMP packet size for later comparison
       packetSize = mpu.dmpGetFIFOPacketSize();
   } else {
       // ERROR!
       // 1 = initial memory load failed
       // 2 = DMP configuration updates failed
       // (if it's going to break, usually the code will be 1)
       Serial.print(F("DMP Initialization failed (code "));
       Serial.print(devStatus);
       Serial.println(F(")"));
   }

   // configure LED for output
   pinMode(LED_PIN, OUTPUT);
}



// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop() {
   // if programming failed, don't try to do anything
   if (!dmpReady) return;

   // wait for MPU interrupt or extra packet(s) available
   while (!mpuInterrupt && fifoCount < packetSize) {
       // other program behavior stuff here
       // .
       // .
       // .
       // if you are really paranoid you can frequently test in between other
       // stuff to see if mpuInterrupt is true, and if so, "break;" from the
       // while() loop to immediately process the MPU data
       // .
       // .
       // .
   }

   // reset interrupt flag and get INT_STATUS byte
   mpuInterrupt = false;
   mpuIntStatus = mpu.getIntStatus();

   // get current FIFO count
   fifoCount = mpu.getFIFOCount();

   // check for overflow (this should never happen unless our code is too inefficient)
   if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
       // reset so we can continue cleanly
       mpu.resetFIFO();
       Serial.println(F("FIFO overflow!"));

   // otherwise, check for DMP data ready interrupt (this should happen frequently)
   } else if (mpuIntStatus & 0x02) {
       // wait for correct available data length, should be a VERY short wait
       while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

       // read a packet from FIFO
       mpu.getFIFOBytes(fifoBuffer, packetSize);
       
       // track FIFO count here in case there is > 1 packet available
       // (this lets us immediately read more without waiting for an interrupt)
       fifoCount -= packetSize;

       #ifdef OUTPUT_READABLE_QUATERNION
           // display quaternion values in easy matrix form: w x y z
           mpu.dmpGetQuaternion(&q, fifoBuffer);
           Serial.print("quat\t");
           Serial.print(q.w);
           Serial.print("\t");
           Serial.print(q.x);
           Serial.print("\t");
           Serial.print(q.y);
           Serial.print("\t");
           Serial.println(q.z);
       #endif

       #ifdef OUTPUT_READABLE_EULER
           // display Euler angles in degrees
           mpu.dmpGetQuaternion(&q, fifoBuffer);
           mpu.dmpGetEuler(euler, &q);
           Serial.print("euler\t");
           Serial.print(euler[0] * 180/M_PI);
           Serial.print("\t");
           Serial.print(euler[1] * 180/M_PI);
           Serial.print("\t");
           Serial.println(euler[2] * 180/M_PI);
       #endif

       #ifdef OUTPUT_READABLE_YAWPITCHROLL
           // display Euler angles in degrees
           mpu.dmpGetQuaternion(&q, fifoBuffer);
           mpu.dmpGetGravity(&gravity, &q);
           mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
           Serial.print("ypr\t");
           Serial.print(ypr[0] * 180/M_PI);
           Serial.print("\t");
           Serial.print(ypr[1] * 180/M_PI);
           Serial.print("\t");
           Serial.println(ypr[2] * 180/M_PI);
       #endif

       #ifdef OUTPUT_READABLE_REALACCEL
           // display real acceleration, adjusted to remove gravity
           mpu.dmpGetQuaternion(&q, fifoBuffer);
           mpu.dmpGetAccel(&aa, fifoBuffer);
           mpu.dmpGetGravity(&gravity, &q);
           mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
           Serial.print("areal\t");
           Serial.print(aaReal.x);
           Serial.print("\t");
           Serial.print(aaReal.y);
           Serial.print("\t");
           Serial.println(aaReal.z);
       #endif

       #ifdef OUTPUT_READABLE_WORLDACCEL
           // display initial world-frame acceleration, adjusted to remove gravity
           // and rotated based on known orientation from quaternion
           mpu.dmpGetQuaternion(&q, fifoBuffer);
           mpu.dmpGetAccel(&aa, fifoBuffer);
           mpu.dmpGetGravity(&gravity, &q);
           mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
           mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
           Serial.print("aworld\t");
           Serial.print(aaWorld.x);
           Serial.print("\t");
           Serial.print(aaWorld.y);
           Serial.print("\t");
           Serial.println(aaWorld.z);
       #endif
   
       #ifdef OUTPUT_TEAPOT
           // display quaternion values in InvenSense Teapot demo format:
           teapotPacket[2] = fifoBuffer[0];
           teapotPacket[3] = fifoBuffer[1];
           teapotPacket[4] = fifoBuffer[4];
           teapotPacket[5] = fifoBuffer[5];
           teapotPacket[6] = fifoBuffer[8];
           teapotPacket[7] = fifoBuffer[9];
           teapotPacket[8] = fifoBuffer[12];
           teapotPacket[9] = fifoBuffer[13];
           Serial.write(teapotPacket, 14);
           teapotPacket[11]++; // packetCount, loops at 0xFF on purpose
       #endif

       // blink LED to indicate activity
       blinkState = !blinkState;
       digitalWrite(LED_PIN, blinkState);
   }
}

Ciao Etemenanki, si ho tagliato la testa al toro e ho messo il codice diviso in 2 post.
Per tutti coloro che vogliono avere gli angoli XYZ dai dati grezzi del sensore!

ps: complimenti all'autore di questo codice!!

Ciao a tutti,
sto usando due imu mpu6050 e non ho grossi problemi per quanto riguarda la rotazione del sensore..
in pratica utilizzo il DCM e importo i quaternioni su Unity in modo da vedere graficamente la rotazione del mio sensore.
Il mio desiderio è quello di vedere anche lo spostamento del mio sensore, in linea teorica potrei integrare due volte l'accelerazione per avere una misura dello spostamento ma in linea pratica come posso comportarmi?
Esistono librerie per integrare? sono sufficientemente precise? il mio progetto prevede che si possano riconoscere spostamenti nell'ordine di 1cm.
Grazie mille