Estoy usando el BMI055 en mi AVR a través de I2C.
Hoja de datos: enlace
Lo puse en salida filtrada a un ODR de 1000Hz y lo sondeamos cada 1005 us.
Lo puse a 1000deg / s de sensibilidad, a 16 bits de salida. Eso da 32.8 LSB / grado
Estoy leyendo los valores del FIFO en modo bypass.
Ahora, para probar, tengo una función que hace lo siguiente (pseudo):
dt = microseconds passed since last call (around 1000)
scale = 1/32.8/1000000;
deltaANGLE[axis] = dt * scale;
static sum[axis] += deltaANGLE[axis];
Every 1000 calls:
{
print the sums[] to serial;
sum[axis]=0;
}
Habría esperado un poco de ruido y deriva durante 1 segundo (1000 muestras) pero obtendría un valor de compensación de -3 a -11 en los 3 ejes cuando lo tengo en la tabla fija.
También los valores cambian mucho, incluso una corrección promedio no ayudaría mucho
Time dif 995 us
Angles: -9.944047 -9.904691 -10.001564
Time dif 1003 us
Angles: -9.846170 -9.824638 -9.923825
Time dif 998 us
Angles: -5.871545 -5.805600 -5.935478
Time dif 1005 us
Angles: -8.871223 -9.628742 -8.884630
Time dif 1009 us
Angles: -8.874594 -8.875291 -8.956609
Time dif 1007 us
Angles: -5.902205 -5.916657 -5.970954
También me desconcertó que los tres ejes muestren siempre la misma desviación extraña.
Al mover el tablero dentro de la segunda integración, muestra "sobre" el cambio correcto (= -15 grados desde el valor esperado)
Creo que hago algo mal pero no puedo encontrar el problema.
Addon1: Acabo de encontrar que aumentar el tiempo de mi rutina de sondeo reduce significativamente el error. Tengo la ODR configurada a 1000Hz, si me conecto a 500Hz obtengo un nivel de ruido bajo y un resultado bastante preciso. ¿Aunque debería significar que el sensor está saturado en un 50% del tiempo y espera mi encuesta? ¿Puede este ruido ser el resultado de un problema entre mi sondeo y la configuración de ancho de banda / ODR de los sensores?
Addon2: Otras varias horas desperdiciadas. Experimenté con varias configuraciones relacionadas con la tasa de sondeo y el sensor ODR / ancho de banda.
Cuando el sondeo es más rápido que la ODR, obtengo valores completamente locos de la FIFO, la hoja de datos dice que debería dar valores CERO ..
La nueva interrupción de datos (en el octavo byte de FIFO) se establece de manera permanente en 1 wth. Las interrupciones en 0, incluso si sondeo 3 veces más rápido que la frecuencia de muestreo.
Cuando el sondeo es más lento que la frecuencia de muestreo, obtengo mejores valores, pero el ángulo Y salta esporádicamente en -3 grados cada pocos segundos (todavía se está acumulando, ahora 2 segundos).
El eje Z es bastante estable, después de unos pocos minutos de acumulación total, muestra un desplazamiento de 7 grados.
El eje X muestra alrededor de 36.
El eje Y -133 grados.
No puedo pensar en una manera de compensar estos picos repentinos, no es un desplazamiento general. Mi conclusión actual es que el chip en sí es malo. (?)
Actualización con código real: Inicialización:
data[0]=0x0F;data[1]=0b000; //001 = 1000deg/sec,000 =2000
error += twiSend( ACC_BM055_ADDR_GYRO, data, 2 );
_delay_us(5);
data[0]=0x10;data[1]=0b0011; // 0011 = 400hz odr 2khz = 0001. decimation factor 2, odr 1000hz (1k=0b0010)
error += twiSend( ACC_BM055_ADDR_GYRO, data, 2 );
_delay_us(5);
data[0]=0x13;data[1]=0b0; // filter 1, shadow 1
error += twiSend( ACC_BM055_ADDR_GYRO, data, 2 );
_delay_us(5);
data[0]=0x15;data[1]=0b0; // all interrupts off
error += twiSend( ACC_BM055_ADDR_GYRO, data, 2 );
_delay_us(5);
data[0]=0x15;data[1]=0b0; // all interrupts off
error += twiSend( ACC_BM055_ADDR_GYRO, data, 2 );
_delay_us(5);
data[0]=0x3E;data[1]=0b00; // FIFO bypass und XYZ modus
error += twiSend( ACC_BM055_ADDR_GYRO, data, 2 );
_delay_us(5);
data[0]=0x31;data[1]=0b11101111; // try to run offset comp
error += twiSend( ACC_BM055_ADDR_GYRO, data, 2 );
_delay_ms(1300);
data[0]=0x15;data[1]=0b10000010; // auto offset .. doesnt help
error += twiSend( ACC_BM055_ADDR_GYRO, data, 2 );
_delay_us(5);
data[0]=0x00;
error += twiSend( ACC_BM055_ADDR_GYRO, data, 1 );
error += twiReceive( ACC_BM055_ADDR_GYRO, result, 1 );
if (result[0] != 0b00001111) error+=32;
if (error == 100) error=0;
return error;
}
Estoy sondeando el búfer FIFO para 6 bytes (lectura de ráfaga de la dirección 0x3F) usando un temporizador que golpea cada n microsegundos.
Tan pronto como he recibido los 6 bytes esto sucede:
uint8_t axis;
float scale, deltaGyroAngle[3];
static uint16_t time_last;
uint16_t time_now = get_micros();
scale = (time_now - time_last) * GYRO_TO_RAD_FACTOR; // gyro * dt
for (axis = 0; axis < 3; axis++)
{
deltaGyroAngle[axis] = attitude.gyro_raw[axis] * scale;
}
static float sum[3];
static uint16_t counter;
sum[0] += deltaGyroAngle[0];
sum[1] += deltaGyroAngle[1];
sum[2] += deltaGyroAngle[2];
if (counter++==1000) // at current 400hz it hits once per 2.5 sec, at 1000hz it hits once per second
{
WRITE("\n\nTime dif %u us\n",time_now-time_last);
WRITE("\nWinkelsnapshot: %f %f %f\n",(sum[0]),(sum[1]),(sum[2]));uart_wait_rx0_empty();
// This shows that Z is stable
// X is slightly unstable
// Y has random -3.5 degree per second spikes (in 1000hz mode -7)
//sum[0]=0;
//sum[1]=0;
//sum[2]=0;
counter=0;
}
time_last = time_now;
Otra actualización, esta vez más cerca de la fuente:
Escribí una rutina promedio para encontrar un sesgo, muestro el chip cada 2800 nosotros.
La ODR está configurada a 400 Hz, por lo que 2500 dólares sería la tasa mínima.
Los resultados generales son muy buenos, muestra una compensación promedio de cero en 1000 muestras.
Pero cada 1-2 segundos recibo un gran aumento en uno de los valores, cerca de la lectura máxima.
El sensor se comporta como si recibiera una patada repentina dentro de dos milisegundos, pero simplemente está sentado en la mesa.
Aquí los valores en formato de 16 bits firmado y sin firmar:
Sampled 00001 -0001 00005 00001 65535 00005
Sampled 00001 00000 00002 00001 00000 00002
Sampled 00001 00001 00000 00001 00001 00000
Sampled 00001 00000 00001 00001 00000 00001
Sampled -0001 -0001 00001 65535 65535 00001
Sampled 00001 00000 00000 00001 00000 00000
Sampled 00003 00006 -0001 00003 00006 65535
Sampled 00001 00007 00000 00001 00007 00000
Sampled 00000 00004 00002 00000 00004 00002
Sampled 00001 00000 00002 00001 00000 00002
Sampled 00003 -0001 00001 00003 65535 00001
Sampled 00003 00001 00001 00003 00001 00001
Sampled 00002 00000 00001 00002 00000 00001
Sampled 00002 -18497 -0001 00002 47039 65535 <-----
Sampled -0002 00002 -0002 65534 00002 65534
Sampled 00000 -0001 00000 00000 65535 00000
Sampled 00000 00001 00000 00000 00001 00000
Sampled 00000 00002 -0001 00000 00002 65535
Sampled 00001 00001 -0003 00001 00001 65533
Sampled 00003 -0001 -0002 00003 65535 65534
Sampled 00004 -0001 00001 00004 65535 00001
Sampled 00003 -0001 00002 00003 65535 00002
Sampled 00002 -0004 00000 00002 65532 00000
Sampled 00003 -0003 00000 00003 65533 00000
Sampled 00002 00000 00000 00002 00000 00000
Sampled 00001 00001 00001 00001 00001 00001
Sampled 00002 00000 00002 00002 00000 00002
Puedes ver que los valores son realmente bajos con la excepción de un pico de -18497.
Si reduzco la demora entre muestras, estos picos se vuelven más frecuentes.
Realmente empiezo a creer que hago todo bien y Bosch tiene un problema con su chip BMI055 o este solo chip es una locura.
Una solución potencial en la que pensé sería dejar que todo el algoritmo del sensor se demorara un cuadro (alrededor de 2500us) e ignorar por completo un pico repentino de 1 ms. Pero agregaría un cierto retraso de respuesta a mi proyecto. Un filtro de paso bajo digital también podría hacer un buen trabajo con menos retraso, pero un aumento de 0 a 16000 (y también he visto 32k) también tendrá un impacto en toda la lectura.
Deseo que un experto me ilumine