ARIMA / BNO055

Dependents:   arim_AutoMachine

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BNO055.cpp Source File

BNO055.cpp

00001 #include "BNO055.h"
00002 #include "mbed.h"
00003 
00004 BNO055::BNO055(PinName SDA, PinName SCL) : _i2c(SDA,SCL){
00005     //Set I2C fast and bring reset line high
00006     _i2c.frequency(400000);
00007     address = BNOAddress;
00008     accel_scale = 0.001f;
00009     rate_scale = 1.0f/16.0f;
00010     angle_scale = 1.0f/16.0f;
00011     temp_scale = 1;
00012     }
00013     
00014     
00015 BNO055::BNO055(PinName SDA, PinName SCL, double *p_yaw) : _i2c(SDA, SCL), yaw(p_yaw)
00016 {
00017     // Set I2C fast and bring reset line high
00018     _i2c.frequency(400000);
00019     address = BNOAddress;
00020     accel_scale = 0.001f;
00021     rate_scale = 1.0f / 16.0f;
00022     angle_scale = 1.0f / 16.0f;
00023     temp_scale = 1;
00024 }
00025 
00026 void BNO055::get_yaw()
00027 {
00028 
00029     static double rawyaw[2]= {0};
00030 
00031     setmode(OPERATION_MODE_IMUPLUS);
00032     get_angles();                   
00033 
00034     rawyaw[1] = rawyaw[0];
00035     rawyaw[0] = euler.yaw;
00036 
00037     if (rawyaw[0] != 0) {  //不慮の再起動対策
00038         if (rawyaw[1] < 90 && rawyaw[0] > 270)
00039             rawyaw[1] += 360;
00040         else if (rawyaw[1] > 270 && rawyaw[0] < 90)
00041             rawyaw[1] -= 360;
00042         *yaw -= rawyaw[0] - rawyaw[1];
00043     }
00044 }
00045     
00046 void BNO055::reset(){
00047 //Perform a power-on-reset
00048     readchar(BNO055_SYS_TRIGGER_ADDR);
00049     rx = rx | 0x20;
00050     writechar(BNO055_SYS_TRIGGER_ADDR,rx);
00051 //Wait for the system to come back up again (datasheet says 650ms)
00052     wait_ms(675);
00053 }
00054     
00055 bool BNO055::check(){
00056 //Check we have communication link with the chip
00057     readchar(BNO055_CHIP_ID_ADDR);
00058     if (rx != 0xA0) return false;
00059 //Grab the chip ID and software versions
00060     tx[0] = BNO055_CHIP_ID_ADDR;
00061     _i2c.write(address,tx,1,true);  
00062     _i2c.read(address+1,rawdata,7,false); 
00063     ID.id = rawdata[0];
00064     ID.accel = rawdata[1];
00065     ID.mag = rawdata[2];
00066     ID.gyro = rawdata[3];
00067     ID.sw[0] = rawdata[4];
00068     ID.sw[1] = rawdata[5];
00069     ID.bootload = rawdata[6];
00070     setpage(1);
00071     tx[0] = BNO055_UNIQUE_ID_ADDR;
00072     _i2c.write(address,tx,1,true);  
00073     _i2c.read(address+1,ID.serial,16,false); 
00074     setpage(0);
00075     return true;
00076     }
00077     
00078 void BNO055::SetExternalCrystal(bool yn){
00079 // Read the current status from the device
00080     readchar(BNO055_SYS_TRIGGER_ADDR); 
00081     if (yn) rx = rx | 0x80;
00082     else rx = rx & 0x7F;
00083     writechar(BNO055_SYS_TRIGGER_ADDR,rx); 
00084 }
00085 
00086 void BNO055::set_accel_units(char units){
00087     readchar(BNO055_UNIT_SEL_ADDR);
00088     if(units == MPERSPERS){
00089         rx = rx & 0xFE;
00090         accel_scale = 0.01f;
00091         }
00092     else {
00093         rx = rx | units;
00094         accel_scale = 0.001f;
00095         }
00096     writechar(BNO055_UNIT_SEL_ADDR,rx);
00097 }
00098 
00099 void BNO055::set_anglerate_units(char units){
00100     readchar(BNO055_UNIT_SEL_ADDR);
00101     if (units == DEG_PER_SEC){
00102         rx = rx & 0xFD;
00103         rate_scale = 1.0f/16.0f;
00104         }
00105     else {
00106         rx = rx | units;
00107         rate_scale = 1.0f/900.0f;
00108         }
00109     writechar(BNO055_UNIT_SEL_ADDR,rx);
00110 }    
00111 
00112 void BNO055::set_angle_units(char units){
00113     readchar(BNO055_UNIT_SEL_ADDR);
00114     if (units == DEGREES){
00115         rx = rx & 0xFB;
00116         angle_scale = 1.0f/16.0f;
00117         }
00118     else {
00119         rx = rx | units;
00120         rate_scale = 1.0f/900.0f;
00121         }
00122     writechar(BNO055_UNIT_SEL_ADDR,rx);
00123 }    
00124 
00125 void BNO055::set_temp_units(char units){
00126     readchar(BNO055_UNIT_SEL_ADDR);
00127     if (units == CENTIGRADE){
00128         rx = rx & 0xEF;
00129         temp_scale = 1;
00130         }
00131     else {
00132         rx = rx | units;
00133         temp_scale = 2;
00134         }
00135     writechar(BNO055_UNIT_SEL_ADDR,rx);
00136 }    
00137 
00138 void BNO055::set_orientation(char units){
00139     readchar(BNO055_UNIT_SEL_ADDR);
00140     if (units == WINDOWS) rx = rx &0x7F;
00141     else rx = rx | units;
00142     writechar(BNO055_UNIT_SEL_ADDR,rx);
00143 }        
00144 
00145 void BNO055::setmode(char omode){
00146     writechar(BNO055_OPR_MODE_ADDR,omode);
00147     op_mode = omode;
00148 }
00149 
00150 void BNO055::setpowermode(char pmode){
00151     writechar(BNO055_PWR_MODE_ADDR,pmode);
00152     pwr_mode = pmode;
00153 }
00154 
00155 void BNO055::get_accel(void){
00156     tx[0] = BNO055_ACCEL_DATA_X_LSB_ADDR;
00157     _i2c.write(address,tx,1,true);  
00158     _i2c.read(address+1,rawdata,6,0); 
00159     accel.rawx = (rawdata[1] << 8 | rawdata[0]);
00160     accel.rawy = (rawdata[3] << 8 | rawdata[2]);
00161     accel.rawz = (rawdata[5] << 8 | rawdata[4]);
00162     accel.x = float(accel.rawx)*accel_scale;
00163     accel.y = float(accel.rawy)*accel_scale;
00164     accel.z = float(accel.rawz)*accel_scale;
00165 }
00166     
00167 void BNO055::get_gyro(void){
00168     tx[0] = BNO055_GYRO_DATA_X_LSB_ADDR;
00169     _i2c.write(address,tx,1,true);  
00170     _i2c.read(address+1,rawdata,6,0); 
00171     gyro.rawx = (rawdata[1] << 8 | rawdata[0]);
00172     gyro.rawy = (rawdata[3] << 8 | rawdata[2]);
00173     gyro.rawz = (rawdata[5] << 8 | rawdata[4]);
00174     gyro.x = float(gyro.rawx)*rate_scale;
00175     gyro.y = float(gyro.rawy)*rate_scale;
00176     gyro.z = float(gyro.rawz)*rate_scale;
00177 }
00178 
00179 void BNO055::get_mag(void){
00180     tx[0] = BNO055_MAG_DATA_X_LSB_ADDR;
00181     _i2c.write(address,tx,1,true);  
00182     _i2c.read(address+1,rawdata,6,0); 
00183     mag.rawx = (rawdata[1] << 8 | rawdata[0]);
00184     mag.rawy = (rawdata[3] << 8 | rawdata[2]);
00185     mag.rawz = (rawdata[5] << 8 | rawdata[4]);
00186     mag.x = float(mag.rawx);
00187     mag.y = float(mag.rawy);
00188     mag.z = float(mag.rawz);
00189 }
00190 
00191 void BNO055::get_lia(void){
00192     tx[0] = BNO055_LINEAR_ACCEL_DATA_X_LSB_ADDR;
00193     _i2c.write(address,tx,1,true);  
00194     _i2c.read(address+1,rawdata,6,0); 
00195     lia.rawx = (rawdata[1] << 8 | rawdata[0]);
00196     lia.rawy = (rawdata[3] << 8 | rawdata[2]);
00197     lia.rawz = (rawdata[5] << 8 | rawdata[4]);
00198     lia.x = float(lia.rawx)*accel_scale;
00199     lia.y = float(lia.rawy)*accel_scale;
00200     lia.z = float(lia.rawz)*accel_scale;
00201 }
00202 
00203 void BNO055::get_grv(void){
00204     tx[0] = BNO055_GRAVITY_DATA_X_LSB_ADDR;
00205     _i2c.write(address,tx,1,true);  
00206     _i2c.read(address+1,rawdata,6,0); 
00207     gravity.rawx = (rawdata[1] << 8 | rawdata[0]);
00208     gravity.rawy = (rawdata[3] << 8 | rawdata[2]);
00209     gravity.rawz = (rawdata[5] << 8 | rawdata[4]);
00210     gravity.x = float(gravity.rawx)*accel_scale;
00211     gravity.y = float(gravity.rawy)*accel_scale;
00212     gravity.z = float(gravity.rawz)*accel_scale;
00213 }
00214 
00215 void BNO055::get_quat(void){
00216     tx[0] = BNO055_QUATERNION_DATA_W_LSB_ADDR;
00217     _i2c.write(address,tx,1,true);  
00218     _i2c.read(address+1,rawdata,8,0); 
00219     quat.raww = (rawdata[1] << 8 | rawdata[0]);
00220     quat.rawx = (rawdata[3] << 8 | rawdata[2]);
00221     quat.rawy = (rawdata[5] << 8 | rawdata[4]);
00222     quat.rawz = (rawdata[7] << 8 | rawdata[6]);
00223     quat.w = float(quat.raww)/16384.0f;
00224     quat.x = float(quat.rawx)/16384.0f;
00225     quat.y = float(quat.rawy)/16384.0f;
00226     quat.z = float(quat.rawz)/16384.0f;
00227 }
00228 
00229 void BNO055::get_angles(void){
00230     tx[0] = BNO055_EULER_H_LSB_ADDR;
00231     _i2c.write(address,tx,1,true);  
00232     _i2c.read(address+1,rawdata,6,0); 
00233     euler.rawyaw = (rawdata[1] << 8 | rawdata[0]);
00234     euler.rawroll = (rawdata[3] << 8 | rawdata[2]);
00235     euler.rawpitch = (rawdata[5] << 8 | rawdata[4]);
00236     euler.yaw = float(euler.rawyaw)*angle_scale;
00237     euler.roll = float(euler.rawroll)*angle_scale;
00238     euler.pitch = float(euler.rawpitch)*angle_scale;
00239 }
00240 
00241 
00242 void BNO055::get_temp(void){
00243     readchar(BNO055_TEMP_ADDR);
00244     temperature = rx / temp_scale;
00245 }
00246 
00247 void BNO055::get_calib(void){
00248      readchar(BNO055_CALIB_STAT_ADDR);
00249      calib = rx;
00250 }
00251 
00252 void BNO055::read_calibration_data(void){
00253     char tempmode = op_mode;
00254     setmode(OPERATION_MODE_CONFIG);
00255     wait_ms(20);
00256     tx[0] = ACCEL_OFFSET_X_LSB_ADDR;
00257     _i2c.write(address,tx,1,true);  
00258     _i2c.read(address,calibration,22,false); 
00259     setmode(tempmode);
00260     wait_ms(10);
00261 }
00262 
00263 void BNO055::write_calibration_data(void){
00264     char tempmode = op_mode;
00265     setmode(OPERATION_MODE_CONFIG);
00266     wait_ms(20);
00267     tx[0] = ACCEL_OFFSET_X_LSB_ADDR;
00268     _i2c.write(address,tx,1,true);  
00269     _i2c.write(address,calibration,22,false); 
00270     setmode(tempmode);
00271     wait_ms(10);
00272 }
00273 
00274 void BNO055::set_mapping(char orient){
00275     switch (orient){
00276         case 0: 
00277             writechar(BNO055_AXIS_MAP_CONFIG_ADDR,0x21);
00278             writechar(BNO055_AXIS_MAP_SIGN_ADDR,0x04);
00279             break;
00280         case 1:
00281             writechar(BNO055_AXIS_MAP_CONFIG_ADDR,0x24);
00282             writechar(BNO055_AXIS_MAP_SIGN_ADDR,0x00);
00283             break;
00284         case 2:
00285             writechar(BNO055_AXIS_MAP_CONFIG_ADDR,0x24);
00286             writechar(BNO055_AXIS_MAP_SIGN_ADDR,0x00);
00287             break;
00288         case 3:
00289             writechar(BNO055_AXIS_MAP_CONFIG_ADDR,0x21);
00290             writechar(BNO055_AXIS_MAP_SIGN_ADDR,0x02);
00291             break;
00292         case 4:
00293             writechar(BNO055_AXIS_MAP_CONFIG_ADDR,0x24);
00294             writechar(BNO055_AXIS_MAP_SIGN_ADDR,0x03);
00295             break;
00296         case 5:
00297             writechar(BNO055_AXIS_MAP_CONFIG_ADDR,0x21);
00298             writechar(BNO055_AXIS_MAP_SIGN_ADDR,0x01);
00299             break;
00300         case 6:
00301             writechar(BNO055_AXIS_MAP_CONFIG_ADDR,0x21);
00302             writechar(BNO055_AXIS_MAP_SIGN_ADDR,0x07);
00303             break;
00304         case 7:
00305             writechar(BNO055_AXIS_MAP_CONFIG_ADDR,0x24);
00306             writechar(BNO055_AXIS_MAP_SIGN_ADDR,0x05);
00307             break;
00308         default:
00309             writechar(BNO055_AXIS_MAP_CONFIG_ADDR,0x24);
00310             writechar(BNO055_AXIS_MAP_SIGN_ADDR,0x00);
00311         }
00312 }