Estoy usando el BMI055 en mi AVR a través de I2C.
Hoja de datos: http://ae-bst.resource.bosch.com/media/products/dokumente/bmi055/BST-BMI055-DS000-06.pdf
Lo configuré para salida filtrada a un ODR de 1000 Hz y lo sondeé cada 1005us.
Lo configuré a una sensibilidad de 1000 grados / s, a una salida de 16 bits. Eso da 32,8 LSB/grado.
Estoy leyendo los valores del FIFO en modo de derivación.
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 obtengo un valor de compensación de -3 a -11 en los 3 ejes cuando lo tengo en la mesa fija.
Además, 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 el mismo desplazamiento extraño.
Al mover el tablero dentro del segundo de integración, muestra 'aproximadamente' el cambio correcto (=-15 grados del valor esperado)
Creo que hago algo mal pero no encuentro el problema.
Addon1: Acabo de descubrir que aumentar el tiempo de mi rutina de sondeo reduce significativamente el error. Tengo el ODR configurado a 1000 Hz, si tiro a 500 Hz obtengo poco ruido y un resultado bastante preciso. Aunque debería significar que el sensor está saturado el 50% del tiempo y espera mi encuesta. ¿Puede ese ruido ser el resultado de un problema entre mi sondeo y la configuración de ODR/ancho de banda de los sensores?
Addon2: Otras horas desperdiciadas. Experimenté con varias configuraciones relacionadas con la tasa de sondeo y el ODR/ancho de banda del sensor.
Cuando sondeo más rápido que ODR, obtengo valores completamente locos del FIFO,
la hoja de datos dice que debería dar valores CERO. veces más rápido que la tasa de muestreo.
Cuando sondeo más lento que la frecuencia de muestreo, obtengo mejores valores, pero el ángulo Y salta esporádicamente a -3 grados cada pocos segundos (todavía se acumula, ahora 2 segundos). El eje Z es bastante estable, después de unos 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 forma de compensar picos tan repentinos, no es una compensación 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 en ráfaga desde la dirección 0x3F) usando un temporizador que golpea cada n microsegundos.
Tan pronto como he recibido los 6 bytes sucede esto:
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, estoy probando el chip cada 2800 us.
El ODR está configurado en 400 HZ, por lo que 2500 us sería la tarifa mínima.
Los resultados generales son muy buenos, muestra una compensación promedio de cero sobre 1000 muestras.
Pero cada 1-2 segundos obtengo un gran pico en uno de los valores, cerca de la lectura máxima.
El sensor se comporta como si recibiera una patada repentina en dos milisegundos, pero simplemente está sentado sobre 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
Puede ver que los valores son realmente bajos con la excepción de un pico de -18497.
Si reduzco el retraso entre las muestras, estos picos se vuelven más frecuentes.
De hecho, empiezo a creer que hago todo bien y que Bosch tiene un problema con su chip BMI055 o que este único chip es una locura.
Una posible solución en la que pensé sería dejar que todo el algoritmo del sensor se retrasara un cuadro (alrededor de 2500 us) e ignorar por completo un pico repentino de 1 ms. Pero agregaría bastante retraso en la respuesta a mi proyecto. Un filtro de paso bajo digital también podría hacer un buen trabajo con menos demora, pero un pico de 0 a 16000 (y también he visto 32k) tendrá un impacto en toda la lectura.
ojala un experto me pueda iluminar
Editar: Encontré la causa de los picos. El chip BMI055 tiene fallas internas, ahora estoy seguro. Si lee el FIFO en modo Bypass (eso significa que solo se conserva un cuadro), entonces debe esperar errores de datos. Si lo lee más rápido que la frecuencia de muestreo, recibe un 10 % de 0x8000 (el número más pequeño posible) en la mezcla. Ni cero, ni el último valor.. un valor MÁXIMO!
Si lee los datos un poco más lento que la frecuencia de muestreo, recibirá datos válidos con 1-8 picos por segundo.
Esto sucede si usa el registro FIFO en modo de ráfaga de 6 u 8 bytes.
Ahora tengo curiosidad, leí el registro 0x02 en una ráfaga de 6 bytes y esto da los mismos datos (x, y, z) y no cambié absolutamente nada más.
Los picos se han ido.
texto anterior:
Parece que el giroscopio en sí tiene fallas y no es solo ese.
Primero esperaba un error en la comunicación I2C, bajé la velocidad e intercambié el circuito de cambio de voltaje sin ningún cambio en los resultados.
Ahora que identifiqué que el problema provenía de picos altos aleatorios, también pude encontrar muchas otras personas con problemas o informes similares.
Un hecho sorprendente es que rara vez hay respuestas.
Mi primera prueba fue un filtro de promedio exponencial móvil, pero como esperaba, arruina muchas lecturas posteriores y solo amortigua los picos.
La mejor solución que se me ocurre es usar dos giroscopios, eso es lo que haré a largo plazo. Es probable que ambos tengan picos y al comparar ambos marcos entre sí, debería ser posible obtener un resultado muy bueno y sin picos.
La solución simple es filtrar los picos en función de un valor de cambio máximo codificado.
Primero consideré capturar datos al doble de la velocidad actual y luego siempre retrasarme un cuadro.
De esa manera, sabría el 'futuro' y el pasado, si los datos 'actuales' están muy lejos del futuro y el pasado, es un pico (o alguien golpeó un martillo en el sensor).
Pero para giroscopios con resolución de alto grado/s y uso práctico fuera de 2000 grados/seg, el filtrado puede ser más fácil.
Jugué y sacudí fuertemente el giroscopio, los valores brutos rara vez excedían los +10k y no importaba lo que hiciera, no tenían cambios tan repentinos, incluso durante una caída sobre la mesa.
Yo uso esto ahora:
if (abs(old-current)>0x3000) use_value();
Entonces, si el resultado está fuera de más de 12,000 valores sin procesar en comparación con el valor anterior, el valor anterior permanecerá en la variable. De lo contrario, la variable se actualiza con el nuevo valor.
Ahora tengo una deriva bastante baja que incluso funciona durante muchos minutos.
Notas al margen sobre el giroscopio usado:
a) El giroscopio BMI055 está especificado para devolver CERO si lo muestrea demasiado rápido, en realidad devuelve valores aleatorios. b) El giroscopio BMI055 bloquea el bus I2C si le envía un soft_reset (el ACC en chip no hace eso) c) Los picos repentinos no se describen en las hojas de datos de los giroscopios y aún así muchas personas los notan. Eso es bastante extraño.
Agradecería una mejor respuesta, tal vez me equivoque.
Sin embargo, la filtración de picos hizo que mi programa funcionara de manera bastante confiable en comparación con los resultados inutilizables anteriores.
También tengo picos altos aleatorios en los datos convertidos y encontré la razón .
Configuración:
Problema:
a veces, aleatoriamente, los paquetes de datos leídos se llenan con ceros, lo que crea picos altos en el gráfico de datos de medición
Motivo:
david tweed
John