Frecuencia de muestreo Acelerómetro MPU6050

Buen día a toda la comunidad.

He intentado soluciona por varias semanas un problema que tengo con la frecuencia de muestreo del acelerómetro MPU6050 en mi proyecto sin buenos resultados. La idea del proyecto es poder tomar valores de aceleración (X,Y,Z) y tiempo(t), enviarlos por el puerto serie al PC y desde ahí procesar esa información con Python. Hasta acá todo bien, sin embargo, el tiempo de muestreo (dt) máximo que he obtenido es de 1.8milisegundos (frecuencia más o menos de 500hz) utilizando el MPU6050 y arduino uno, en el datasheet del acelerómetro dice que puede llegar a una frecuencia de 1000Hz, pero no he logrado ese valor.

El sketch que estoy utilizando para medir el tiempo es este:

#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"
MPU6050 sensor;
int ax, ay, az;
void setup() {

  Serial.begin(250000);
  Wire.begin();
  sensor.initialize();

  if (sensor.testConnection()) Serial.println("Sensor iniciado correctamente");
  else Serial.println("Error al iniciar el sensor");
  muestreo();
}

void loop() {
}

void muestreo() {
  unsigned long time1 = 0;
  unsigned long time = 0;
  Serial.println("*************************");
  Serial.println("    TIEMPO DE MUESTRO:");
  Serial.println("Tiempo(µs);  ax ; ay ; az; dt(µs)"); //
  Serial.println("*************************");
  for (byte i = 0; i < 10; i++) {

    time1 = micros();
    sensor.getAcceleration(&ax, &ay, &az);
    Serial.print(   (String)micros() + ";  " +  (String)ax + ";  " + (String)ay + ";  " + (String)az);
    time = micros() - time1;
    Serial.print("        Muestra: ");
    Serial.print(i + 1);
    Serial.print(" Tiempo: ");
    Serial.println(time);
  }
}

El resultado arrojado en el monitor serie es:

`yX.6XNg>⸮<NHhNH8Sensor iniciado correctamente
*************************
    TIEMPO DE MUESTRO:
Tiempo(µs);  ax ; ay ; az; dt(µs)
*************************
8208;  -16124;  224;  8        Muestra: 1 Tiempo: 1804
10568;  -16132;  216;  -44        Muestra: 2 Tiempo: 1844
13000;  -16072;  188;  -112        Muestra: 3 Tiempo: 1880
15424;  -16044;  200;  -8        Muestra: 4 Tiempo: 1836
17828;  -16136;  264;  4        Muestra: 5 Tiempo: 1820
20240;  -16112;  244;  -104        Muestra: 6 Tiempo: 1880
22676;  -16092;  152;  68        Muestra: 7 Tiempo: 1852
25084;  -16192;  292;  40        Muestra: 8 Tiempo: 1848
27500;  -16076;  252;  -28        Muestra: 9 Tiempo: 1864
29948;  -15992;  140;  128        Muestra: 10 Tiempo: 1876

Agradecería que me ayudaran con lo siguiente:

  1. ¿Cómo llegar a una frecuencia de toma de datos de 1000Hz con el arduino uno y el MPU6050?
  2. ¿quisiera que mi proyecto realice lecturas de aceleración cada 0.25 milisegundos (frecuencia cercana a 4000Hz=4kHz), que acelerómetro y placa arduino me recomiendan para obtener esta frecuencia?
    Mil gracias por su tiempo

A como lo tienes, la medición de tiempo es errónea ya que estás capturando una instancia de tiempo durante un proceso tan laborioso como la concatenación. Un resultado más realista sería:

void muestreo() {
  unsigned long ptime;
  unsigned long ctime;
  Serial.println("*************************");
  Serial.println("    TIEMPO DE MUESTRO:");
  Serial.println("Tiempo(µs)\t\tax\t\tay\t\taz\t\tdt(µs)"); //
  Serial.println("*************************");
  for (byte i = 0; i < 10; i++) {

    ptime = micros();
    sensor.getAcceleration(&ax, &ay, &az);
    ctime = micros();
    Serial.print((String)ctime + "\t\t" + ax + "\t\t" + ay + "\t\t" + az);
    Serial.print("\t\tMuestra: ");
    Serial.print(i + 1);
    Serial.print(" Tiempo: ");
    Serial.println(ctime - ptime);
  }
}

Si esta manera aún no te satisfacen los resultados, deberías primero revisar la hoja de datos del integrado para ver la frecuencia máxima del reloj (SCL) que soporta, para así configurarla en el Arduino acorde a dicho valor (asumiendo que por lo menos haya un registro para eso).

Si aún yendo a tope no te satisface para 1 o 4 KHz; puede que más bien sea necesario un integrado con interfaz SPI. Cuando el protocolo I2C es el cuello de botella, aumentar el poder de procesamiento no ayuda en nada.

Lucario448 muchas gracias por tu respuesta, he probado el código que me has suministrado y me ha arrojado el siguiente resultado:

`yxXN'^+⸮hhNH80o⸮Z⸮⸮-⸮⸮$⸮!&J%J⸮Z⸮⸮J⸮7^⸮(>⸮ZDz-⸮J$⸮
\^⸮J^~⸮Z&/J%jX⸮;⸮
4⸮⸮⸮a&_oJ%J⸮-⸮⸮z⸮⸮*7^⸮h~⸮ZDZI⸮J⸮:$⸮!&
J%J⸮Z⸮⸮-⸮⸮$⸮!&J%J⸮Z⸮⸮J⸮7^⸮(>⸮ZDz-⸮J$⸮
\^⸮J^~⸮ZSensor iniciado correctamente
*************************
    TIEMPO DE MUESTRO:
Tiempo(µs) ax ay az dt(µs)
*************************
7844 -15024 5884 0 Muestra: 1 Tiempo: 1020
10036 -15052 5868 28 Muestra: 2 Tiempo: 1012
12284 -14972 5912 -88 Muestra: 3 Tiempo: 1004
14556 -14944 5908 -164 Muestra: 4 Tiempo: 1016
16844 -15052 5904 -72 Muestra: 5 Tiempo: 1016
19108 -15012 5880 16 Muestra: 6 Tiempo: 1020
21312 -15104 5884 -168 Muestra: 7 Tiempo: 1016
23540 -15092 5916 36 Muestra: 8 Tiempo: 1028
25736 -15068 5880 80 Muestra: 9 Tiempo: 1008
27920 -15096 5932 40 Muestra: 10 Tiempo: 1012

De esto observo que el tiempo que dura en leer los datos (dt) es de ≈1000µs, al igual como lo indica el datasheet del MPU6050(1KHz), hasta acá todo bien y descarto que sea el sensor dado que está dando el máximo, pero de la primera columna (Tiempo) me indica que el tiempo entre una impresión (en el puerto serial) de un dato y otro es de ≈2200µs, por consiguiente, entiendo que la impresión dura ≈1200µs y la toma del dato dura ≈1000µs.

Si se considera lo anterior yo estaría perdiendo 1200µs en la toma de datos, ¿podría reducir este tiempo? ¿O se puede guardar un conjunto de datos para luego imprimirlos?(soy muy novato todavia). Lo que necesito es que me tome la mayor cantidad de conjunto de datos (tiempo-t y aceleraciones-ax-ay-az), la impresión en puerto serial puede ser al finalizar la toma de datos, que puede tardar 0.5 o 1 segundos y una cantidad de conjunto de datos de 500 o 1000 respectivamente.

También he pensado conectarlo por SPI, pero la verdad no encuentro información (soy novato :sob: :sob: ), tú me podrías indicar como conectarlos o un link donde lo expliquen para guiarme.

Por ultimo tu sabes por qué me aparecen caracteres raros al iniciar la impresión de datos

De antemano muchas gracias

Elimina tanto envio de datos por puerto serie. Agrupa información en un buffer y la envias de una vez.

El punto optimo habrá que determinarlo.

Conectarlo por SPI no es posible. Debes considerar otro MPU para tal tarea, este solo es I2C. Ese punto lo investigué en su momento.
El que si puedes usar por SPI es el MPU9250 y la prueba es que hay librerìa MPU9250 SPI

Asi que si tu problema es velocidad, entonces no pierdas tiempo y apunta a este modelo.

Gracias por tu respuesta surbyte, tú me podrías explicar acerca de “Agrupa información en un buffer y la envías de una vez” o algún sitio donde lo expliquen, la verdad soy muy nuevo en esto.

El código original (el primero que publique) lo he modificado, almacenando los valores en un array para cada dato (t-ax-ay-az) y luego imprimirlos, sin embargo, la memoria del Arduino UNO me deja almacenar solo ≈100 valores, he intentado obtener estos 100 valores, luego imprimirlos, borrar contenido y volver a realizar el ciclo, pero cunado imprime de demora ≈100000µs y pierdo ese tiempo de adquisición de datos. ¿Cómo podría solucionarlo?, el código modificado es este:

#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"
MPU6050 sensor;
int ax, ay, az;

long vectorT[100];
int vectorAX[100];
int vectorAY[100];
int vectorAZ[100];
void setup() {

  Serial.begin(250000);
  Wire.begin();
  sensor.initialize();

  if (sensor.testConnection()) Serial.println("Sensor iniciado correctamente");
  else Serial.println("Error al iniciar el sensor");
  Serial.println("*************************");
  Serial.println("    TIEMPO DE MUESTRO:");
  Serial.println("Tiempo(µs)\t\tax\t\tay\t\taz\t\tdt(µs)"); //
  Serial.println("*************************");
  for (byte i = 0; i < 5; i++) {
    muestreo();
    for (byte i = 0; i < 99; i++) {
      Serial.print(vectorT[i]);
      Serial.print("\t");
      Serial.print(vectorAX[i]);
      Serial.print("\t");
      Serial.print(vectorAY[i]);
      Serial.print("\t");
      Serial.println(vectorAZ[i]);
    }
    memset(vectorT, 0, sizeof(vectorT)); // borra el array
  }
}

void loop() {
}

void muestreo() {
  for (byte i = 0; i < 99; i++) {
    sensor.getAcceleration(&ax, &ay, &az);
    vectorT[i] = micros();
    vectorAX[i] = ax;
    vectorAY[i] = ay;
    vectorAZ[i] = az;
  }
}

Lo del tiempo se puede observar en la imagen adjunta, la de color azul representa los microsegundos

por ultimo sensor el gy-91 mpu 9250, sirve con la librería que mencionas, es el único modelo que puedo conseguir donde vivo

de antemano gracias por tu colaboracion