MEMS-Gyroskop BMI055 – zufällige hohe Datenspitzen

Ich verwende den BMI055 auf meinem AVR über I2C.
Datenblatt: http://ae-bst.resource.bosch.com/media/products/dokumente/bmi055/BST-BMI055-DS000-06.pdf

Ich stelle es auf gefilterte Ausgabe bei einer ODR von 1000 Hz ein und frage es alle 1005 us ab.
Ich habe es auf 1000 Grad / s Empfindlichkeit bei 16-Bit-Ausgabe eingestellt. Das ergibt 32,8 LSB/Grad.
Ich lese die Werte aus dem FIFO im Bypass-Modus.

Jetzt habe ich zum Testen eine Funktion, die Folgendes tut (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;
}

Ich hätte ein bisschen Rauschen und Drift während 1 Sekunde (1000 Samples) erwartet, aber ich bekomme einen Offset-Wert von -3 bis -11 auf allen 3 Achsen, wenn ich es auf dem Standbildtisch habe.
Außerdem ändern sich die Werte so stark, dass selbst eine durchschnittliche Korrektur nicht viel helfen würde

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

Es hat mich auch verwundert, dass die drei Achsen immer denselben seltsamen Versatz zeigen.
Beim Bewegen des Boards innerhalb der Integrationssekunde zeigt es "ungefähr" die richtige Änderung (= -15 Grad vom erwarteten Wert)

Ich glaube, ich mache etwas falsch, aber ich kann das Problem nicht finden.

Addon1: Ich habe gerade festgestellt, dass das Erhöhen der Zeit meiner Abfrageroutine den Fehler erheblich reduziert. Ich habe die ODR auf 1000 Hz eingestellt, wenn ich bei 500 Hz ziehe, erhalte ich ein geringes Rauschen und ein ziemlich genaues Ergebnis. Obwohl es bedeuten sollte, dass der Sensor zu 50% der Zeit gesättigt ist und auf meine Umfrage wartet? Kann ein solches Rauschen das Ergebnis eines Problems zwischen meiner Abfrage und der Bandbreiten-/ODR-Einstellung des Sensors sein?

Addon2: Wieder mehrere Stunden verschwendet. Ich habe mit verschiedenen Einstellungen bezüglich Abfragerate und Sensor-ODR/Bandbreite experimentiert.
Wenn ich schneller als ODR abfrage, erhalte ich völlig verrückte Werte aus dem FIFO, laut Datenblatt sollte es NULL-Werte geben.
Der neue Dateninterrupt (im 8 mal schneller als die Abtastrate.
Beim Polling langsamer als die Abtastrate erhalte ich bessere Werte, aber der Y-Winkel springt sporadisch alle paar Sekunden auf -3 Grad (immer noch kumulierend, jetzt 2 Sekunden). Die Z-Achse ist recht stabil, nach einigen Minuten Gesamtakkumulation zeigt sie 7 Grad Versatz. Die X-Achse zeigt etwa 36. Die Y-Achse -133 Grad.

Ich kann mir keine Möglichkeit vorstellen, solche plötzlichen Spitzen zu kompensieren, es ist kein allgemeiner Ausgleich. Meine aktuelle Schlussfolgerung ist, dass der Chip selbst schlecht ist. (?)

Update mit echtem Code: Initialisierung:

    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;
}

Ich frage den FIFO-Puffer für 6 Bytes (Burst-Lesen von Adresse 0x3F) mit einem Timer ab, der alle n Mikrosekunden trifft.
Sobald ich die 6 Bytes erhalten habe passiert das:

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;

Ein weiteres Update, diesmal näher an der Quelle:
Ich habe eine durchschnittliche Routine geschrieben, um einen Bias zu finden, ich teste den Chip alle 2800 us.
Die ODR ist auf 400 Hz eingestellt, also wären 2500 us die Mindestrate.
Die allgemeinen Ergebnisse sind sehr gut, es zeigt einen durchschnittlichen Offset von Null über 1000 Proben.
Aber alle 1-2 Sekunden erhalte ich eine große Spitze in einem der Werte, nahe der maximalen Anzeige.
Der Sensor verhält sich innerhalb von zwei Millisekunden so, als ob er einen plötzlichen Tritt erhalten hätte, aber er sitzt einfach still auf dem Tisch.
Hier die Werte im vorzeichenbehafteten und vorzeichenlosen 16-Bit-Format:

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

Sie können sehen, dass die Werte mit Ausnahme einer Spitze von -18497 wirklich niedrig sind.
Wenn ich die Verzögerung zwischen den Abtastungen verringere, werden diese Spitzen häufiger.

Ich fange tatsächlich an zu glauben, dass ich alles richtig mache und Bosch ein Problem mit ihrem BMI055-Chip hat oder dieser einzelne Chip einfach verrückt ist.

Eine mögliche Lösung, an die ich dachte, wäre, den gesamten Sensoralgorithmus um einen Frame (ca. 2500 us) nacheilen zu lassen und eine plötzliche Spitze von 1 ms vollständig zu ignorieren. Aber es würde meinem Projekt eine ziemliche Antwortverzögerung hinzufügen. Ein digitaler Tiefpassfilter könnte auch mit weniger Verzögerung gute Arbeit leisten, aber eine Spitze von 0 auf 16000 (und ich habe auch 32.000 gesehen) wirkt sich immer noch auf die gesamte Anzeige aus.

Ich wünschte, ein Experte könnte mich aufklären

Ich denke, Sie müssen uns Ihren tatsächlichen Code zeigen, da der Pseudocode nicht viel Sinn ergibt. Wo werden die tatsächlichen Werte des Sensors verwendet?
Ich habe meine Frage aktualisiert und die relevanten Codeteile hinzugefügt. Ich habe die Init-Routine und den Datenberechnungsteil gezeigt. Das ganze Teil soll dazu dienen, eine Flugdrohne in der Luft auszubalancieren, im Moment stelle ich nur sicher, dass die Sensoren stabil funktionieren, bevor ich sie weiter fusioniere.

Antworten (2)

Edit: Ich habe die Ursache für die Spikes gefunden. Der BMI055-Chip ist intern fehlerhaft, da bin ich mir jetzt sicher. Wenn Sie den FIFO im Bypass-Modus auslesen (d. h. es wird nur ein Frame gehalten), müssen Sie mit Datenfehlern rechnen. Wenn Sie es schneller als die Abtastrate lesen, erhalten Sie 10% 0x8000 (kleinstmögliche Zahl) im Mix. Nicht Null, nicht der letzte Wert .. ein MAXIMAL-Wert!

Wenn Sie die Daten etwas langsamer als die Abtastrate lesen, erhalten Sie gültige Daten mit 1-8 Spikes pro Sekunde.

Dies passiert, wenn Sie das FIFO-Register im 6- oder 8-Byte-Burst-Modus verwenden.
Jetzt wurde ich neugierig, ich habe das 0x02-Register im 6-Byte-Burst gelesen und dies gibt die gleichen Daten (x,y,z) und ich habe absolut nichts anderes geändert.
Die Spikes sind zuverlässig weg.


vorheriger Text:

Es scheint, dass das Gyroskop selbst fehlerhaft ist und nicht nur dieses.

Ich erwartete zunächst einen Fehler in der I2C-Kommunikation, drehte die Geschwindigkeit herunter und tauschte die Spannungsverschiebungsschaltung aus, ohne dass sich die Ergebnisse änderten.

Als ich nun erkannte, dass das Problem von zufälligen hohen Spitzen herrührt, konnte ich auch viele andere Leute mit ähnlichen Problemen oder Berichten finden.
Überraschend ist, dass es selten Antworten gibt.

Mein erster Test war ein gleitender exponentieller Durchschnittsfilter, aber wie ich erwartet hatte, ruinierte das viele nachfolgende Messwerte und dämpfte nur die Spitzen.

Die beste Lösung, die mir einfällt, ist die Verwendung von zwei Gyroskopen, das werde ich langfristig tun. Sie werden wahrscheinlich beide Spikes haben und wenn man beide Frames miteinander vergleicht, sollte es möglich sein, ein sehr gutes Ergebnis und keine Spikes zu erhalten.

Die einfache Lösung besteht darin, Spitzen basierend auf einem fest codierten maximalen Änderungswert zu filtern.
Ich habe zuerst überlegt, Daten mit der doppelten Rate zu erfassen und dann immer einen Frame hinterherzuhinken.
Auf diese Weise würde ich die „Zukunft“ und die Vergangenheit kennen, wenn die „aktuellen“ Daten weit von Zukunft und Vergangenheit entfernt sind, handelt es sich um eine Spitze (oder jemand hat einen Hammer auf den Sensor geschlagen).

Aber für Kreisel mit hoher Auflösung in Grad/s und praktischer Verwendung außerhalb von 2000 Grad/s kann die Filterung einfacher sein.
Ich spielte herum und schüttelte den Kreisel heftig, die Rohwerte überschritten selten +10k und egal was ich tat, sie hatten keine solchen plötzlichen Änderungen, selbst während eines Tropfens auf dem Tisch.
Ich benutze das jetzt:

if (abs(old-current)>0x3000) use_value();

Wenn also das Ergebnis um mehr als 12.000 Rohwerte im Vergleich zum vorherigen Wert abweicht, bleibt der vorherige Wert in der Variablen. Andernfalls wird die Variable mit dem neuen Wert aktualisiert.

Jetzt habe ich eine recht geringe Drift, die sogar für viele Minuten funktioniert.

Anmerkungen zum verwendeten Gyroskop:
a) Das BMI055-Gyroskop ist so spezifiziert, dass es NULL zurückgibt, wenn Sie es zu schnell abtasten, in Wirklichkeit gibt es zufällige Werte zurück. b) Das BMI055-Gyroskop bringt den I2C-Bus zum Absturz, wenn Sie ihm einen Soft_Reset senden (das Onchip-ACC macht das nicht) c) Plötzliche Spitzen werden in den Datenblättern der Gyros nicht beschrieben und trotzdem bemerken sie viele Leute. Das ist ziemlich seltsam.

Ich würde mich über eine bessere Antwort freuen, vielleicht irre ich mich.
Die Spike-Filterung ließ mein Programm jedoch im Vergleich zu den unbrauchbaren Ergebnissen früher recht zuverlässig arbeiten.

Zusätzliche Informationen für BMI055 Kreisel- und Beschleunigungssensor:

Ich habe auch zufällige hohe Spitzen in konvertierten Daten und habe den Grund gefunden .
Aufstellen:

  • ACC: Bandbreite 250 Hz = 500 Hz ODR, FIFO-STREAM-Modus und Wasserzeichen-Interrupt aktiviert, Wasserzeichen = 60 = 10 Datenrahmen, Messung für alle Achsen
  • GYR: 400 Hz ODR, FIFO-STREAM-Modus und Wasserzeichen-Interrupt aktiviert, Wasserzeichen = 60 = 10 Datenrahmen, Messung für alle Achsen
  • Der Mikrocontroller liest die Sensordaten (genau 10 Frames) über SPI, wenn die Interrupts ausgelöst werden, und konvertiert sie in 16-Bit-Ganzzahldaten

Problem:
Zufällig werden manchmal die ausgelesenen Datenpakete mit Nullen aufgefüllt, die in der Messdatengrafik hohe Spitzen bilden

Grund:

  • im Datenblatt des BMI055: Wird der FIFO über den FIFO-Füllstand hinaus gelesen, werden Nullen (0) gelesen. -> Dies sollte mit dem genannten Setup nicht passieren, da der FIFO-Wasserzeichen-Interrupt nur dann ausgelöst wird, wenn genügend Daten im FIFO vorhanden sind
  • Aber!!! Der FIFO-Wasserzeichen-Interrupt wird erneut ausgelöst, wenn der ERSTE Frame ausgelesen wird und wenn in diesem Moment (oder einige Mikrosekunden später) der Sensor das nächste Datenpaket erfasst, was bedeutet, dass er einen neuen Frame im FIFO speichert --> dann ist der Wasserzeichenzustand gegeben während des SPI-Auslesens gefüllt und der Interrupt ausgelöst -> also liest der Mikrocontroller nach dem Auslesen der 10 Frames sofort wieder 10 Frames, aber es werden nicht genügend Daten erfasst --> Nullen werden gelesen

Lösung:
  • Wenn der Wasserzeichen-Interrupt ausgelöst wird -> deaktivieren Sie den Interrupt im Mikrocontroller, bevor Sie den FIFO über SPI auslesen
  • Aktivieren Sie den Interrupt am Mikrocontroller erneut, nachdem der FIFO-Lesevorgang abgeschlossen ist --> Daten sind jetzt in Ordnung
Auch interessant, hängt wahrscheinlich auch mit meinem Problem zusammen. Ich bin bereits auf das BMX055 umgestiegen. Im Allgemeinen habe ich bereits einige Probleme mit dem Bosch-Chip gefunden, einschließlich Fehlern im Datenblatt und seltsamen Entscheidungen, die sie getroffen haben. Auch deren Support ist nicht vorhanden, E-Mails werden überhaupt nicht beantwortet. Wenn Sie den FIFO nicht verwenden, besteht die einfachste Lösung darin, dieses Biest im Allgemeinen zu vermeiden. Das Lesen aus den Registern verursacht solche Probleme überhaupt nicht.