Disable standby mode at init Can now calculate offset on acc and gyro Fifo reset function
373 lines
8.8 KiB
C++
373 lines
8.8 KiB
C++
/*CODED by Bruno Alfano on 07/03/2014
|
|
www.xene.it
|
|
*/
|
|
|
|
#include <mbed.h>
|
|
#include "MPU6000.h"
|
|
#include <math.h>
|
|
#include "src/math/Utilities.h"
|
|
|
|
mpu6000_spi::mpu6000_spi(SPI& _spi, PinName _cs)
|
|
: spi(_spi)
|
|
, cs(_cs)
|
|
{
|
|
_gyro_offset[0] = 0;
|
|
_gyro_offset[1] = 0;
|
|
_gyro_offset[2] = 0;
|
|
_acc_offset[0] = 0;
|
|
_acc_offset[1] = 0;
|
|
_acc_offset[2] = 0;
|
|
}
|
|
|
|
|
|
bool mpu6000_spi::init(int sample_rate_div,int low_pass_filter){
|
|
unsigned int response;
|
|
spi.format(8,0);
|
|
spi.frequency(1000000);
|
|
//FIRST OF ALL DISABLE I2C
|
|
select();
|
|
response=spi.write(MPUREG_USER_CTRL);
|
|
response=spi.write(BIT_I2C_IF_DIS);
|
|
deselect();
|
|
//RESET CHIP
|
|
select();
|
|
response=spi.write(MPUREG_PWR_MGMT_1);
|
|
response=spi.write(BIT_H_RESET);
|
|
deselect();
|
|
wait(0.15);
|
|
//WAKE UP AND SET GYROZ CLOCK
|
|
select();
|
|
response=spi.write(MPUREG_PWR_MGMT_1);
|
|
response=spi.write(MPU_CLK_SEL_PLLGYROZ);
|
|
deselect();
|
|
//DISABLE I2C
|
|
select();
|
|
response=spi.write(MPUREG_USER_CTRL);
|
|
response=spi.write(BIT_I2C_IF_DIS);
|
|
deselect();
|
|
// DISABLE STANDBY MODE
|
|
select();
|
|
response=spi.write(MPUREG_PWR_MGMT_2);
|
|
response=spi.write(0x00);
|
|
deselect();
|
|
//WHO AM I?
|
|
select();
|
|
response=spi.write(MPUREG_WHOAMI|READ_FLAG);
|
|
response=spi.write(0x00);
|
|
deselect();
|
|
if(response<100){return 0;}//COULDN'T RECEIVE WHOAMI
|
|
//SET SAMPLE RATE
|
|
select();
|
|
response=spi.write(MPUREG_SMPLRT_DIV);
|
|
response=spi.write(sample_rate_div);
|
|
deselect();
|
|
// FS & DLPF
|
|
select();
|
|
response=spi.write(MPUREG_CONFIG);
|
|
response=spi.write(low_pass_filter);
|
|
deselect();
|
|
//DISABLE INTERRUPTS
|
|
select();
|
|
response=spi.write(MPUREG_INT_ENABLE);
|
|
response=spi.write(0x00);
|
|
deselect();
|
|
|
|
return true; // TODO
|
|
}
|
|
|
|
int mpu6000_spi::enableInterrupt()
|
|
{
|
|
unsigned int response;
|
|
|
|
//ENABLE INTERRUPTS
|
|
select();
|
|
response=spi.write(MPUREG_INT_ENABLE);
|
|
response=spi.write(0x01);
|
|
deselect();
|
|
return 0;
|
|
}
|
|
|
|
unsigned int mpu6000_spi::set_acc_scale(int scale){
|
|
unsigned int temp_scale;
|
|
select();
|
|
spi.write(MPUREG_ACCEL_CONFIG);
|
|
spi.write(scale);
|
|
deselect();
|
|
switch (scale){
|
|
case BITS_FS_2G:
|
|
acc_divider=16384;
|
|
break;
|
|
case BITS_FS_4G:
|
|
acc_divider=8192;
|
|
break;
|
|
case BITS_FS_8G:
|
|
acc_divider=4096;
|
|
break;
|
|
case BITS_FS_16G:
|
|
acc_divider=2048;
|
|
break;
|
|
}
|
|
wait(0.01);
|
|
select();
|
|
temp_scale=spi.write(MPUREG_ACCEL_CONFIG|READ_FLAG);
|
|
temp_scale=spi.write(0x00);
|
|
deselect();
|
|
switch (temp_scale){
|
|
case BITS_FS_2G:
|
|
temp_scale=2;
|
|
break;
|
|
case BITS_FS_4G:
|
|
temp_scale=4;
|
|
break;
|
|
case BITS_FS_8G:
|
|
temp_scale=8;
|
|
break;
|
|
case BITS_FS_16G:
|
|
temp_scale=16;
|
|
break;
|
|
}
|
|
return temp_scale;
|
|
}
|
|
|
|
unsigned int mpu6000_spi::set_gyro_scale(int scale){
|
|
unsigned int temp_scale;
|
|
select();
|
|
spi.write(MPUREG_GYRO_CONFIG);
|
|
spi.write(scale);
|
|
deselect();
|
|
switch (scale){
|
|
case BITS_FS_250DPS:
|
|
gyro_divider=131;
|
|
break;
|
|
case BITS_FS_500DPS:
|
|
gyro_divider=65.5;
|
|
break;
|
|
case BITS_FS_1000DPS:
|
|
gyro_divider=32.8;
|
|
break;
|
|
case BITS_FS_2000DPS:
|
|
gyro_divider=16.4;
|
|
break;
|
|
}
|
|
wait(0.01);
|
|
select();
|
|
temp_scale=spi.write(MPUREG_GYRO_CONFIG|READ_FLAG);
|
|
temp_scale=spi.write(0x00);
|
|
deselect();
|
|
switch (temp_scale){
|
|
case BITS_FS_250DPS:
|
|
temp_scale=250;
|
|
break;
|
|
case BITS_FS_500DPS:
|
|
temp_scale=500;
|
|
break;
|
|
case BITS_FS_1000DPS:
|
|
temp_scale=1000;
|
|
break;
|
|
case BITS_FS_2000DPS:
|
|
temp_scale=2000;
|
|
break;
|
|
}
|
|
return temp_scale;
|
|
}
|
|
|
|
unsigned int mpu6000_spi::whoami(){
|
|
unsigned int response;
|
|
select();
|
|
response=spi.write(MPUREG_WHOAMI|READ_FLAG);
|
|
response=spi.write(0x00);
|
|
deselect();
|
|
return response;
|
|
}
|
|
|
|
float mpu6000_spi::read_acc(int axis){
|
|
uint8_t responseH,responseL;
|
|
int16_t bit_data;
|
|
float data;
|
|
select();
|
|
switch (axis){
|
|
case 0:
|
|
responseH=spi.write(MPUREG_ACCEL_XOUT_H | READ_FLAG);
|
|
break;
|
|
case 1:
|
|
responseH=spi.write(MPUREG_ACCEL_YOUT_H | READ_FLAG);
|
|
break;
|
|
case 2:
|
|
responseH=spi.write(MPUREG_ACCEL_ZOUT_H | READ_FLAG);
|
|
break;
|
|
}
|
|
responseH=spi.write(0x00);
|
|
responseL=spi.write(0x00);
|
|
bit_data=((int16_t)responseH<<8)|responseL;
|
|
data=(float)bit_data;
|
|
data=data/acc_divider;
|
|
deselect();
|
|
return data - _acc_offset[axis];;
|
|
}
|
|
|
|
float mpu6000_spi::read_acc_deg(int axis)
|
|
{
|
|
return asin(read_acc(axis))/PI*180;
|
|
}
|
|
|
|
float mpu6000_spi::read_rot(int axis){
|
|
uint8_t responseH,responseL;
|
|
int16_t bit_data;
|
|
float data;
|
|
select();
|
|
switch (axis){
|
|
case 0:
|
|
responseH=spi.write(MPUREG_GYRO_XOUT_H | READ_FLAG);
|
|
break;
|
|
case 1:
|
|
responseH=spi.write(MPUREG_GYRO_YOUT_H | READ_FLAG);
|
|
break;
|
|
case 2:
|
|
responseH=spi.write(MPUREG_GYRO_ZOUT_H | READ_FLAG);
|
|
break;
|
|
}
|
|
responseH=spi.write(0x00);
|
|
responseL=spi.write(0x00);
|
|
bit_data=((int16_t)responseH<<8)|responseL;
|
|
data=(float)bit_data;
|
|
data=data/gyro_divider;
|
|
deselect();
|
|
return data - _gyro_offset[axis];
|
|
}
|
|
|
|
float mpu6000_spi::read_temp(){
|
|
uint8_t responseH,responseL;
|
|
int16_t bit_data;
|
|
float data;
|
|
select();
|
|
responseH=spi.write(MPUREG_TEMP_OUT_H | READ_FLAG);
|
|
responseH=spi.write(0x00);
|
|
responseL=spi.write(0x00);
|
|
bit_data=((int16_t)responseH<<8)|responseL;
|
|
data=(float)bit_data;
|
|
data=(data/340)+36.53;
|
|
deselect();
|
|
return data;
|
|
}
|
|
|
|
bool mpu6000_spi::resetOffset_gyro(){
|
|
wait_ms(20);
|
|
|
|
bool result(true);
|
|
|
|
float validThreshold(5.0);
|
|
|
|
for (int axisIt = 0; axisIt <= 2 ; axisIt++)
|
|
{
|
|
for (int samples = 0; samples <= 5; samples++)
|
|
{
|
|
Thread::wait(20);
|
|
float abc = read_rot(axisIt);
|
|
_gyro_offset[axisIt] += abc;
|
|
}
|
|
_gyro_offset[axisIt] /= 6;
|
|
|
|
if (abs(_gyro_offset[axisIt]) > validThreshold)
|
|
{
|
|
// Calibration failed
|
|
result = false;
|
|
_gyro_offset[axisIt] = 0.0;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool mpu6000_spi::resetOffset_acc(){
|
|
wait_ms(20);
|
|
|
|
bool result(true);
|
|
|
|
float validThreshold(5.0);
|
|
|
|
for (int axisIt = 0; axisIt <= 2 ; axisIt++)
|
|
{
|
|
for (int samples = 0; samples <= 5; samples++)
|
|
{
|
|
Thread::wait(20);
|
|
float abc = read_acc(axisIt);
|
|
_acc_offset[axisIt] += abc;
|
|
}
|
|
_acc_offset[axisIt] /= 6;
|
|
|
|
if (abs(_acc_offset[axisIt]) > validThreshold)
|
|
{
|
|
// Calibration failed
|
|
result = false;
|
|
_acc_offset[axisIt] = 0.0;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int mpu6000_spi::calib_acc(int axis){
|
|
uint8_t responseH,responseL,calib_data;
|
|
int temp_scale;
|
|
//READ CURRENT ACC SCALE
|
|
select();
|
|
responseH=spi.write(MPUREG_ACCEL_CONFIG|READ_FLAG);
|
|
temp_scale=spi.write(0x00);
|
|
deselect();
|
|
wait(0.01);
|
|
set_acc_scale(BITS_FS_8G);
|
|
wait(0.01);
|
|
//ENABLE SELF TEST
|
|
select();
|
|
responseH=spi.write(MPUREG_ACCEL_CONFIG);
|
|
temp_scale=spi.write(0x80>>axis);
|
|
deselect();
|
|
wait(0.01);
|
|
select();
|
|
responseH=spi.write(MPUREG_SELF_TEST_X|READ_FLAG);
|
|
switch(axis){
|
|
case 0:
|
|
responseH=spi.write(0x00);
|
|
responseL=spi.write(0x00);
|
|
responseL=spi.write(0x00);
|
|
responseL=spi.write(0x00);
|
|
calib_data=((responseH&11100000)>>3)|((responseL&00110000)>>4);
|
|
break;
|
|
case 1:
|
|
responseH=spi.write(0x00);
|
|
responseH=spi.write(0x00);
|
|
responseL=spi.write(0x00);
|
|
responseL=spi.write(0x00);
|
|
calib_data=((responseH&11100000)>>3)|((responseL&00001100)>>2);
|
|
break;
|
|
case 2:
|
|
responseH=spi.write(0x00);
|
|
responseH=spi.write(0x00);
|
|
responseH=spi.write(0x00);
|
|
responseL=spi.write(0x00);
|
|
calib_data=((responseH&11100000)>>3)|((responseL&00000011));
|
|
break;
|
|
}
|
|
deselect();
|
|
wait(0.01);
|
|
set_acc_scale(temp_scale);
|
|
return calib_data;
|
|
}
|
|
|
|
void mpu6000_spi::select() {
|
|
//Set CS low to start transmission (interrupts conversion)
|
|
cs = 0;
|
|
}
|
|
void mpu6000_spi::deselect() {
|
|
//Set CS high to stop transmission (restarts conversion)
|
|
cs = 1;
|
|
}
|
|
|
|
void mpu6000_spi::fifo_reset()
|
|
{
|
|
unsigned int response;
|
|
//FIFO RESET
|
|
select();
|
|
response=spi.write(MPUREG_USER_CTRL);
|
|
response=spi.write(BIT_FIFO_RESET);
|
|
deselect();
|
|
}
|