ai_car
MPU9205_SPI.cpp@12:f3816a0f498e, 2021-05-03 (annotated)
- Committer:
- wngudwls000
- Date:
- Mon May 03 07:20:25 2021 +0000
- Revision:
- 12:f3816a0f498e
adas
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
wngudwls000 | 12:f3816a0f498e | 1 | #include "mbed.h" |
wngudwls000 | 12:f3816a0f498e | 2 | #include "MPU9250_SPI.h" |
wngudwls000 | 12:f3816a0f498e | 3 | #include "MPU9250RegisterMap.h" |
wngudwls000 | 12:f3816a0f498e | 4 | #include <cmath> |
wngudwls000 | 12:f3816a0f498e | 5 | // MPU9250 with SPI interface library Ver. 0.98 |
wngudwls000 | 12:f3816a0f498e | 6 | // Made by HeeJae Park |
wngudwls000 | 12:f3816a0f498e | 7 | // 2019.05.27 |
wngudwls000 | 12:f3816a0f498e | 8 | //extern Serial pc; |
wngudwls000 | 12:f3816a0f498e | 9 | volatile bool MPU9250_SPI::_dataReady=false; |
wngudwls000 | 12:f3816a0f498e | 10 | MPU9250_SPI::MPU9250_SPI(PinName mosi,PinName miso,PinName sclk, PinName cs, PinName intpin) |
wngudwls000 | 12:f3816a0f498e | 11 | : _spi(mosi,miso,sclk), _csPin(cs), _intPin(intpin),_mMode(MGN_CONT_MEAS2),_mBits( MGN_16BITS),_srd(SR_100HZ) { |
wngudwls000 | 12:f3816a0f498e | 12 | magCalibration.x=0;magCalibration.y=0;magCalibration.z=0; |
wngudwls000 | 12:f3816a0f498e | 13 | magBias.x=0; magBias.y=0; magBias.z=0; |
wngudwls000 | 12:f3816a0f498e | 14 | magScale.x=1;magScale.y=1;magScale.z=1; |
wngudwls000 | 12:f3816a0f498e | 15 | gyroBias.x =0; gyroBias.y =0; gyroBias.z =0; |
wngudwls000 | 12:f3816a0f498e | 16 | accelBias.x=0; accelBias.y=0; accelBias.z=0; |
wngudwls000 | 12:f3816a0f498e | 17 | magnetic_declination = 8.5; |
wngudwls000 | 12:f3816a0f498e | 18 | _csPin=1; |
wngudwls000 | 12:f3816a0f498e | 19 | } |
wngudwls000 | 12:f3816a0f498e | 20 | void MPU9250_SPI::setup() { |
wngudwls000 | 12:f3816a0f498e | 21 | _csPin=1; // setting CS pin high |
wngudwls000 | 12:f3816a0f498e | 22 | _spi.format(8,3); // SPI mode 3 |
wngudwls000 | 12:f3816a0f498e | 23 | _spi.frequency(SPI_HS_CLOCK); // 1Mega |
wngudwls000 | 12:f3816a0f498e | 24 | uint8_t m_whoami = 0x00; |
wngudwls000 | 12:f3816a0f498e | 25 | uint8_t a_whoami = 0x00; |
wngudwls000 | 12:f3816a0f498e | 26 | m_whoami = isConnectedMPU9250(); |
wngudwls000 | 12:f3816a0f498e | 27 | if (m_whoami==MPU9250_WHOAMI_DEFAULT_VALUE) { |
wngudwls000 | 12:f3816a0f498e | 28 | initMPU9250(); |
wngudwls000 | 12:f3816a0f498e | 29 | a_whoami = isConnectedAK8963(); |
wngudwls000 | 12:f3816a0f498e | 30 | if (a_whoami == AK8963_WHOAMI_DEFAULT_VALUE){ |
wngudwls000 | 12:f3816a0f498e | 31 | initAK8963(); |
wngudwls000 | 12:f3816a0f498e | 32 | } |
wngudwls000 | 12:f3816a0f498e | 33 | else { |
wngudwls000 | 12:f3816a0f498e | 34 | while(1); |
wngudwls000 | 12:f3816a0f498e | 35 | } |
wngudwls000 | 12:f3816a0f498e | 36 | } |
wngudwls000 | 12:f3816a0f498e | 37 | else { |
wngudwls000 | 12:f3816a0f498e | 38 | while(1); |
wngudwls000 | 12:f3816a0f498e | 39 | } |
wngudwls000 | 12:f3816a0f498e | 40 | _intPin.rise(callback(this, &MPU9250_SPI::intService)); |
wngudwls000 | 12:f3816a0f498e | 41 | _tmr.start(); |
wngudwls000 | 12:f3816a0f498e | 42 | } |
wngudwls000 | 12:f3816a0f498e | 43 | void MPU9250_SPI::update(Vect3& _a,Vect3& _g,Vect3& _m) { |
wngudwls000 | 12:f3816a0f498e | 44 | if (_dataReady){ // On interrupt, check if data ready interrupt |
wngudwls000 | 12:f3816a0f498e | 45 | updateSensors(); |
wngudwls000 | 12:f3816a0f498e | 46 | _a=a;_g=g;_m=m; |
wngudwls000 | 12:f3816a0f498e | 47 | } |
wngudwls000 | 12:f3816a0f498e | 48 | } |
wngudwls000 | 12:f3816a0f498e | 49 | |
wngudwls000 | 12:f3816a0f498e | 50 | uint8_t MPU9250_SPI::isConnectedMPU9250() { |
wngudwls000 | 12:f3816a0f498e | 51 | uint8_t c = readByte(WHO_AM_I_MPU9250); |
wngudwls000 | 12:f3816a0f498e | 52 | return c; // (c == MPU9250_WHOAMI_DEFAULT_VALUE); |
wngudwls000 | 12:f3816a0f498e | 53 | } |
wngudwls000 | 12:f3816a0f498e | 54 | uint8_t MPU9250_SPI::isConnectedAK8963() { |
wngudwls000 | 12:f3816a0f498e | 55 | uint8_t c = readAK8963Byte(AK8963_WHO_AM_I); |
wngudwls000 | 12:f3816a0f498e | 56 | return c; // (c == AK8963_WHOAMI_DEFAULT_VALUE); |
wngudwls000 | 12:f3816a0f498e | 57 | } |
wngudwls000 | 12:f3816a0f498e | 58 | |
wngudwls000 | 12:f3816a0f498e | 59 | void MPU9250_SPI::initMPU9250() { |
wngudwls000 | 12:f3816a0f498e | 60 | wait_ms(100); |
wngudwls000 | 12:f3816a0f498e | 61 | writeByte(PWR_MGMT_1, CLOCK_SEL_PLL); |
wngudwls000 | 12:f3816a0f498e | 62 | writeByte(USER_CTRL,I2C_MST_EN); // Master enable |
wngudwls000 | 12:f3816a0f498e | 63 | writeByte(I2C_MST_CTRL,I2C_MST_CLK); // I2C master clock =400HZ |
wngudwls000 | 12:f3816a0f498e | 64 | replaceBlockAK(AK8963_CNTL,MGN_POWER_DN,0,4); // Power down |
wngudwls000 | 12:f3816a0f498e | 65 | writeByte(PWR_MGMT_1, PWR_RESET); // Clear sleep mode bit (6), enable all sensors |
wngudwls000 | 12:f3816a0f498e | 66 | wait_ms(100); |
wngudwls000 | 12:f3816a0f498e | 67 | writeByte(PWR_MGMT_1, CLOCK_SEL_PLL); |
wngudwls000 | 12:f3816a0f498e | 68 | setDlpfBandwidth( DLPF_BANDWIDTH_5HZ); |
wngudwls000 | 12:f3816a0f498e | 69 | writeByte(SMPLRT_DIV, SR_100HZ); //{SR_1000HZ=0, SR_200HZ=4, SR_100HZ=9 } |
wngudwls000 | 12:f3816a0f498e | 70 | setGyroRange(GYRO_RANGE_2000DPS); |
wngudwls000 | 12:f3816a0f498e | 71 | writeByte(PWR_MGMT_2,SEN_ENABLE); |
wngudwls000 | 12:f3816a0f498e | 72 | setAccelRange(ACCEL_RANGE_16G);//{ _2G, _4G, _8G, _16G } |
wngudwls000 | 12:f3816a0f498e | 73 | setDlpfBandwidth(DLPF_BANDWIDTH_184HZ); // [250HZ, 184HZ, 92HZ, 41HZ, 20HZ, 10HZ, 5HZ] |
wngudwls000 | 12:f3816a0f498e | 74 | writeByte(INT_PIN_CFG, 0x20); // LATCH_INT_EN=1, BYPASS_EN=1-->0 (0x22) |
wngudwls000 | 12:f3816a0f498e | 75 | writeByte(INT_ENABLE, 0x01); // Enable raw data ready (bit 0) interrupt |
wngudwls000 | 12:f3816a0f498e | 76 | writeByte(USER_CTRL,I2C_MST_EN); |
wngudwls000 | 12:f3816a0f498e | 77 | wait_ms(100); |
wngudwls000 | 12:f3816a0f498e | 78 | writeByte(I2C_MST_CTRL,I2C_MST_CLK); |
wngudwls000 | 12:f3816a0f498e | 79 | wait_ms(100); |
wngudwls000 | 12:f3816a0f498e | 80 | } |
wngudwls000 | 12:f3816a0f498e | 81 | |
wngudwls000 | 12:f3816a0f498e | 82 | void MPU9250_SPI::initAK8963() { |
wngudwls000 | 12:f3816a0f498e | 83 | uint8_t rawData[3]; // x/y/z gyro calibration data stored here |
wngudwls000 | 12:f3816a0f498e | 84 | replaceBlockAK(AK8963_CNTL,MGN_POWER_DN,0,4); // Power down magnetometer |
wngudwls000 | 12:f3816a0f498e | 85 | wait_ms(50); |
wngudwls000 | 12:f3816a0f498e | 86 | replaceBlockAK(AK8963_CNTL,MGN_FUSE_ROM,0,4); |
wngudwls000 | 12:f3816a0f498e | 87 | wait_ms(50); |
wngudwls000 | 12:f3816a0f498e | 88 | readAK8963Bytes( AK8963_ASAX, 3, rawData); // Read the x-, y-, and z-axis calibration values |
wngudwls000 | 12:f3816a0f498e | 89 | magCalibration.x = (float)(rawData[0] - 128)/256.f + 1.f; // Return x-axis sensitivity adjustment values, etc. |
wngudwls000 | 12:f3816a0f498e | 90 | magCalibration.y = (float)(rawData[1] - 128)/256.f + 1.f; |
wngudwls000 | 12:f3816a0f498e | 91 | magCalibration.z = (float)(rawData[2] - 128)/256.f + 1.f; |
wngudwls000 | 12:f3816a0f498e | 92 | replaceBlockAK(AK8963_CNTL,MGN_POWER_DN,0,4); // Power down magnetometer |
wngudwls000 | 12:f3816a0f498e | 93 | wait_ms(50); |
wngudwls000 | 12:f3816a0f498e | 94 | replaceBlockAK(AK8963_CNTL,((_mBits << 4 )| _mMode),0,5); // Set measurment mode, mMode[0:3] |
wngudwls000 | 12:f3816a0f498e | 95 | writeByte(PWR_MGMT_1,CLOCK_SEL_PLL); |
wngudwls000 | 12:f3816a0f498e | 96 | wait_ms(50); |
wngudwls000 | 12:f3816a0f498e | 97 | mRes=10. * 4912. / 32760.0; // for Magenetometer 16BITS |
wngudwls000 | 12:f3816a0f498e | 98 | } |
wngudwls000 | 12:f3816a0f498e | 99 | |
wngudwls000 | 12:f3816a0f498e | 100 | void MPU9250_SPI::setAccelRange(AccelRange range) { |
wngudwls000 | 12:f3816a0f498e | 101 | switch(range) { |
wngudwls000 | 12:f3816a0f498e | 102 | case ACCEL_RANGE_2G: |
wngudwls000 | 12:f3816a0f498e | 103 | aRes = 2.0f/32767.5f; break; |
wngudwls000 | 12:f3816a0f498e | 104 | case ACCEL_RANGE_4G: |
wngudwls000 | 12:f3816a0f498e | 105 | aRes = 4.0f/32767.5f; break; |
wngudwls000 | 12:f3816a0f498e | 106 | case ACCEL_RANGE_8G: |
wngudwls000 | 12:f3816a0f498e | 107 | aRes = 8.0f/32767.5f; break; |
wngudwls000 | 12:f3816a0f498e | 108 | case ACCEL_RANGE_16G: |
wngudwls000 | 12:f3816a0f498e | 109 | aRes = 16.0f/32767.5f; // setting the accel scale to 16G |
wngudwls000 | 12:f3816a0f498e | 110 | break; |
wngudwls000 | 12:f3816a0f498e | 111 | } |
wngudwls000 | 12:f3816a0f498e | 112 | replaceBlock(ACCEL_CONFIG,range,3,2); // addr, value, at, size |
wngudwls000 | 12:f3816a0f498e | 113 | _accelRange = range; |
wngudwls000 | 12:f3816a0f498e | 114 | } |
wngudwls000 | 12:f3816a0f498e | 115 | void MPU9250_SPI::setGyroRange(GyroRange range) { |
wngudwls000 | 12:f3816a0f498e | 116 | switch(range) { |
wngudwls000 | 12:f3816a0f498e | 117 | case GYRO_RANGE_250DPS: |
wngudwls000 | 12:f3816a0f498e | 118 | gRes = 250.0f/32767.5f; break; |
wngudwls000 | 12:f3816a0f498e | 119 | case GYRO_RANGE_500DPS: |
wngudwls000 | 12:f3816a0f498e | 120 | gRes = 500.0f/32767.5f; break; |
wngudwls000 | 12:f3816a0f498e | 121 | case GYRO_RANGE_1000DPS: |
wngudwls000 | 12:f3816a0f498e | 122 | gRes = 1000.0f/32767.5f; break; |
wngudwls000 | 12:f3816a0f498e | 123 | case GYRO_RANGE_2000DPS: |
wngudwls000 | 12:f3816a0f498e | 124 | gRes = 2000.0f/32767.5f ; break; |
wngudwls000 | 12:f3816a0f498e | 125 | } |
wngudwls000 | 12:f3816a0f498e | 126 | replaceBlock(GYRO_CONFIG,range,3,2); |
wngudwls000 | 12:f3816a0f498e | 127 | _gyroRange = range; |
wngudwls000 | 12:f3816a0f498e | 128 | } |
wngudwls000 | 12:f3816a0f498e | 129 | void MPU9250_SPI::setDlpfBandwidth(DlpfBandwidth bandwidth) { |
wngudwls000 | 12:f3816a0f498e | 130 | replaceBlock(ACCEL_CONFIG2,bandwidth,0,4); //Accel DLPF [0:2] |
wngudwls000 | 12:f3816a0f498e | 131 | replaceBlock(MPU_CONFIG,bandwidth,0,3); //Gyro DLPF [0:2] |
wngudwls000 | 12:f3816a0f498e | 132 | _bandwidth = bandwidth; |
wngudwls000 | 12:f3816a0f498e | 133 | } |
wngudwls000 | 12:f3816a0f498e | 134 | |
wngudwls000 | 12:f3816a0f498e | 135 | void MPU9250_SPI::setSampleRate(SampleRate srd){ |
wngudwls000 | 12:f3816a0f498e | 136 | writeByte(SMPLRT_DIV, srd); // sampling rate set |
wngudwls000 | 12:f3816a0f498e | 137 | _srd = srd; |
wngudwls000 | 12:f3816a0f498e | 138 | } |
wngudwls000 | 12:f3816a0f498e | 139 | |
wngudwls000 | 12:f3816a0f498e | 140 | void MPU9250_SPI::enableDataReadyInterrupt() { |
wngudwls000 | 12:f3816a0f498e | 141 | writeByte(INT_PIN_CFG,0x00); // setup interrupt, 50 us pulse |
wngudwls000 | 12:f3816a0f498e | 142 | writeByte(INT_ENABLE,0x01) ; // set to data ready |
wngudwls000 | 12:f3816a0f498e | 143 | } |
wngudwls000 | 12:f3816a0f498e | 144 | |
wngudwls000 | 12:f3816a0f498e | 145 | void MPU9250_SPI::updateSensors(){ |
wngudwls000 | 12:f3816a0f498e | 146 | int16_t MPU9250Data[10]; // MPU9250 accel/gyro 에서 16비트 정수로 7개 저장 |
wngudwls000 | 12:f3816a0f498e | 147 | uint8_t rawData[21]; // 가속도 자이로 원시 데이터 보관 |
wngudwls000 | 12:f3816a0f498e | 148 | writeByte(I2C_SLV0_ADDR,AK8963_I2C_ADDR|SPI_READ); // Set the I2C slave addres of AK8963 and set for read. |
wngudwls000 | 12:f3816a0f498e | 149 | writeByte(I2C_SLV0_REG,AK8963_XOUT_L); // I2C slave 0 register address from where to begin data transfer |
wngudwls000 | 12:f3816a0f498e | 150 | writeByte(I2C_SLV0_CTRL, 0x87); // Read 7 bytes from the magnetometer |
wngudwls000 | 12:f3816a0f498e | 151 | readBytes(ACCEL_XOUT_H, 21, rawData); // 16비트 정수로 7개 저장--> 14byte |
wngudwls000 | 12:f3816a0f498e | 152 | MPU9250Data[0] = ((int16_t)rawData[0] << 8) | rawData[1] ; // signed 16-bit (MSB + LSB) |
wngudwls000 | 12:f3816a0f498e | 153 | MPU9250Data[1] = ((int16_t)rawData[2] << 8) | rawData[3] ; |
wngudwls000 | 12:f3816a0f498e | 154 | MPU9250Data[2] = ((int16_t)rawData[4] << 8) | rawData[5] ; |
wngudwls000 | 12:f3816a0f498e | 155 | MPU9250Data[3] = ((int16_t)rawData[6] << 8) | rawData[7] ; |
wngudwls000 | 12:f3816a0f498e | 156 | MPU9250Data[4] = ((int16_t)rawData[8] << 8) | rawData[9] ; |
wngudwls000 | 12:f3816a0f498e | 157 | MPU9250Data[5] = ((int16_t)rawData[10] << 8) | rawData[11] ; |
wngudwls000 | 12:f3816a0f498e | 158 | MPU9250Data[6] = ((int16_t)rawData[12] << 8) | rawData[13] ; |
wngudwls000 | 12:f3816a0f498e | 159 | MPU9250Data[7] = (((int16_t)rawData[15]) << 8) |rawData[14]; |
wngudwls000 | 12:f3816a0f498e | 160 | MPU9250Data[8] = (((int16_t)rawData[17]) << 8) |rawData[16]; |
wngudwls000 | 12:f3816a0f498e | 161 | MPU9250Data[9] = (((int16_t)rawData[19]) << 8) |rawData[18]; |
wngudwls000 | 12:f3816a0f498e | 162 | a.x = (float)MPU9250Data[0] * aRes - accelBias.x; // 가속도 해상도와 바이어스 보정 |
wngudwls000 | 12:f3816a0f498e | 163 | a.y = (float)MPU9250Data[1] * aRes - accelBias.y; |
wngudwls000 | 12:f3816a0f498e | 164 | a.z = (float)MPU9250Data[2] * aRes - accelBias.z; |
wngudwls000 | 12:f3816a0f498e | 165 | g.x = (float)MPU9250Data[4] * gRes - gyroBias.x; // 자이로 해상도 보정 |
wngudwls000 | 12:f3816a0f498e | 166 | g.y = (float)MPU9250Data[5] * gRes - gyroBias.y; // 자이로 바이어스는 칩내부에서 보정함!!! |
wngudwls000 | 12:f3816a0f498e | 167 | g.z = (float)MPU9250Data[6] * gRes - gyroBias.z; |
wngudwls000 | 12:f3816a0f498e | 168 | m.x = (float)(MPU9250Data[7] * mRes * magCalibration.x - magBias.x) * magScale.x; |
wngudwls000 | 12:f3816a0f498e | 169 | m.y = (float)(MPU9250Data[8] * mRes * magCalibration.y - magBias.y) * magScale.y; |
wngudwls000 | 12:f3816a0f498e | 170 | m.z = (float)(MPU9250Data[9] * mRes * magCalibration.z - magBias.z) * magScale.z; |
wngudwls000 | 12:f3816a0f498e | 171 | } |
wngudwls000 | 12:f3816a0f498e | 172 | void MPU9250_SPI::updateAccelGyro() { |
wngudwls000 | 12:f3816a0f498e | 173 | int16_t MPU9250Data[7]; // MPU9250 accel/gyro 에서 16비트 정수로 7개 저장 |
wngudwls000 | 12:f3816a0f498e | 174 | readMPU9250Data(MPU9250Data); // 읽으면 INT 핀 해제 |
wngudwls000 | 12:f3816a0f498e | 175 | a.x = (float)MPU9250Data[0] * aRes - accelBias.x; // 가속도 해상도와 바이어스 보정 |
wngudwls000 | 12:f3816a0f498e | 176 | a.y = (float)MPU9250Data[1] * aRes - accelBias.y; |
wngudwls000 | 12:f3816a0f498e | 177 | a.z = (float)MPU9250Data[2] * aRes - accelBias.z; |
wngudwls000 | 12:f3816a0f498e | 178 | g.x = (float)MPU9250Data[4] * gRes - gyroBias.x; // 자이로 해상도 보정 |
wngudwls000 | 12:f3816a0f498e | 179 | g.y = (float)MPU9250Data[5] * gRes - gyroBias.y; // |
wngudwls000 | 12:f3816a0f498e | 180 | g.z = (float)MPU9250Data[6] * gRes - gyroBias.z; |
wngudwls000 | 12:f3816a0f498e | 181 | } |
wngudwls000 | 12:f3816a0f498e | 182 | |
wngudwls000 | 12:f3816a0f498e | 183 | void MPU9250_SPI::readMPU9250Data(int16_t * destination) { |
wngudwls000 | 12:f3816a0f498e | 184 | uint8_t rawData[14]; // 가속도 자이로 원시 데이터 보관 |
wngudwls000 | 12:f3816a0f498e | 185 | readBytes(ACCEL_XOUT_H, 14, rawData); // 16비트 정수로 7개 저장--> 14byte |
wngudwls000 | 12:f3816a0f498e | 186 | destination[0] = ((int16_t)rawData[0] << 8) | rawData[1] ; // signed 16-bit (MSB + LSB) |
wngudwls000 | 12:f3816a0f498e | 187 | destination[1] = ((int16_t)rawData[2] << 8) | rawData[3] ; |
wngudwls000 | 12:f3816a0f498e | 188 | destination[2] = ((int16_t)rawData[4] << 8) | rawData[5] ; |
wngudwls000 | 12:f3816a0f498e | 189 | destination[3] = ((int16_t)rawData[6] << 8) | rawData[7] ; |
wngudwls000 | 12:f3816a0f498e | 190 | destination[4] = ((int16_t)rawData[8] << 8) | rawData[9] ; |
wngudwls000 | 12:f3816a0f498e | 191 | destination[5] = ((int16_t)rawData[10] << 8) | rawData[11] ; |
wngudwls000 | 12:f3816a0f498e | 192 | destination[6] = ((int16_t)rawData[12] << 8) | rawData[13] ; |
wngudwls000 | 12:f3816a0f498e | 193 | } |
wngudwls000 | 12:f3816a0f498e | 194 | |
wngudwls000 | 12:f3816a0f498e | 195 | void MPU9250_SPI::updateMag() { |
wngudwls000 | 12:f3816a0f498e | 196 | int16_t magCount[3] = {0, 0, 0}; // 16-bit 지자기 데이터 |
wngudwls000 | 12:f3816a0f498e | 197 | readMagData(magCount); // 지자기 데이터 읽기 |
wngudwls000 | 12:f3816a0f498e | 198 | // 지자기 해상도, 검정값, 바이어스 보정, 검정값 (magCalibration[] )은 칩의 ROM에서 |
wngudwls000 | 12:f3816a0f498e | 199 | m.x = (float)(magCount[0] * mRes * magCalibration.x - magBias.x) * magScale.x; |
wngudwls000 | 12:f3816a0f498e | 200 | m.y = (float)(magCount[1] * mRes * magCalibration.y - magBias.y) * magScale.y; |
wngudwls000 | 12:f3816a0f498e | 201 | m.z = (float)(magCount[2] * mRes * magCalibration.z - magBias.z) * magScale.z; |
wngudwls000 | 12:f3816a0f498e | 202 | } |
wngudwls000 | 12:f3816a0f498e | 203 | void MPU9250_SPI::readMagData(int16_t * destination) { |
wngudwls000 | 12:f3816a0f498e | 204 | uint8_t rawData[7]; // x/y/z gyro register data, ST2 register stored here, must read ST2 at end of data acquisition |
wngudwls000 | 12:f3816a0f498e | 205 | if(readAK8963Byte(AK8963_ST1) & 0x01) { // wait for magnetometer data ready bit to be set |
wngudwls000 | 12:f3816a0f498e | 206 | readAK8963Bytes(AK8963_XOUT_L, 7,rawData); // Read the six raw data and ST2 registers sequentially into data array |
wngudwls000 | 12:f3816a0f498e | 207 | uint8_t c = rawData[6]; // End data read by reading ST2 register |
wngudwls000 | 12:f3816a0f498e | 208 | if(!(c & 0x08)) { // Check if magnetic sensor overflow set, if not then report data |
wngudwls000 | 12:f3816a0f498e | 209 | destination[0] = ((int16_t)rawData[1] << 8) | rawData[0]; // Turn the MSB and LSB into a signed 16-bit value |
wngudwls000 | 12:f3816a0f498e | 210 | destination[1] = ((int16_t)rawData[3] << 8) | rawData[2]; // Data stored as little Endian |
wngudwls000 | 12:f3816a0f498e | 211 | destination[2] = ((int16_t)rawData[5] << 8) | rawData[4]; |
wngudwls000 | 12:f3816a0f498e | 212 | } |
wngudwls000 | 12:f3816a0f498e | 213 | } |
wngudwls000 | 12:f3816a0f498e | 214 | } |
wngudwls000 | 12:f3816a0f498e | 215 | |
wngudwls000 | 12:f3816a0f498e | 216 | void MPU9250_SPI::writeByte(uint8_t subAddress, uint8_t data){ /* write data to device */ |
wngudwls000 | 12:f3816a0f498e | 217 | // _spi->beginTransaction(SPISettings(SPI_HS_CLOCK, MSBFIRST, SPI_MODE3)); // begin the transaction |
wngudwls000 | 12:f3816a0f498e | 218 | // digitalWrite(_csPin,LOW); // select the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 219 | // _spi->transfer(subAddress); // write the register address |
wngudwls000 | 12:f3816a0f498e | 220 | // _spi->transfer(data); // write the data |
wngudwls000 | 12:f3816a0f498e | 221 | // digitalWrite(_csPin,HIGH); // deselect the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 222 | // _spi->endTransaction(); // end the transaction |
wngudwls000 | 12:f3816a0f498e | 223 | _spi.frequency(SPI_LS_CLOCK); // setup clock |
wngudwls000 | 12:f3816a0f498e | 224 | _csPin=0; // select the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 225 | _spi.write(subAddress); // write the register address |
wngudwls000 | 12:f3816a0f498e | 226 | _spi.write(data); // write the data |
wngudwls000 | 12:f3816a0f498e | 227 | _csPin=1; // deselect the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 228 | } |
wngudwls000 | 12:f3816a0f498e | 229 | uint8_t MPU9250_SPI::readByte(uint8_t subAddress){ |
wngudwls000 | 12:f3816a0f498e | 230 | // _spi->beginTransaction(SPISettings(SPI_HS_CLOCK, MSBFIRST, SPI_MODE3)); |
wngudwls000 | 12:f3816a0f498e | 231 | // digitalWrite(_csPin,LOW); // select the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 232 | // _spi->transfer(subAddress | SPI_READ); // specify the starting register address |
wngudwls000 | 12:f3816a0f498e | 233 | // uint8_t data = _spi->transfer(0x00); // read the data |
wngudwls000 | 12:f3816a0f498e | 234 | // digitalWrite(_csPin,HIGH); // deselect the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 235 | // _spi->endTransaction(); // end the transaction |
wngudwls000 | 12:f3816a0f498e | 236 | |
wngudwls000 | 12:f3816a0f498e | 237 | _spi.frequency(SPI_LS_CLOCK); // setup clock |
wngudwls000 | 12:f3816a0f498e | 238 | _csPin=0; // select the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 239 | _spi.write(subAddress| SPI_READ); // use READ MASK |
wngudwls000 | 12:f3816a0f498e | 240 | uint8_t data =_spi.write(0); // write any to get data |
wngudwls000 | 12:f3816a0f498e | 241 | _csPin=1; // deselect the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 242 | return data; |
wngudwls000 | 12:f3816a0f498e | 243 | } |
wngudwls000 | 12:f3816a0f498e | 244 | |
wngudwls000 | 12:f3816a0f498e | 245 | void MPU9250_SPI::readBytes(uint8_t subAddress, uint8_t cnt, uint8_t* dest){ |
wngudwls000 | 12:f3816a0f498e | 246 | // _spi->beginTransaction(SPISettings(SPI_HS_CLOCK, MSBFIRST, SPI_MODE3)); |
wngudwls000 | 12:f3816a0f498e | 247 | // digitalWrite(_csPin,LOW); // select the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 248 | // _spi->transfer(subAddress | SPI_READ); // specify the starting register address |
wngudwls000 | 12:f3816a0f498e | 249 | // for(uint8_t i = 0; i < count; i++){ |
wngudwls000 | 12:f3816a0f498e | 250 | // dest[i] = _spi->transfer(0x00); // read the data |
wngudwls000 | 12:f3816a0f498e | 251 | // } |
wngudwls000 | 12:f3816a0f498e | 252 | // digitalWrite(_csPin,HIGH); // deselect the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 253 | // _spi->endTransaction(); // end the transaction |
wngudwls000 | 12:f3816a0f498e | 254 | _spi.frequency(SPI_HS_CLOCK); // setup clock |
wngudwls000 | 12:f3816a0f498e | 255 | _csPin=0; // select the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 256 | _spi.write(subAddress | SPI_READ); // specify the starting register address |
wngudwls000 | 12:f3816a0f498e | 257 | for(uint8_t i = 0; i < cnt; i++){ |
wngudwls000 | 12:f3816a0f498e | 258 | dest[i] = _spi.write(0x00); // read the data |
wngudwls000 | 12:f3816a0f498e | 259 | } |
wngudwls000 | 12:f3816a0f498e | 260 | _csPin=1; // deselect the MPU9250 chip |
wngudwls000 | 12:f3816a0f498e | 261 | } |
wngudwls000 | 12:f3816a0f498e | 262 | |
wngudwls000 | 12:f3816a0f498e | 263 | void MPU9250_SPI::writeAK8963Byte(uint8_t subAddress, uint8_t data){ |
wngudwls000 | 12:f3816a0f498e | 264 | writeByte(I2C_SLV0_ADDR,AK8963_I2C_ADDR) ; // set slave 0 to the AK8963 and set for write |
wngudwls000 | 12:f3816a0f498e | 265 | writeByte(I2C_SLV0_REG,subAddress) ; // set the register to the desired AK8963 sub address |
wngudwls000 | 12:f3816a0f498e | 266 | writeByte(I2C_SLV0_DO,data) ; // store the data for write |
wngudwls000 | 12:f3816a0f498e | 267 | writeByte(I2C_SLV0_CTRL,I2C_SLV0_EN | (uint8_t)1); // enable I2C and send 1 byte |
wngudwls000 | 12:f3816a0f498e | 268 | } |
wngudwls000 | 12:f3816a0f498e | 269 | |
wngudwls000 | 12:f3816a0f498e | 270 | void MPU9250_SPI::readAK8963Bytes(uint8_t subAddress, uint8_t count, uint8_t* dest){ |
wngudwls000 | 12:f3816a0f498e | 271 | writeByte(I2C_SLV0_ADDR,AK8963_I2C_ADDR | I2C_READ_FLAG) ; // set slave 0 to the AK8963 and set for read |
wngudwls000 | 12:f3816a0f498e | 272 | writeByte(I2C_SLV0_REG,subAddress) ; // set the register to the desired AK8963 sub address |
wngudwls000 | 12:f3816a0f498e | 273 | writeByte(I2C_SLV0_CTRL,I2C_SLV0_EN | count); // enable I2C and request the bytes |
wngudwls000 | 12:f3816a0f498e | 274 | wait_ms(1); // takes some time for these registers to fill |
wngudwls000 | 12:f3816a0f498e | 275 | readBytes(EXT_SENS_DATA_00,count,dest); // read the bytes off the MPU9250 EXT_SENS_DATA registers |
wngudwls000 | 12:f3816a0f498e | 276 | } |
wngudwls000 | 12:f3816a0f498e | 277 | |
wngudwls000 | 12:f3816a0f498e | 278 | uint8_t MPU9250_SPI::readAK8963Byte(uint8_t subAddress){ |
wngudwls000 | 12:f3816a0f498e | 279 | writeByte(I2C_SLV0_ADDR,AK8963_I2C_ADDR | I2C_READ_FLAG) ; // set slave 0 to the AK8963 and set for read |
wngudwls000 | 12:f3816a0f498e | 280 | writeByte(I2C_SLV0_REG,subAddress) ; // set the register to the desired AK8963 sub address |
wngudwls000 | 12:f3816a0f498e | 281 | writeByte(I2C_SLV0_CTRL,I2C_SLV0_EN | (uint8_t)1); // enable I2C and request the bytes |
wngudwls000 | 12:f3816a0f498e | 282 | wait_ms(11); // takes some time for these registers to fill |
wngudwls000 | 12:f3816a0f498e | 283 | return readByte(EXT_SENS_DATA_00); // read the bytes off the MPU9250 EXT_SENS_DATA registers |
wngudwls000 | 12:f3816a0f498e | 284 | } |
wngudwls000 | 12:f3816a0f498e | 285 | void MPU9250_SPI::replaceBlock(uint8_t address, uint8_t block, uint8_t at, uint8_t sz){ |
wngudwls000 | 12:f3816a0f498e | 286 | uint8_t data=readByte(address); |
wngudwls000 | 12:f3816a0f498e | 287 | data &= ~(((1<<sz)-1)<<at); |
wngudwls000 | 12:f3816a0f498e | 288 | data |= block<<at; |
wngudwls000 | 12:f3816a0f498e | 289 | writeByte(address, data ); |
wngudwls000 | 12:f3816a0f498e | 290 | } |
wngudwls000 | 12:f3816a0f498e | 291 | void MPU9250_SPI::replaceBlockAK(uint8_t address, uint8_t block, uint8_t at, uint8_t sz){ |
wngudwls000 | 12:f3816a0f498e | 292 | uint8_t data=readByte(address); |
wngudwls000 | 12:f3816a0f498e | 293 | data &= ~(((1<<sz)-1)<<at); |
wngudwls000 | 12:f3816a0f498e | 294 | data |= block<<at; |
wngudwls000 | 12:f3816a0f498e | 295 | writeAK8963Byte(address, data ); |
wngudwls000 | 12:f3816a0f498e | 296 | } |
wngudwls000 | 12:f3816a0f498e | 297 |