MPU-6050 convertire accelerazione in mm/s2

Salve a tutti, ho un accelerometro MPU-6050 che utilizzo mediante la libreria MPU5060. Vorrei convertire questo valore in mm/s2. Ho cercato online ma non ho trovato niente di funzionante. Ho cercato di studiare il sistema dei bit per capire cosa è il bit più significativo utilizzato per il valore ma non ci ho capito niente. Potete gentilmente dirmi come effettuare la conversione?

1g = 9,81 m/s^2

Ciao Uwe

Questo lo sapevo, però come faccio la conversione? Come accelerazione ottengo numeri molto elevati, non possono essere in G, qual'è la loro unità di misura?

dai un occhio qui, è il primo che ho trovato. Tu probabilmente leggi i valori raw, che devono essere divisi per un numero dato dal valore di fondo scala che vuoi usare (2,4,8,16g)

Dal datasheet: https://www.cdiweb.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf

  • Digital -output triple-axis accelerometer with a programmable full scale range of ±2g, ±4g, ±8g and ±16g
  • Integrated 16-bit ADCs enable simultaneous sampling of accelerometers while requiring no external multiplexer

a secondo del range selezionato:

Sensitivity Scale Factor AFS_SEL=0 16,384LSB/g AFS_SEL=1 8,192LSB/g AFS_SEL=2 4,096LSB/g AFS_SEL=3 2,048LSB/g

Percui nel range piú sensibile 1g ovvero 9810mm/s^2 corrispondono al numero 16384.

Ciao Uwe

Grazie sono riuscito a portare il valore in G e quindi in mm/s2 grazie ai vostri link migliori di quelli che avevo trovato io. Adesso una piccola domanda che sicuramente avrà una risposta negativa... io vorrei che l'accelerometro rilevasse anche accelerazioni quali una mano poggiata sul tavolo... è possibile aumentare la sua precisione fino a 1G?

Ora, non ho riguardato il datasheet ma a naso ti direi di no. La massima risoluzione ce l'hai settando il fondoscala a 2g. Con un fondoscala a 1g poi non avresti possibilità di misurare accelerazioni superiori a 1g che è appunto l'accelerazione di gravità. Certo se devi misurare accelerazioni piane può avere senso ma parlando in generale no.

Per quanto riguarda la mano fai delle prove, dipende da quanto forte la appoggi al tavolo ;)

Quale accelerometro più preciso e di costi contenuti mi consigli? Comunque ho notato che con i dati non elaborati noto una differenza di circa 20 rispetto alla media di quando non tocco il tavolo. Anche solo scrivendo sulla tastiera noto che il valore subisce una variazione notevole.

Quale accelerometro più preciso e di costi contenuti mi consigli?

sinceramente non saprei, ho sempre usato solo l’MPU6050. Ma cosa devi farci esattamente? Sicuro che non ti basti questo?
Considera anche che i valori raw che leggi sono “sporchi” e vanno trattati con della matematica per poterli utilizzare modo più preciso. L’MPU6050 ha al suo interno un DMP, Digital Motion Processor, che fa questo lavoro. Cerca qualche esempio in rete, tipo TeaPot. Oltre non mi spingo a darti informazioni perchè non ho mai approfondito l’argomento e non voglio dire cose inesatte :wink:

Sto costruendo un sismografo, quindi vorrei fosse in grado di rilevare un colpo sul tavolo visto che anche quelli degli smartphone sono in grado di farlo.

Ma prima non dicevi che anche scrivendo sulla tastiera i valori oscillavano molto?

Oscillano i valori RAW ma una volta elaborati l'accelerazione rimane 0.

Posta il codice

E’ il codice di esempio della libreria:

// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class
// 10/7/2011 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
//      2013-05-08 - added multiple output formats
//                 - added seamless Fastwire support
//      2011-10-07 - initial release

/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2011 Jeff Rowberg

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050.h"

// 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 InvenSense evaluation board)
// AD0 high = 0x69
//MPU6050 accelgyro;
MPU6050 accelgyro(0x69); // <-- use for AD0 high

int16_t ax, ay, az;
int16_t gx, gy, gz;



// uncomment "OUTPUT_READABLE_ACCELGYRO" if you want to see a tab-separated
// list of the accel X/Y/Z and then gyro X/Y/Z values in decimal. Easy to read,
// not so easy to parse, and slow(er) over UART.
#define OUTPUT_READABLE_ACCELGYRO

// uncomment "OUTPUT_BINARY_ACCELGYRO" to send all 6 axes of data as 16-bit
// binary, one right after the other. This is very fast (as fast as possible
// without compression or data loss), and easy to parse, but impossible to read
// for a human.
//#define OUTPUT_BINARY_ACCELGYRO


#define LED_PIN 13
bool blinkState = false;

void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

    // initialize serial communication
    // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
    // it's really up to you depending on your project)
    Serial.begin(38400);

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

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

    // use the code below to change accel/gyro offset values
    /*
    Serial.println("Updating internal sensor offsets...");
    // -76	-2359	1688	0	0	0
    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
    Serial.print("\n");
    accelgyro.setXGyroOffset(220);
    accelgyro.setYGyroOffset(76);
    accelgyro.setZGyroOffset(-85);
    Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
    Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
    Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
    Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
    Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
    Serial.print("\n");
    */

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

void loop() {
    // read raw accel/gyro measurements from device
    accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    // these methods (and a few others) are also available
    //accelgyro.getAcceleration(&ax, &ay, &az);
    //accelgyro.getRotation(&gx, &gy, &gz);

    #ifdef OUTPUT_READABLE_ACCELGYRO
        // display tab-separated accel/gyro x/y/z values
        Serial.print("a/g:\t");
        Serial.print(ax); Serial.print("\t");
        Serial.print(ay); Serial.print("\t");
        Serial.print(az); Serial.print("\t");
        Serial.print(gx); Serial.print("\t");
        Serial.print(gy); Serial.print("\t");
        Serial.println(gz);
    #endif

    #ifdef OUTPUT_BINARY_ACCELGYRO
        Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax & 0xFF));
        Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF));
        Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF));
        Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
        Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
        Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));
    #endif

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

ok così ottieni i valori raw, per arrivare ai g devi dividere come detto prima. Lo zero può saltare fuori se dividi due interi tra loro perchè il risultato viene troncato alla cifra intera. Prova ad utilizzare i fattori di divisione come numeri float, cioè aggiungi uno zero dopo la virgola: 16384.0 ; 8192.0 ecc...

Grazie, così rilevo anche piccolissime vibrazioni. Però non funziona la parte

if (ax > 0.02 or ax < -0.02)
  digitalWrite(13, HIGH):
else
  digitalWrite(13, LOW);

prova così;

if (ax > 0.02 || ax < -0.02) digitalWrite(13, HIGH);

else digitalWrite(13, LOW);

oppure con le graffe

if (ax > 0.02 || ax < -0.02){
 digitalWrite(13, HIGH);
}

else {
digitalWrite(13, LOW);
}

Grazie mille, adesso l'ultima domanda per davvero ;): Come posso dichiarare una variabile in modo che venga accettata con le cifre dopo la virgola? INT non va bene, quale parametro devo utilizzare?

Ti serve una variabile di tipo float

dai un occhio qui

Grazie mille