I am using BMI160_driver v3.7.7 to perform a self-test of the BMI160 gyroscope and accelerometer. The following code makes two consecutive calls of bmi160_perform_self_test, the first is for the gyroscope, and the second is for the accelerometer. This code is called repeatedly in a loop to log performance. The result is that the self-tests will fail for 992 of 1000 iterations.
// Perform gyroscope self-test if (bmi160_perform_self_test(BMI160_GYRO_ONLY, &bmi160) != BMI160_OK) { return false; }
// TODO: Delay here
// Perform accelerometer self-test uint8_t data[] = {0x2C}; bmi160_set_regs(0x40, data, sizeof (data), &bmi160); // configure for self-test as per page 43 of datasheet if (bmi160_perform_self_test(BMI160_ACCEL_ONLY, &bmi160) != BMI160_OK) { return false; }
I have found it is necessary to insert a delay between the two function calls. This results in both self-tests passing 1000 of 1000 iterations. I have found this to be the case for delays as short as 300 us.
I have not been able to find any documentation for the requirement of this delay. My test system uses an 10 MHz SPI+DMA interface with a host MCU running at 200 MHz; perhaps the delay is only necessary for faster systems. I suggest that the API or documentation is updated.
Update - Tests of >8000 iterations reveal that the above delay alone is not sufficient.
The following code achieves successful self-tests for 100,000 iterations. It includes three delays: A, B, and C. All three delays are necessary. I have not determined if 10 ms is the minimum required delay.
I am sharing this code so that others can replicated the issue. The code should be called in a loop. Removing the delays will demonstrate the fault. Tests were conducted using BMI160_driver v3.7.7 and a 10 MHz SPI interface.
bool SelfTest() { // Initialise device bmi160_init(&bmi160); // Perform soft reset bmi160_soft_reset(&bmi160); // Configure device bmi160.accel_cfg.odr = BMI160_ACCEL_ODR_400HZ; bmi160.accel_cfg.range = BMI160_ACCEL_RANGE_16G; bmi160.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4; bmi160.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE; bmi160.gyro_cfg.odr = BMI160_ACCEL_ODR_400HZ; bmi160.gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS; bmi160.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE; bmi160.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE; bmi160_set_sens_conf(&bmi160); // Delay A TimerDelay(10); // Perform gyroscope self-test if (bmi160_perform_self_test(BMI160_GYRO_ONLY, &bmi160) != BMI160_OK) { return false; } // Delay B TimerDelay(10); // Perform accelerometer self-test uint8_t data[] = {0x2C}; bmi160_set_regs(0x40, data, sizeof (data), &bmi160); // configure for self-test as per page 43 of datasheet if (bmi160_perform_self_test(BMI160_ACCEL_ONLY, &bmi160) != BMI160_OK) { return false; } // Delay C TimerDelay(10); // Self-test successful return true; }
Hi sebmadgwick,
Thanks for the hint. We will look into it and get back to you when we have an update.
Regards,
kgoveas