1
\$\begingroup\$

I am using the BMI055 on my AVR through I2C.
Datasheet: http://ae-bst.resource.bosch.com/media/products/dokumente/bmi055/BST-BMI055-DS000-06.pdf

I set it to filtered output at an ODR of 1000Hz and I poll it every 1005us.
I set it to 1000deg/s sensitivity, at 16 bit output. That gives 32.8 LSB/degree
I am reading the values from the FIFO in bypass mode.

Now for testing I have a function which does the following(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;
}

I would have expected a bit noise and drift during 1 second (1000 samples) but I get an offset value from -3 to -11 on all 3 axis when having it on the still table.
Also the values change so much, even an average correction would not help much

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

It also puzzled me that the three axes show the same strange offset always.
When moving the board within the integration second it shows 'about' the right change (=-15 deg from the expected value)

I think I do something wrong but I can not find the problem.

Addon1: I just found that increasing the time of my polling routine significantly reduces the error. I have the ODR set at 1000Hz, if I pull at 500Hz I get low noise and a quite accurate result. Although it should mean the sensor is 50% of the time saturated and waits for my poll ? can such noise be the result of an issue between my polling and the sensors bandwidth/ODR setting ?

Addon2: Another several hours wasted. I experimented with various settings regarding poll rate and sensor ODR/bandwidth.
When polling faster than ODR I get completely crazy values from the FIFO, datasheet said it should give ZERO values..
The new data interrupt (in 8th byte of FIFO) is permanently set to 1 wth rare outages to 0, even if I poll 3 times faster than sampling rate .
When polling slower than the sampling rate I get better values but the Y angle sporadically jumps on -3 degree every few seconds (still accumulating, now 2 seconds). The Z axis is quite stable, after a few minutes total accumulation it shows 7 degree offset. The X axis shows around 36. The Y axis -133 degree.

I can not think about a way to compensate such sudden spikes, it is not a general offset. My current conclusion is that the chip itself is bad.(?)

Update with real code: Initialization:

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

I am polling the FIFO buffer for 6 bytes (burst read from address 0x3F) using a timer which hits every n microseconds.
As soon as I have received the 6 bytes this happens:

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;

Another Update, this time closer to the source:
I wrote an average routine to find a bias, I am sampling the chip each 2800 us.
The ODR is set to 400HZ so 2500 us would be the minimum rate.
The general results are very good, it shows an average offset of zero over 1000 samples.
But every 1-2 seconds I get a huge spike in one of the values, close to the maximum readout.
The sensor behaves as if it received a sudden kick within two milliseconds but it is just sitting still on the table.
Here the values in signed and unsigned 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

You can see the values are really low with the excepton of a spike of -18497.
If I reduce the delay between samples these spikes become more frequent.

I actually start to believe I do everything right and Bosch has a problem with their BMI055 chip or this single chip is just crazy.

A potential solution I thought about would be to let the whole sensor algorithm lag by one frame (around 2500us) and to completely ignore a sudden 1ms spike. But it would add quite some response delay to my project. A digital lowpass filter might also do a good job with less delay but a spike from 0 to 16000 (and I have seen 32k ones too) will still have an impact on the whole readout.

I wish an expert could enlighten me

\$\endgroup\$
  • \$\begingroup\$ I think you're going to have to show us your actual code, because the pseudocode doesn't make much sense. Where do the actual values from the sensor get used? \$\endgroup\$ – Dave Tweed May 10 '14 at 4:08
  • \$\begingroup\$ I updated my question and added the relevant code parts. I showed the init routine and the data calculation part. The whole part should be used to balance a flight drone in the air, right now I am just making sure the sensors operate in a stable way before I continue to fuse them. \$\endgroup\$ – John May 10 '14 at 12:18
1
\$\begingroup\$

Edit: I found the cause of the spikes. The BMI055 chip is internally flawed, I am sure of it now. If you read out the FIFO in Bypass mode (that means only one frame is kept) then you have to expect data errors. If you read it faster than the sampling rate you receive 10% 0x8000 (smallest possible number) in the mix. Not zero, not the last value .. a MAXIMUM value!

If you read the data a bit slower than the sampling rate, you receive valid data with 1-8 spikes per second.

This happens if you use the FIFO register in 6 or 8 byte burst mode.
Now I got curious, I read the 0x02 register in 6 byte burst and this gives the same data (x,y,z) and I changed absolutely nothing else.
The spikes are reliable gone.


previous text:

It seems that the gyroscope itself is flawed and it is not just that one.

I first expected an error in I2C communication, turned down the speed and exchanged the voltage shifting circuit without any change in results.

Now as I identified the problem to come from random high spikes I could also find many other people with similar issues or reports.
Surprising fact is that there are rarely any answers.

My first test was a moving exponential average filter, but as I expected that ruins many subsequent readings and only dampens the spikes.

The best solution I can think about is to use two gyroscopes, that is what I will do longterm. They will likely both have spikes and by comparing both frames with each other it should be possible to get a very good result and no spikes.

The simple solution is to filter spikes based on a hardcoded max-change value.
I first considered capturing data at twice the current rate and then always lagging behind one frame.
That way I would know the 'future' and the past, if the 'current' data is way off from future and past it is a spike (or someone hit a hammer on the sensor).

But for gyros with high degree/s resolution and pratical use outside of 2000deg/sec the filtering can be easier.
I played around and was shaking the gyro heavily, the raw values rarely exceeded +10k and no matter what I did they did not have any such sudden changes, even during a drop on the table.
I use this now:

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

So if the result is off by more than 12,000 raw values in comparison to the previous value than the previous value will stay in the variable. Otherwise the variable is updated with the new value.

Now I have a quite low drift which even works for many minutes.

Sidenotes about the used gyro:
a) The BMI055 gyroscope is specified to return ZERO if you sample it too fast, in reality it returns random values. b) The BMI055 gyroscope crashes the I2C bus if you send a soft_reset to it (the onchip ACC doesn't do that) c) Sudden spikes are not described in the datasheets of the gyros and still many people notice them. That's quite strange.

I would appreciate a better answer, maybe I am wrong.
However, the spike filtration made my program work quite reliable compared to the unusable results earlier.

\$\endgroup\$
1
\$\begingroup\$

Additional information for BMI055 Gyro and Acceleration sensor:

I also have random high spikes in converted data and found the reason.
Setup:

  • ACC: bandwith 250Hz = 500 Hz ODR, FIFO STREAM mode and watermark interrupt enabled, watermark = 60 = 10 data frames, measurement for all axes
  • GYR: 400 Hz ODR, FIFO STREAM mode and watermark interrupt enabled, watermark = 60 = 10 data frames, measurement for all axes
  • microcontroller reads the sensor data (exactly 10 frames) over SPI when the interrupts are triggered and converts it to 16 Bit integer data

Problem:
randomly sometimes the read out data packets are filled with zeros which build high spikes in the measurement data graph

Reason:

  • in data sheet of BMI055: If the FIFO is read beyond the FIFO fill level zeroes (0) will be read. -> this should not happen with the named setup because the FIFO watermark interrupt only triggers when there is enough data in the FIFO
  • But!!! the FIFO watermark interrupt triggers again when the FIRST frame is read out and when in this moment (or some mico seconds later) the sensor acquires the next data packet which means it stores a new frame in the FIFO --> then the watermark condition is fullfilled during the SPI read out and the Interrupt is triggered -> so after the 10 frames are read out, the microcontroller reads immediately again 10 frames but there is not enough data acquired --> zeros are read

Solution:
  • when the watermark interrupt is triggered -> disable the interrupt in the microcontroller bofore you read out the FIFO over SPI
  • reenable the interrupt at the microcontroller after the FIFO read is finished --> data is now OK
\$\endgroup\$
  • \$\begingroup\$ Also interesting, probably related to my problem as well. I already switched to the BMX055. In general I found quite a few problems with the bosch chip already, including errors in the datasheet and strange decisions they made. Also their support is not existent, emails are not answered at all. If you are not using the FIFO the simplest solution is to avoid that beast in general, reading from the registers is not causing such issues at all. \$\endgroup\$ – John Jul 18 '14 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.