Enligt internet så har denna gyro adressen 0x68 om AD0 är GND eller 0x69 om AD0 är VCC.
Men för mig så var adressen 0x79.
Jag testade även att köra biblioteket och status blev -1.
Kod: Markera allt
int status = MPU9250_begin_I2C(&mpu, &hi2c1, 0x79);
Fråga:
Kan det vara så att jag köpte en MPU9255 när det stod MPU9250? För mitt bibliotek verkar ej kunna fungera med min gyro.
Kod: Markera allt
/* writes a byte to MPU9250 register given a register address and data */
static int writeRegister(MPU9250_SPI_I2C *mpu, uint8_t subAddress, uint8_t data) {
/* write data to device */
uint8_t pData[2] = { subAddress, data };
if (mpu->useSPI) {
HAL_GPIO_WritePin(mpu->MPU_CS_GPIO_Port, mpu->MPU_CS_GPIO_Pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(mpu->hspi, pData, 2, 10);
HAL_GPIO_WritePin(mpu->MPU_CS_GPIO_Port, mpu->MPU_CS_GPIO_Pin, GPIO_PIN_SET);
} else {
HAL_I2C_Master_Transmit(mpu->hi2c, mpu->address, pData, 2, 10);
}
HAL_Delay(10);
/* read back the register */
readRegisters(mpu, subAddress, 1, mpu->buffer);
/* check the read back register against the written register */
if (mpu->buffer[0] == data) {
return 1;
} else {
return -1;
}
}
Kod: Markera allt
#include "MPU9250.h"
// scale factors
const float tempScale = 333.87f;
const float tempOffset = 21.0f;
const size_t numSamples = 100;
// magnetometer bias and scale factor estimation
const uint16_t maxCounts = 1000;
const float deltaThresh = 0.3f;
const uint8_t coeff = 8;
// transformation matrix
/* transform the accel and gyro axes to match the magnetometer axes */
const int16_t tX[3] = { 0, 1, 0 };
const int16_t tY[3] = { 1, 0, 0 };
const int16_t tZ[3] = { 0, 0, -1 };
// constants
const float G = 9.807f;
const float d2r = 3.14159265359f / 180.0f;
// MPU9250 registers
const uint8_t ACCEL_OUT = 0x3B;
const uint8_t GYRO_OUT = 0x43;
const uint8_t TEMP_OUT = 0x41;
const uint8_t EXT_SENS_DATA_00 = 0x49;
const uint8_t ACCEL_CONFIG = 0x1C;
const uint8_t ACCEL_FS_SEL_2G = 0x00;
const uint8_t ACCEL_FS_SEL_4G = 0x08;
const uint8_t ACCEL_FS_SEL_8G = 0x10;
const uint8_t ACCEL_FS_SEL_16G = 0x18;
const uint8_t GYRO_CONFIG = 0x1B;
const uint8_t GYRO_FS_SEL_250DPS = 0x00;
const uint8_t GYRO_FS_SEL_500DPS = 0x08;
const uint8_t GYRO_FS_SEL_1000DPS = 0x10;
const uint8_t GYRO_FS_SEL_2000DPS = 0x18;
const uint8_t ACCEL_CONFIG2 = 0x1D;
const uint8_t ACCEL_DLPF_184 = 0x01;
const uint8_t ACCEL_DLPF_92 = 0x02;
const uint8_t ACCEL_DLPF_41 = 0x03;
const uint8_t ACCEL_DLPF_20 = 0x04;
const uint8_t ACCEL_DLPF_10 = 0x05;
const uint8_t ACCEL_DLPF_5 = 0x06;
const uint8_t CONFIG = 0x1A;
const uint8_t GYRO_DLPF_184 = 0x01;
const uint8_t GYRO_DLPF_92 = 0x02;
const uint8_t GYRO_DLPF_41 = 0x03;
const uint8_t GYRO_DLPF_20 = 0x04;
const uint8_t GYRO_DLPF_10 = 0x05;
const uint8_t GYRO_DLPF_5 = 0x06;
const uint8_t SMPDIV = 0x19;
const uint8_t INT_PIN_CFG = 0x37;
const uint8_t INT_ENABLE = 0x38;
const uint8_t INT_DISABLE = 0x00;
const uint8_t INT_PULSE_50US = 0x00;
const uint8_t INT_WOM_EN = 0x40;
const uint8_t INT_RAW_RDY_EN = 0x01;
const uint8_t PWR_MGMNT_1 = 0x6B;
const uint8_t PWR_CYCLE = 0x20;
const uint8_t PWR_RESET = 0x80;
const uint8_t CLOCK_SEL_PLL = 0x01;
const uint8_t PWR_MGMNT_2 = 0x6C;
const uint8_t SEN_ENABLE = 0x00;
const uint8_t DIS_GYRO = 0x07;
const uint8_t USER_CTRL = 0x6A;
const uint8_t I2C_MST_EN = 0x20;
const uint8_t I2C_MST_CLK = 0x0D;
const uint8_t I2C_MST_CTRL = 0x24;
const uint8_t I2C_SLV0_ADDR = 0x25;
const uint8_t I2C_SLV0_REG = 0x26;
const uint8_t I2C_SLV0_DO = 0x63;
const uint8_t I2C_SLV0_CTRL = 0x27;
const uint8_t I2C_SLV0_EN = 0x80;
const uint8_t I2C_READ_FLAG = 0x80;
const uint8_t MOT_DETECT_CTRL = 0x69;
const uint8_t ACCEL_INTEL_EN = 0x80;
const uint8_t ACCEL_INTEL_MODE = 0x40;
const uint8_t LP_ACCEL_ODR = 0x1E;
const uint8_t WOM_THR = 0x1F;
const uint8_t WHO_AM_I = 0x75;
const uint8_t FIFO_EN = 0x23;
const uint8_t FIFO_TEMP = 0x80;
const uint8_t FIFO_GYRO = 0x70;
const uint8_t FIFO_ACCEL = 0x08;
const uint8_t FIFO_MAG = 0x01;
const uint8_t FIFO_COUNT = 0x72;
const uint8_t FIFO_READ = 0x74;
// AK8963 registers
const uint8_t AK8963_I2C_ADDR = 0x0C;
const uint8_t AK8963_HXL = 0x03;
const uint8_t AK8963_CNTL1 = 0x0A;
const uint8_t AK8963_PWR_DOWN = 0x00;
const uint8_t AK8963_CNT_MEAS1 = 0x12;
const uint8_t AK8963_CNT_MEAS2 = 0x16;
const uint8_t AK8963_FUSE_ROM = 0x0F;
const uint8_t AK8963_CNTL2 = 0x0B;
const uint8_t AK8963_RESET = 0x01;
const uint8_t AK8963_ASA = 0x10;
const uint8_t AK8963_WHO_AM_I = 0x00;
// Private functions
static int writeRegister(MPU9250_SPI_I2C *mpu, uint8_t subAddress, uint8_t data);
static int readRegisters(MPU9250_SPI_I2C *mpu, uint8_t subAddress, uint8_t count, uint8_t *dest);
static int writeAK8963Register(MPU9250_SPI_I2C *mpu, uint8_t subAddress, uint8_t data);
static int readAK8963Registers(MPU9250_SPI_I2C *mpu, uint8_t subAddress, uint8_t count, uint8_t *dest);
static int whoAmI(MPU9250_SPI_I2C *mpu);
static int whoAmIAK8963(MPU9250_SPI_I2C *mpu);
static long map(long x, long in_min, long in_max, long out_min, long out_max);
static int MPU9250_begin(MPU9250_SPI_I2C *mpu);
/* Use SPI communcation */
int MPU9250_begin_SPI(MPU9250_SPI_I2C *mpu, SPI_HandleTypeDef *hspi, GPIO_TypeDef *MPU_CS_GPIO_Port, uint16_t MPU_CS_GPIO_Pin) {
mpu->useSPI = true;
mpu->MPU_CS_GPIO_Pin = MPU_CS_GPIO_Pin;
mpu->MPU_CS_GPIO_Port = MPU_CS_GPIO_Port;
mpu->hspi = hspi;
return MPU9250_begin(mpu);
}
/* Use I2C communcation */
int MPU9250_begin_I2C(MPU9250_SPI_I2C *mpu, I2C_HandleTypeDef *hi2c, uint8_t address) {
mpu->useSPI = false;
mpu->hi2c = hi2c;
mpu->address = address;
return MPU9250_begin(mpu);
}
/* starts communication with the MPU-9250 */
static int MPU9250_begin(MPU9250_SPI_I2C *mpu) {
mpu->axs = 1.0f;
mpu->ays = 1.0f;
mpu->azs = 1.0f;
mpu->hxs = 1.0f;
mpu->hys = 1.0f;
mpu->hzs = 1.0f;
// select clock source to gyro
if (writeRegister(mpu, PWR_MGMNT_1, CLOCK_SEL_PLL) < 0) {
return -1;
}
// enable I2C master mode
if (writeRegister(mpu, USER_CTRL, I2C_MST_EN) < 0) {
return -2;
}
// set the I2C bus speed to 400 kHz
if (writeRegister(mpu, I2C_MST_CTRL, I2C_MST_CLK) < 0) {
return -3;
}
// set AK8963 to Power Down
writeAK8963Register(mpu, AK8963_CNTL1, AK8963_PWR_DOWN);
// reset the MPU9250
writeRegister(mpu, PWR_MGMNT_1, PWR_RESET);
// wait for MPU-9250 to come back up
HAL_Delay(1);
// reset the AK8963
writeAK8963Register(mpu, AK8963_CNTL2, AK8963_RESET);
// select clock source to gyro
if (writeRegister(mpu, PWR_MGMNT_1, CLOCK_SEL_PLL) < 0) {
return -4;
}
// check the WHO AM I byte, expected value is 0x71 (decimal 113) or 0x73 (decimal 115)
if ((whoAmI(mpu) != 113) && (whoAmI(mpu) != 115)) {
return -5;
}
// enable accelerometer and gyro
if (writeRegister(mpu, PWR_MGMNT_2, SEN_ENABLE) < 0) {
return -6;
}
// setting accel range to 16G as default
if (writeRegister(mpu, ACCEL_CONFIG, ACCEL_FS_SEL_16G) < 0) {
return -7;
}
mpu->accelScale = G * 16.0f / 32767.5f; // setting the accel scale to 16G
mpu->accelRange = ACCEL_RANGE_16G;
// setting the gyro range to 2000DPS as default
if (writeRegister(mpu, GYRO_CONFIG, GYRO_FS_SEL_2000DPS) < 0) {
return -8;
}
mpu->gyroScale = 2000.0f / 32767.5f * d2r; // setting the gyro scale to 2000DPS
mpu->gyroRange = GYRO_RANGE_2000DPS;
// setting bandwidth to 184Hz as default
if (writeRegister(mpu, ACCEL_CONFIG2, ACCEL_DLPF_184) < 0) {
return -9;
}
if (writeRegister(mpu, CONFIG, GYRO_DLPF_184) < 0) { // setting gyro bandwidth to 184Hz
return -10;
}
mpu->bandwidth = DLPF_BANDWIDTH_184HZ;
// setting the sample rate divider to 0 as default
if (writeRegister(mpu, SMPDIV, 0x00) < 0) {
return -11;
}
mpu->srd = 0;
// enable I2C master mode
if (writeRegister(mpu, USER_CTRL, I2C_MST_EN) < 0) {
return -12;
}
// set the I2C bus speed to 400 kHz
if (writeRegister(mpu, I2C_MST_CTRL, I2C_MST_CLK) < 0) {
return -13;
}
// check AK8963 WHO AM I register, expected value is 0x48 (decimal 72)
if (whoAmIAK8963(mpu) != 72) {
return -14;
}
/* get the magnetometer calibration */
// set AK8963 to Power Down
if (writeAK8963Register(mpu, AK8963_CNTL1, AK8963_PWR_DOWN) < 0) {
return -15;
}
HAL_Delay(100); // long wait between AK8963 mode changes
// set AK8963 to FUSE ROM access
if (writeAK8963Register(mpu, AK8963_CNTL1, AK8963_FUSE_ROM) < 0) {
return -16;
}
HAL_Delay(100); // long wait between AK8963 mode changes
// read the AK8963 ASA registers and compute magnetometer scale factors
readAK8963Registers(mpu, AK8963_ASA, 3, mpu->buffer);
mpu->magScaleX = ((((float) mpu->buffer[0]) - 128.0f) / (256.0f) + 1.0f) * 4912.0f / 32760.0f; // micro Tesla
mpu->magScaleY = ((((float) mpu->buffer[1]) - 128.0f) / (256.0f) + 1.0f) * 4912.0f / 32760.0f; // micro Tesla
mpu->magScaleZ = ((((float) mpu->buffer[2]) - 128.0f) / (256.0f) + 1.0f) * 4912.0f / 32760.0f; // micro Tesla
// set AK8963 to Power Down
if (writeAK8963Register(mpu, AK8963_CNTL1, AK8963_PWR_DOWN) < 0) {
return -17;
}
HAL_Delay(100); // long wait between AK8963 mode changes
// set AK8963 to 16 bit resolution, 100 Hz update rate
if (writeAK8963Register(mpu, AK8963_CNTL1, AK8963_CNT_MEAS2) < 0) {
return -18;
}
HAL_Delay(100); // long wait between AK8963 mode changes
// select clock source to gyro
if (writeRegister(mpu, PWR_MGMNT_1, CLOCK_SEL_PLL) < 0) {
return -19;
}
// instruct the MPU9250 to get 7 bytes of data from the AK8963 at the sample rate
readAK8963Registers(mpu, AK8963_HXL, 7, mpu->buffer);
// estimate gyro bias
if (MPU9250_calibrateGyro(mpu) < 0) {
return -20;
}
// successful init, return 1
return 1;
}
/* sets the accelerometer full scale range to values other than default */
int MPU9250_setAccelRange(MPU9250_SPI_I2C *mpu, AccelRange range) {
switch (range) {
case ACCEL_RANGE_2G: {
// setting the accel range to 2G
if (writeRegister(mpu, ACCEL_CONFIG, ACCEL_FS_SEL_2G) < 0) {
return -1;
}
mpu->accelScale = G * 2.0f / 32767.5f; // setting the accel scale to 2G
break;
}
case ACCEL_RANGE_4G: {
// setting the accel range to 4G
if (writeRegister(mpu, ACCEL_CONFIG, ACCEL_FS_SEL_4G) < 0) {
return -1;
}
mpu->accelScale = G * 4.0f / 32767.5f; // setting the accel scale to 4G
break;
}
case ACCEL_RANGE_8G: {
// setting the accel range to 8G
if (writeRegister(mpu, ACCEL_CONFIG, ACCEL_FS_SEL_8G) < 0) {
return -1;
}
mpu->accelScale = G * 8.0f / 32767.5f; // setting the accel scale to 8G
break;
}
case ACCEL_RANGE_16G: {
// setting the accel range to 16G
if (writeRegister(mpu, ACCEL_CONFIG, ACCEL_FS_SEL_16G) < 0) {
return -1;
}
mpu->accelScale = G * 16.0f / 32767.5f; // setting the accel scale to 16G
break;
}
}
mpu->accelRange = range;
return 1;
}
/* sets the gyro full scale range to values other than default */
int MPU9250_setGyroRange(MPU9250_SPI_I2C *mpu, GyroRange range) {
switch (range) {
case GYRO_RANGE_250DPS: {
// setting the gyro range to 250DPS
if (writeRegister(mpu, GYRO_CONFIG, GYRO_FS_SEL_250DPS) < 0) {
return -1;
}
mpu->gyroScale = 250.0f / 32767.5f * d2r; // setting the gyro scale to 250DPS
break;
}
case GYRO_RANGE_500DPS: {
// setting the gyro range to 500DPS
if (writeRegister(mpu, GYRO_CONFIG, GYRO_FS_SEL_500DPS) < 0) {
return -1;
}
mpu->gyroScale = 500.0f / 32767.5f * d2r; // setting the gyro scale to 500DPS
break;
}
case GYRO_RANGE_1000DPS: {
// setting the gyro range to 1000DPS
if (writeRegister(mpu, GYRO_CONFIG, GYRO_FS_SEL_1000DPS) < 0) {
return -1;
}
mpu->gyroScale = 1000.0f / 32767.5f * d2r; // setting the gyro scale to 1000DPS
break;
}
case GYRO_RANGE_2000DPS: {
// setting the gyro range to 2000DPS
if (writeRegister(mpu, GYRO_CONFIG, GYRO_FS_SEL_2000DPS) < 0) {
return -1;
}
mpu->gyroScale = 2000.0f / 32767.5f * d2r; // setting the gyro scale to 2000DPS
break;
}
}
mpu->gyroRange = range;
return 1;
}
/* sets the DLPF bandwidth to values other than default */
int MPU9250_setDlpfBandwidth(MPU9250_SPI_I2C *mpu, DlpfBandwidth bandwidth) {
switch (bandwidth) {
case DLPF_BANDWIDTH_184HZ: {
if (writeRegister(mpu, ACCEL_CONFIG2, ACCEL_DLPF_184) < 0) { // setting accel bandwidth to 184Hz
return -1;
}
if (writeRegister(mpu, CONFIG, GYRO_DLPF_184) < 0) { // setting gyro bandwidth to 184Hz
return -2;
}
break;
}
case DLPF_BANDWIDTH_92HZ: {
if (writeRegister(mpu, ACCEL_CONFIG2, ACCEL_DLPF_92) < 0) { // setting accel bandwidth to 92Hz
return -1;
}
if (writeRegister(mpu, CONFIG, GYRO_DLPF_92) < 0) { // setting gyro bandwidth to 92Hz
return -2;
}
break;
}
case DLPF_BANDWIDTH_41HZ: {
if (writeRegister(mpu, ACCEL_CONFIG2, ACCEL_DLPF_41) < 0) { // setting accel bandwidth to 41Hz
return -1;
}
if (writeRegister(mpu, CONFIG, GYRO_DLPF_41) < 0) { // setting gyro bandwidth to 41Hz
return -2;
}
break;
}
case DLPF_BANDWIDTH_20HZ: {
if (writeRegister(mpu, ACCEL_CONFIG2, ACCEL_DLPF_20) < 0) { // setting accel bandwidth to 20Hz
return -1;
}
if (writeRegister(mpu, CONFIG, GYRO_DLPF_20) < 0) { // setting gyro bandwidth to 20Hz
return -2;
}
break;
}
case DLPF_BANDWIDTH_10HZ: {
if (writeRegister(mpu, ACCEL_CONFIG2, ACCEL_DLPF_10) < 0) { // setting accel bandwidth to 10Hz
return -1;
}
if (writeRegister(mpu, CONFIG, GYRO_DLPF_10) < 0) { // setting gyro bandwidth to 10Hz
return -2;
}
break;
}
case DLPF_BANDWIDTH_5HZ: {
if (writeRegister(mpu, ACCEL_CONFIG2, ACCEL_DLPF_5) < 0) { // setting accel bandwidth to 5Hz
return -1;
}
if (writeRegister(mpu, CONFIG, GYRO_DLPF_5) < 0) { // setting gyro bandwidth to 5Hz
return -2;
}
break;
}
}
mpu->bandwidth = bandwidth;
return 1;
}
/* sets the sample rate divider to values other than default */
int MPU9250_setSrd(MPU9250_SPI_I2C *mpu, uint8_t srd) {
/* setting the sample rate divider to 19 to facilitate setting up magnetometer */
if (writeRegister(mpu, SMPDIV, 19) < 0) { // setting the sample rate divider
return -1;
}
if (srd > 9) {
// set AK8963 to Power Down
if (writeAK8963Register(mpu, AK8963_CNTL1, AK8963_PWR_DOWN) < 0) {
return -2;
}
HAL_Delay(100); // long wait between AK8963 mode changes
// set AK8963 to 16 bit resolution, 8 Hz update rate
if (writeAK8963Register(mpu, AK8963_CNTL1, AK8963_CNT_MEAS1) < 0) {
return -3;
}
HAL_Delay(100); // long wait between AK8963 mode changes
// instruct the MPU9250 to get 7 bytes of data from the AK8963 at the sample rate
readAK8963Registers(mpu, AK8963_HXL, 7, mpu->buffer);
} else {
// set AK8963 to Power Down
if (writeAK8963Register(mpu, AK8963_CNTL1, AK8963_PWR_DOWN) < 0) {
return -2;
}
HAL_Delay(100); // long wait between AK8963 mode changes
// set AK8963 to 16 bit resolution, 100 Hz update rate
if (writeAK8963Register(mpu, AK8963_CNTL1, AK8963_CNT_MEAS2) < 0) {
return -3;
}
HAL_Delay(100); // long wait between AK8963 mode changes
// instruct the MPU9250 to get 7 bytes of data from the AK8963 at the sample rate
readAK8963Registers(mpu, AK8963_HXL, 7, mpu->buffer);
}
/* setting the sample rate divider */
if (writeRegister(mpu, SMPDIV, srd) < 0) { // setting the sample rate divider
return -4;
}
mpu->srd = srd;
return 1;
}
/* enables the data ready interrupt */
int MPU9250_enableDataReadyInterrupt(MPU9250_SPI_I2C *mpu) {
/* setting the interrupt */
if (writeRegister(mpu, INT_PIN_CFG, INT_PULSE_50US) < 0) { // setup interrupt, 50 us pulse
return -1;
}
if (writeRegister(mpu, INT_ENABLE, INT_RAW_RDY_EN) < 0) { // set to data ready
return -2;
}
return 1;
}
/* disables the data ready interrupt */
int MPU9250_disableDataReadyInterrupt(MPU9250_SPI_I2C *mpu) {
if (writeRegister(mpu, INT_ENABLE, INT_DISABLE) < 0) { // disable interrupt
return -1;
}
return 1;
}
/* configures and enables wake on motion, low power mode */
int MPU9250_enableWakeOnMotion(MPU9250_SPI_I2C *mpu, float womThresh_mg, LpAccelOdr odr) {
// set AK8963 to Power Down
writeAK8963Register(mpu, AK8963_CNTL1, AK8963_PWR_DOWN);
// reset the MPU9250
writeRegister(mpu, PWR_MGMNT_1, PWR_RESET);
// wait for MPU-9250 to come back up
HAL_Delay(1);
if (writeRegister(mpu, PWR_MGMNT_1, 0x00) < 0) { // cycle 0, sleep 0, standby 0
return -1;
}
if (writeRegister(mpu, PWR_MGMNT_2, DIS_GYRO) < 0) { // disable gyro measurements
return -2;
}
if (writeRegister(mpu, ACCEL_CONFIG2, ACCEL_DLPF_184) < 0) { // setting accel bandwidth to 184Hz
return -3;
}
if (writeRegister(mpu, INT_ENABLE, INT_WOM_EN) < 0) { // enabling interrupt to wake on motion
return -4;
}
if (writeRegister(mpu, MOT_DETECT_CTRL, (ACCEL_INTEL_EN | ACCEL_INTEL_MODE)) < 0) { // enabling accel hardware intelligence
return -5;
}
mpu->womThreshold = map(womThresh_mg, 0, 1020, 0, 255);
if (writeRegister(mpu, WOM_THR, mpu->womThreshold) < 0) { // setting wake on motion threshold
return -6;
}
if (writeRegister(mpu, LP_ACCEL_ODR, (uint8_t) odr) < 0) { // set frequency of wakeup
return -7;
}
if (writeRegister(mpu, PWR_MGMNT_1, PWR_CYCLE) < 0) { // switch to accel low power mode
return -8;
}
return 1;
}
/* configures and enables the FIFO buffer */
int MPU9250FIFO_enableFifo(MPU9250_SPI_I2C *mpu, bool accel, bool gyro, bool mag, bool temp) {
if (writeRegister(mpu, USER_CTRL, (0x40 | I2C_MST_EN)) < 0) {
return -1;
}
if (writeRegister(mpu, FIFO_EN, (accel * FIFO_ACCEL) | (gyro * FIFO_GYRO) | (mag * FIFO_MAG) | (temp * FIFO_TEMP)) < 0) {
return -2;
}
mpu->enFifoAccel = accel;
mpu->enFifoGyro = gyro;
mpu->enFifoMag = mag;
mpu->enFifoTemp = temp;
mpu->fifoFrameSize = accel * 6 + gyro * 6 + mag * 7 + temp * 2;
return 1;
}
/* reads the most current data from MPU9250 and stores in buffer */
int MPU9250_readSensor(MPU9250_SPI_I2C *mpu) {
// grab the data from the MPU9250
if (readRegisters(mpu, ACCEL_OUT, 21, mpu->buffer) < 0) {
return -1;
}
// combine into 16 bit values
mpu->axcounts = (((int16_t) mpu->buffer[0]) << 8) | mpu->buffer[1];
mpu->aycounts = (((int16_t) mpu->buffer[2]) << 8) | mpu->buffer[3];
mpu->azcounts = (((int16_t) mpu->buffer[4]) << 8) | mpu->buffer[5];
mpu->tcounts = (((int16_t) mpu->buffer[6]) << 8) | mpu->buffer[7];
mpu->gxcounts = (((int16_t) mpu->buffer[8]) << 8) | mpu->buffer[9];
mpu->gycounts = (((int16_t) mpu->buffer[10]) << 8) | mpu->buffer[11];
mpu->gzcounts = (((int16_t) mpu->buffer[12]) << 8) | mpu->buffer[13];
mpu->hxcounts = (((int16_t) mpu->buffer[15]) << 8) | mpu->buffer[14];
mpu->hycounts = (((int16_t) mpu->buffer[17]) << 8) | mpu->buffer[16];
mpu->hzcounts = (((int16_t) mpu->buffer[19]) << 8) | mpu->buffer[18];
// transform and convert to float values
mpu->ax = (((float) (tX[0] * mpu->axcounts + tX[1] * mpu->aycounts + tX[2] * mpu->azcounts) * mpu->accelScale) - mpu->axb) * mpu->axs;
mpu->ay = (((float) (tY[0] * mpu->axcounts + tY[1] * mpu->aycounts + tY[2] * mpu->azcounts) * mpu->accelScale) - mpu->ayb) * mpu->ays;
mpu->az = (((float) (tZ[0] * mpu->axcounts + tZ[1] * mpu->aycounts + tZ[2] * mpu->azcounts) * mpu->accelScale) - mpu->azb) * mpu->azs;
mpu->gx = ((float) (tX[0] * mpu->gxcounts + tX[1] * mpu->gycounts + tX[2] * mpu->gzcounts) * mpu->gyroScale) - mpu->gxb;
mpu->gy = ((float) (tY[0] * mpu->gxcounts + tY[1] * mpu->gycounts + tY[2] * mpu->gzcounts) * mpu->gyroScale) - mpu->gyb;
mpu->gz = ((float) (tZ[0] * mpu->gxcounts + tZ[1] * mpu->gycounts + tZ[2] * mpu->gzcounts) * mpu->gyroScale) - mpu->gzb;
mpu->hx = (((float) (mpu->hxcounts) * mpu->magScaleX) - mpu->hxb) * mpu->hxs;
mpu->hy = (((float) (mpu->hycounts) * mpu->magScaleY) - mpu->hyb) * mpu->hys;
mpu->hz = (((float) (mpu->hzcounts) * mpu->magScaleZ) - mpu->hzb) * mpu->hzs;
mpu->t = ((((float) mpu->tcounts) - tempOffset) / tempScale) + tempOffset;
return 1;
}
/* returns the accelerometer measurement in the x direction, m/s/s */
float MPU9250_getAccelX_mss(MPU9250_SPI_I2C *mpu) {
return mpu->ax;
}
/* returns the accelerometer measurement in the y direction, m/s/s */
float MPU9250_getAccelY_mss(MPU9250_SPI_I2C *mpu) {
return mpu->ay;
}
/* returns the accelerometer measurement in the z direction, m/s/s */
float MPU9250_getAccelZ_mss(MPU9250_SPI_I2C *mpu) {
return mpu->az;
}
/* returns the gyroscope measurement in the x direction, rad/s */
float MPU9250_getGyroX_rads(MPU9250_SPI_I2C *mpu) {
return mpu->gx;
}
/* returns the gyroscope measurement in the y direction, rad/s */
float MPU9250_getGyroY_rads(MPU9250_SPI_I2C *mpu) {
return mpu->gy;
}
/* returns the gyroscope measurement in the z direction, rad/s */
float MPU9250_getGyroZ_rads(MPU9250_SPI_I2C *mpu) {
return mpu->gz;
}
/* returns the magnetometer measurement in the x direction, uT */
float MPU9250_getMagX_uT(MPU9250_SPI_I2C *mpu) {
return mpu->hx;
}
/* returns the magnetometer measurement in the y direction, uT */
float MPU9250_getMagY_uT(MPU9250_SPI_I2C *mpu) {
return mpu->hy;
}
/* returns the magnetometer measurement in the z direction, uT */
float MPU9250_getMagZ_uT(MPU9250_SPI_I2C *mpu) {
return mpu->hz;
}
/* returns the die temperature, C */
float MPU9250_getTemperature_C(MPU9250_SPI_I2C *mpu) {
return mpu->t;
}
/* reads data from the MPU9250 FIFO and stores in buffer */
int MPU9250FIFO_readFifo(MPU9250_SPI_I2C *mpu) {
// get the fifo size
readRegisters(mpu, FIFO_COUNT, 2, mpu->buffer);
mpu->fifoSize = (((uint16_t) (mpu->buffer[0] & 0x0F)) << 8) + (((uint16_t) mpu->buffer[1]));
// read and parse the buffer
for (size_t i = 0; i < mpu->fifoSize / mpu->fifoFrameSize; i++) {
// grab the data from the MPU9250
if (readRegisters(mpu, FIFO_READ, mpu->fifoFrameSize, mpu->buffer) < 0) {
return -1;
}
if (mpu->enFifoAccel) {
// combine into 16 bit values
mpu->axcounts = (((int16_t) mpu->buffer[0]) << 8) | mpu->buffer[1];
mpu->aycounts = (((int16_t) mpu->buffer[2]) << 8) | mpu->buffer[3];
mpu->azcounts = (((int16_t) mpu->buffer[4]) << 8) | mpu->buffer[5];
// transform and convert to float values
mpu->axFifo[i] = (((float) (tX[0] * mpu->axcounts + tX[1] * mpu->aycounts + tX[2] * mpu->azcounts) * mpu->accelScale) - mpu->axb) * mpu->axs;
mpu->ayFifo[i] = (((float) (tY[0] * mpu->axcounts + tY[1] * mpu->aycounts + tY[2] * mpu->azcounts) * mpu->accelScale) - mpu->ayb) * mpu->ays;
mpu->azFifo[i] = (((float) (tZ[0] * mpu->axcounts + tZ[1] * mpu->aycounts + tZ[2] * mpu->azcounts) * mpu->accelScale) - mpu->azb) * mpu->azs;
mpu->aSize = mpu->fifoSize / mpu->fifoFrameSize;
}
if (mpu->enFifoTemp) {
// combine into 16 bit values
mpu->tcounts = (((int16_t) mpu->buffer[0 + mpu->enFifoAccel * 6]) << 8) | mpu->buffer[1 + mpu->enFifoAccel * 6];
// transform and convert to float values
mpu->tFifo[i] = ((((float) mpu->tcounts) - tempOffset) / tempScale) + tempOffset;
mpu->tSize = mpu->fifoSize / mpu->fifoFrameSize;
}
if (mpu->enFifoGyro) {
// combine into 16 bit values
mpu->gxcounts = (((int16_t) mpu->buffer[0 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2]) << 8) | mpu->buffer[1 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2];
mpu->gycounts = (((int16_t) mpu->buffer[2 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2]) << 8) | mpu->buffer[3 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2];
mpu->gzcounts = (((int16_t) mpu->buffer[4 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2]) << 8) | mpu->buffer[5 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2];
// transform and convert to float values
mpu->gxFifo[i] = ((float) (tX[0] * mpu->gxcounts + tX[1] * mpu->gycounts + tX[2] * mpu->gzcounts) * mpu->gyroScale) - mpu->gxb;
mpu->gyFifo[i] = ((float) (tY[0] * mpu->gxcounts + tY[1] * mpu->gycounts + tY[2] * mpu->gzcounts) * mpu->gyroScale) - mpu->gyb;
mpu->gzFifo[i] = ((float) (tZ[0] * mpu->gxcounts + tZ[1] * mpu->gycounts + tZ[2] * mpu->gzcounts) * mpu->gyroScale) - mpu->gzb;
mpu->gSize = mpu->fifoSize / mpu->fifoFrameSize;
}
if (mpu->enFifoMag) {
// combine into 16 bit values
mpu->hxcounts = (((int16_t) mpu->buffer[1 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2 + mpu->enFifoGyro * 6]) << 8)
| mpu->buffer[0 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2 + mpu->enFifoGyro * 6];
mpu->hycounts = (((int16_t) mpu->buffer[3 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2 + mpu->enFifoGyro * 6]) << 8)
| mpu->buffer[2 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2 + mpu->enFifoGyro * 6];
mpu->hzcounts = (((int16_t) mpu->buffer[5 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2 + mpu->enFifoGyro * 6]) << 8)
| mpu->buffer[4 + mpu->enFifoAccel * 6 + mpu->enFifoTemp * 2 + mpu->enFifoGyro * 6];
// transform and convert to float values
mpu->hxFifo[i] = (((float) (mpu->hxcounts) * mpu->magScaleX) - mpu->hxb) * mpu->hxs;
mpu->hyFifo[i] = (((float) (mpu->hycounts) * mpu->magScaleY) - mpu->hyb) * mpu->hys;
mpu->hzFifo[i] = (((float) (mpu->hzcounts) * mpu->magScaleZ) - mpu->hzb) * mpu->hzs;
mpu->hSize = mpu->fifoSize / mpu->fifoFrameSize;
}
}
return 1;
}
/* returns the accelerometer FIFO size and data in the x direction, m/s/s */
void MPU9250FIFO_getFifoAccelX_mss(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->aSize;
memcpy(data, mpu->axFifo, mpu->aSize * sizeof(float));
}
/* returns the accelerometer FIFO size and data in the y direction, m/s/s */
void MPU9250FIFO_getFifoAccelY_mss(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->aSize;
memcpy(data, mpu->ayFifo, mpu->aSize * sizeof(float));
}
/* returns the accelerometer FIFO size and data in the z direction, m/s/s */
void MPU9250FIFO_getFifoAccelZ_mss(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->aSize;
memcpy(data, mpu->azFifo, mpu->aSize * sizeof(float));
}
/* returns the gyroscope FIFO size and data in the x direction, rad/s */
void MPU9250FIFO_getFifoGyroX_rads(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->gSize;
memcpy(data, mpu->gxFifo, mpu->gSize * sizeof(float));
}
/* returns the gyroscope FIFO size and data in the y direction, rad/s */
void MPU9250FIFO_getFifoGyroY_rads(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->gSize;
memcpy(data, mpu->gyFifo, mpu->gSize * sizeof(float));
}
/* returns the gyroscope FIFO size and data in the z direction, rad/s */
void MPU9250FIFO_getFifoGyroZ_rads(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->gSize;
memcpy(data, mpu->gzFifo, mpu->gSize * sizeof(float));
}
/* returns the magnetometer FIFO size and data in the x direction, uT */
void MPU9250FIFO_getFifoMagX_uT(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->hSize;
memcpy(data, mpu->hxFifo, mpu->hSize * sizeof(float));
}
/* returns the magnetometer FIFO size and data in the y direction, uT */
void MPU9250FIFO_getFifoMagY_uT(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->hSize;
memcpy(data, mpu->hyFifo, mpu->hSize * sizeof(float));
}
/* returns the magnetometer FIFO size and data in the z direction, uT */
void MPU9250FIFO_getFifoMagZ_uT(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->hSize;
memcpy(data, mpu->hzFifo, mpu->hSize * sizeof(float));
}
/* returns the die temperature FIFO size and data, C */
void MPU9250FIFO_getFifoTemperature_C(MPU9250_SPI_I2C *mpu, size_t *size, float *data) {
*size = mpu->tSize;
memcpy(data, mpu->tFifo, mpu->tSize * sizeof(float));
}
/* estimates the gyro biases */
int MPU9250_calibrateGyro(MPU9250_SPI_I2C *mpu) {
// set the range, bandwidth, and srd
if (MPU9250_setGyroRange(mpu, GYRO_RANGE_250DPS) < 0) {
return -1;
}
if (MPU9250_setDlpfBandwidth(mpu, DLPF_BANDWIDTH_20HZ) < 0) {
return -2;
}
if (MPU9250_setSrd(mpu, 19) < 0) {
return -3;
}
// take samples and find bias
mpu->gxbD = 0;
mpu->gybD = 0;
mpu->gzbD = 0;
for (size_t i = 0; i < numSamples; i++) {
MPU9250_readSensor(mpu);
mpu->gxbD += (MPU9250_getGyroX_rads(mpu) + mpu->gxb) / ((float) numSamples);
mpu->gybD += (MPU9250_getGyroY_rads(mpu) + mpu->gyb) / ((float) numSamples);
mpu->gzbD += (MPU9250_getGyroZ_rads(mpu) + mpu->gzb) / ((float) numSamples);
HAL_Delay(20);
}
mpu->gxb = mpu->gxbD;
mpu->gyb = mpu->gybD;
mpu->gzb = mpu->gzbD;
// set the range, bandwidth, and srd back to what they were
if (MPU9250_setGyroRange(mpu, mpu->gyroRange) < 0) {
return -4;
}
if (MPU9250_setDlpfBandwidth(mpu, mpu->bandwidth) < 0) {
return -5;
}
if (MPU9250_setSrd(mpu, mpu->srd) < 0) {
return -6;
}
return 1;
}
/* returns the gyro bias in the X direction, rad/s */
float MPU9250_getGyroBiasX_rads(MPU9250_SPI_I2C *mpu) {
return mpu->gxb;
}
/* returns the gyro bias in the Y direction, rad/s */
float MPU9250_getGyroBiasY_rads(MPU9250_SPI_I2C *mpu) {
return mpu->gyb;
}
/* returns the gyro bias in the Z direction, rad/s */
float MPU9250_getGyroBiasZ_rads(MPU9250_SPI_I2C *mpu) {
return mpu->gzb;
}
/* sets the gyro bias in the X direction to bias, rad/s */
void MPU9250_setGyroBiasX_rads(MPU9250_SPI_I2C *mpu, float bias) {
mpu->gxb = bias;
}
/* sets the gyro bias in the Y direction to bias, rad/s */
void MPU9250_setGyroBiasY_rads(MPU9250_SPI_I2C *mpu, float bias) {
mpu->gyb = bias;
}
/* sets the gyro bias in the Z direction to bias, rad/s */
void MPU9250_setGyroBiasZ_rads(MPU9250_SPI_I2C *mpu, float bias) {
mpu->gzb = bias;
}
/* finds bias and scale factor calibration for the accelerometer,
this should be run for each axis in each direction (6 total) to find
the min and max values along each */
int MPU9250_calibrateAccel(MPU9250_SPI_I2C *mpu) {
// set the range, bandwidth, and srd
if (MPU9250_setAccelRange(mpu, ACCEL_RANGE_2G) < 0) {
return -1;
}
if (MPU9250_setDlpfBandwidth(mpu, DLPF_BANDWIDTH_20HZ) < 0) {
return -2;
}
if (MPU9250_setSrd(mpu, 19) < 0) {
return -3;
}
// take samples and find min / max
mpu->axbD = 0;
mpu->aybD = 0;
mpu->azbD = 0;
for (size_t i = 0; i < numSamples; i++) {
MPU9250_readSensor(mpu);
mpu->axbD += (MPU9250_getAccelX_mss(mpu) / mpu->axs + mpu->axb) / ((float) numSamples);
mpu->aybD += (MPU9250_getAccelY_mss(mpu) / mpu->ays + mpu->ayb) / ((float) numSamples);
mpu->azbD += (MPU9250_getAccelZ_mss(mpu) / mpu->azs + mpu->azb) / ((float) numSamples);
HAL_Delay(20);
}
if (mpu->axbD > 9.0f) {
mpu->axmax = mpu->axbD;
}
if (mpu->aybD > 9.0f) {
mpu->aymax = mpu->aybD;
}
if (mpu->azbD > 9.0f) {
mpu->azmax = mpu->azbD;
}
if (mpu->axbD < -9.0f) {
mpu->axmin = mpu->axbD;
}
if (mpu->aybD < -9.0f) {
mpu->aymin = mpu->aybD;
}
if (mpu->azbD < -9.0f) {
mpu->azmin = mpu->azbD;
}
// find bias and scale factor
if ((abs(mpu->axmin) > 9.0f) && (abs(mpu->axmax) > 9.0f)) {
mpu->axb = (mpu->axmin + mpu->axmax) / 2.0f;
mpu->axs = G / ((abs(mpu->axmin) + abs(mpu->axmax)) / 2.0f);
}
if ((abs(mpu->aymin) > 9.0f) && (abs(mpu->aymax) > 9.0f)) {
mpu->ayb = (mpu->aymin + mpu->aymax) / 2.0f;
mpu->ays = G / ((abs(mpu->aymin) + abs(mpu->aymax)) / 2.0f);
}
if ((abs(mpu->azmin) > 9.0f) && (abs(mpu->azmax) > 9.0f)) {
mpu->azb = (mpu->azmin + mpu->azmax) / 2.0f;
mpu->azs = G / ((abs(mpu->azmin) + abs(mpu->azmax)) / 2.0f);
}
// set the range, bandwidth, and srd back to what they were
if (MPU9250_setAccelRange(mpu, mpu->accelRange) < 0) {
return -4;
}
if (MPU9250_setDlpfBandwidth(mpu, mpu->bandwidth) < 0) {
return -5;
}
if (MPU9250_setSrd(mpu, mpu->srd) < 0) {
return -6;
}
return 1;
}
/* returns the accelerometer bias in the X direction, m/s/s */
float MPU9250_getAccelBiasX_mss(MPU9250_SPI_I2C *mpu) {
return mpu->axb;
}
/* returns the accelerometer scale factor in the X direction */
float MPU9250_getAccelScaleFactorX(MPU9250_SPI_I2C *mpu) {
return mpu->axs;
}
/* returns the accelerometer bias in the Y direction, m/s/s */
float MPU9250_getAccelBiasY_mss(MPU9250_SPI_I2C *mpu) {
return mpu->ayb;
}
/* returns the accelerometer scale factor in the Y direction */
float MPU9250_getAccelScaleFactorY(MPU9250_SPI_I2C *mpu) {
return mpu->ays;
}
/* returns the accelerometer bias in the Z direction, m/s/s */
float MPU9250_getAccelBiasZ_mss(MPU9250_SPI_I2C *mpu) {
return mpu->azb;
}
/* returns the accelerometer scale factor in the Z direction */
float MPU9250_getAccelScaleFactorZ(MPU9250_SPI_I2C *mpu) {
return mpu->azs;
}
/* sets the accelerometer bias (m/s/s) and scale factor in the X direction */
void MPU9250_setAccelCalX(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor) {
mpu->axb = bias;
mpu->axs = scaleFactor;
}
/* sets the accelerometer bias (m/s/s) and scale factor in the Y direction */
void MPU9250_setAccelCalY(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor) {
mpu->ayb = bias;
mpu->ays = scaleFactor;
}
/* sets the accelerometer bias (m/s/s) and scale factor in the Z direction */
void MPU9250_setAccelCalZ(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor) {
mpu->azb = bias;
mpu->azs = scaleFactor;
}
/* finds bias and scale factor calibration for the magnetometer,
the sensor should be rotated in a figure 8 motion until complete */
int MPU9250_calibrateMag(MPU9250_SPI_I2C *mpu) {
// set the srd
if (MPU9250_setSrd(mpu, 19) < 0) {
return -1;
}
// get a starting set of data
MPU9250_readSensor(mpu);
mpu->hxmax = MPU9250_getMagX_uT(mpu);
mpu->hxmin = MPU9250_getMagX_uT(mpu);
mpu->hymax = MPU9250_getMagY_uT(mpu);
mpu->hymin = MPU9250_getMagY_uT(mpu);
mpu->hzmax = MPU9250_getMagZ_uT(mpu);
mpu->hzmin = MPU9250_getMagZ_uT(mpu);
// collect data to find max / min in each channel
mpu->counter = 0;
while (mpu->counter < maxCounts) {
mpu->delta = 0.0f;
mpu->framedelta = 0.0f;
MPU9250_readSensor(mpu);
mpu->hxfilt = (mpu->hxfilt * ((float) coeff - 1) + (MPU9250_getMagX_uT(mpu) / mpu->hxs + mpu->hxb)) / ((float) coeff);
mpu->hyfilt = (mpu->hyfilt * ((float) coeff - 1) + (MPU9250_getMagY_uT(mpu) / mpu->hys + mpu->hyb)) / ((float) coeff);
mpu->hzfilt = (mpu->hzfilt * ((float) coeff - 1) + (MPU9250_getMagZ_uT(mpu) / mpu->hzs + mpu->hzb)) / ((float) coeff);
if (mpu->hxfilt > mpu->hxmax) {
mpu->delta = mpu->hxfilt - mpu->hxmax;
mpu->hxmax = mpu->hxfilt;
}
if (mpu->delta > mpu->framedelta) {
mpu->framedelta = mpu->delta;
}
if (mpu->hyfilt > mpu->hymax) {
mpu->delta = mpu->hyfilt - mpu->hymax;
mpu->hymax = mpu->hyfilt;
}
if (mpu->delta > mpu->framedelta) {
mpu->framedelta = mpu->delta;
}
if (mpu->hzfilt > mpu->hzmax) {
mpu->delta = mpu->hzfilt - mpu->hzmax;
mpu->hzmax = mpu->hzfilt;
}
if (mpu->delta > mpu->framedelta) {
mpu->framedelta = mpu->delta;
}
if (mpu->hxfilt < mpu->hxmin) {
mpu->delta = abs(mpu->hxfilt - mpu->hxmin);
mpu->hxmin = mpu->hxfilt;
}
if (mpu->delta > mpu->framedelta) {
mpu->framedelta = mpu->delta;
}
if (mpu->hyfilt < mpu->hymin) {
mpu->delta = abs(mpu->hyfilt - mpu->hymin);
mpu->hymin = mpu->hyfilt;
}
if (mpu->delta > mpu->framedelta) {
mpu->framedelta = mpu->delta;
}
if (mpu->hzfilt < mpu->hzmin) {
mpu->delta = abs(mpu->hzfilt - mpu->hzmin);
mpu->hzmin = mpu->hzfilt;
}
if (mpu->delta > mpu->framedelta) {
mpu->framedelta = mpu->delta;
}
if (mpu->framedelta > deltaThresh) {
mpu->counter = 0;
} else {
mpu->counter++;
}
HAL_Delay(20);
}
// find the magnetometer bias
mpu->hxb = (mpu->hxmax + mpu->hxmin) / 2.0f;
mpu->hyb = (mpu->hymax + mpu->hymin) / 2.0f;
mpu->hzb = (mpu->hzmax + mpu->hzmin) / 2.0f;
// find the magnetometer scale factor
mpu->hxs = (mpu->hxmax - mpu->hxmin) / 2.0f;
mpu->hys = (mpu->hymax - mpu->hymin) / 2.0f;
mpu->hzs = (mpu->hzmax - mpu->hzmin) / 2.0f;
mpu->avgs = (mpu->hxs + mpu->hys + mpu->hzs) / 3.0f;
mpu->hxs = mpu->avgs / mpu->hxs;
mpu->hys = mpu->avgs / mpu->hys;
mpu->hzs = mpu->avgs / mpu->hzs;
// set the srd back to what it was
if (MPU9250_setSrd(mpu, mpu->srd) < 0) {
return -2;
}
return 1;
}
/* returns the magnetometer bias in the X direction, uT */
float MPU9250_getMagBiasX_uT(MPU9250_SPI_I2C *mpu) {
return mpu->hxb;
}
/* returns the magnetometer scale factor in the X direction */
float MPU9250_getMagScaleFactorX(MPU9250_SPI_I2C *mpu) {
return mpu->hxs;
}
/* returns the magnetometer bias in the Y direction, uT */
float MPU9250_getMagBiasY_uT(MPU9250_SPI_I2C *mpu) {
return mpu->hyb;
}
/* returns the magnetometer scale factor in the Y direction */
float MPU9250_getMagScaleFactorY(MPU9250_SPI_I2C *mpu) {
return mpu->hys;
}
/* returns the magnetometer bias in the Z direction, uT */
float MPU9250_getMagBiasZ_uT(MPU9250_SPI_I2C *mpu) {
return mpu->hzb;
}
/* returns the magnetometer scale factor in the Z direction */
float MPU9250_getMagScaleFactorZ(MPU9250_SPI_I2C *mpu) {
return mpu->hzs;
}
/* sets the magnetometer bias (uT) and scale factor in the X direction */
void MPU9250_setMagCalX(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor) {
mpu->hxb = bias;
mpu->hxs = scaleFactor;
}
/* sets the magnetometer bias (uT) and scale factor in the Y direction */
void MPU9250_setMagCalY(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor) {
mpu->hyb = bias;
mpu->hys = scaleFactor;
}
/* sets the magnetometer bias (uT) and scale factor in the Z direction */
void MPU9250_setMagCalZ(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor) {
mpu->hzb = bias;
mpu->hzs = scaleFactor;
}
/* writes a byte to MPU9250 register given a register address and data */
static int writeRegister(MPU9250_SPI_I2C *mpu, uint8_t subAddress, uint8_t data) {
/* write data to device */
uint8_t pData[2] = { subAddress, data };
if (mpu->useSPI) {
HAL_GPIO_WritePin(mpu->MPU_CS_GPIO_Port, mpu->MPU_CS_GPIO_Pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(mpu->hspi, pData, 2, 10);
HAL_GPIO_WritePin(mpu->MPU_CS_GPIO_Port, mpu->MPU_CS_GPIO_Pin, GPIO_PIN_SET);
} else {
HAL_I2C_Master_Transmit(mpu->hi2c, mpu->address, pData, 2, 10);
}
HAL_Delay(10);
/* read back the register */
readRegisters(mpu, subAddress, 1, mpu->buffer);
/* check the read back register against the written register */
if (mpu->buffer[0] == data) {
return 1;
} else {
return -1;
}
}
/* reads registers from MPU9250 given a starting register address, number of bytes, and a pointer to store data */
static int readRegisters(MPU9250_SPI_I2C *mpu, uint8_t subAddress, uint8_t count, uint8_t *dest) {
if (mpu->useSPI) {
// begin the transaction
HAL_GPIO_WritePin(mpu->MPU_CS_GPIO_Port, mpu->MPU_CS_GPIO_Pin, GPIO_PIN_RESET);
// specify the starting register address
subAddress = subAddress | 0x80; // SPI_READ = 0x80
HAL_SPI_Transmit(mpu->hspi, &subAddress, 1, 10);
// Read while sending 0x00
uint8_t pTxData[count];
memset(pTxData, 0, count);
HAL_SPI_TransmitReceive(mpu->hspi, pTxData, dest, count, 10);
HAL_GPIO_WritePin(mpu->MPU_CS_GPIO_Port, mpu->MPU_CS_GPIO_Pin, GPIO_PIN_SET);
return 1;
} else {
HAL_I2C_Master_Transmit(mpu->hi2c, mpu->address, &subAddress, 1, 10);
HAL_I2C_Master_Receive(mpu->hi2c, mpu->address, dest, count, 10);
return 1;
}
}
/* writes a register to the AK8963 given a register address and data */
static int writeAK8963Register(MPU9250_SPI_I2C *mpu, uint8_t subAddress, uint8_t data) {
// set slave 0 to the AK8963 and set for write
if (writeRegister(mpu, I2C_SLV0_ADDR, AK8963_I2C_ADDR) < 0) {
return -1;
}
// set the register to the desired AK8963 sub address
if (writeRegister(mpu, I2C_SLV0_REG, subAddress) < 0) {
return -2;
}
// store the data for write
if (writeRegister(mpu, I2C_SLV0_DO, data) < 0) {
return -3;
}
// enable I2C and send 1 byte
if (writeRegister(mpu, I2C_SLV0_CTRL, I2C_SLV0_EN | (uint8_t) 1) < 0) {
return -4;
}
// read the register and confirm
if (readAK8963Registers(mpu, subAddress, 1, mpu->buffer) < 0) {
return -5;
}
if (mpu->buffer[0] == data) {
return 1;
} else {
return -6;
}
}
/* reads registers from the AK8963 */
static int readAK8963Registers(MPU9250_SPI_I2C *mpu, uint8_t subAddress, uint8_t count, uint8_t *dest) {
// set slave 0 to the AK8963 and set for read
if (writeRegister(mpu, I2C_SLV0_ADDR, AK8963_I2C_ADDR | I2C_READ_FLAG) < 0) {
return -1;
}
// set the register to the desired AK8963 sub address
if (writeRegister(mpu, I2C_SLV0_REG, subAddress) < 0) {
return -2;
}
// enable I2C and request the bytes
if (writeRegister(mpu, I2C_SLV0_CTRL, I2C_SLV0_EN | count) < 0) {
return -3;
}
HAL_Delay(1); // takes some time for these registers to fill
// read the bytes off the MPU9250 EXT_SENS_DATA registers
mpu->status = readRegisters(mpu, EXT_SENS_DATA_00, count, dest);
return mpu->status;
}
/* gets the MPU9250 WHO_AM_I register value, expected to be 0x71 */
static int whoAmI(MPU9250_SPI_I2C *mpu) {
// read the WHO AM I register
if (readRegisters(mpu, WHO_AM_I, 1, mpu->buffer) < 0) {
return -1;
}
// return the register value
return mpu->buffer[0];
}
/* gets the AK8963 WHO_AM_I register value, expected to be 0x48 */
static int whoAmIAK8963(MPU9250_SPI_I2C *mpu) {
// read the WHO AM I register
if (readAK8963Registers(mpu, AK8963_WHO_AM_I, 1, mpu->buffer) < 0) {
return -1;
}
// return the register value
return mpu->buffer[0];
}
static long map(long x, long in_min, long in_max, long out_min, long out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
Kod: Markera allt
#ifndef SRC_MPU9250_MPU9250_H_
#define SRC_MPU9250_MPU9250_H_
#include "main.h"
#include "stdbool.h"
#include "stdlib.h"
#include "string.h"
typedef enum {
GYRO_RANGE_250DPS, GYRO_RANGE_500DPS, GYRO_RANGE_1000DPS, GYRO_RANGE_2000DPS
} GyroRange;
typedef enum {
ACCEL_RANGE_2G, ACCEL_RANGE_4G, ACCEL_RANGE_8G, ACCEL_RANGE_16G
} AccelRange;
typedef enum {
DLPF_BANDWIDTH_184HZ, DLPF_BANDWIDTH_92HZ, DLPF_BANDWIDTH_41HZ, DLPF_BANDWIDTH_20HZ, DLPF_BANDWIDTH_10HZ, DLPF_BANDWIDTH_5HZ
} DlpfBandwidth;
typedef enum {
LP_ACCEL_ODR_0_24HZ = 0,
LP_ACCEL_ODR_0_49HZ = 1,
LP_ACCEL_ODR_0_98HZ = 2,
LP_ACCEL_ODR_1_95HZ = 3,
LP_ACCEL_ODR_3_91HZ = 4,
LP_ACCEL_ODR_7_81HZ = 5,
LP_ACCEL_ODR_15_63HZ = 6,
LP_ACCEL_ODR_31_25HZ = 7,
LP_ACCEL_ODR_62_50HZ = 8,
LP_ACCEL_ODR_125HZ = 9,
LP_ACCEL_ODR_250HZ = 10,
LP_ACCEL_ODR_500HZ = 11
} LpAccelOdr;
typedef struct {
// SPI
bool useSPI;
uint16_t MPU_CS_GPIO_Pin;
GPIO_TypeDef *MPU_CS_GPIO_Port;
SPI_HandleTypeDef *hspi;
// I2C
uint8_t address;
I2C_HandleTypeDef *hi2c;
// track success of interacting with sensor
int status;
// buffer for reading from sensor
uint8_t buffer[21];
// data counts
int16_t axcounts, aycounts, azcounts;
int16_t gxcounts, gycounts, gzcounts;
int16_t hxcounts, hycounts, hzcounts;
int16_t tcounts;
// data buffer
float ax, ay, az;
float gx, gy, gz;
float hx, hy, hz;
float t;
// wake on motion
uint8_t womThreshold;
// scale factors
float accelScale;
float gyroScale;
float magScaleX, magScaleY, magScaleZ;
// configuration
AccelRange accelRange;
GyroRange gyroRange;
DlpfBandwidth bandwidth;
uint8_t srd;
// gyro bias estimation
float gxbD, gybD, gzbD;
float gxb, gyb, gzb;
// accel bias and scale factor estimation
float axbD, aybD, azbD;
float axmax, aymax, azmax;
float axmin, aymin, azmin;
float axb, ayb, azb;
float axs;
float ays;
float azs;
uint16_t counter;
float framedelta, delta;
float hxfilt, hyfilt, hzfilt;
float hxmax, hymax, hzmax;
float hxmin, hymin, hzmin;
float hxb, hyb, hzb;
float hxs;
float hys;
float hzs;
float avgs;
// fifo
bool enFifoAccel, enFifoGyro, enFifoMag, enFifoTemp;
size_t fifoSize, fifoFrameSize;
float axFifo[85], ayFifo[85], azFifo[85];
size_t aSize;
float gxFifo[85], gyFifo[85], gzFifo[85];
size_t gSize;
float hxFifo[73], hyFifo[73], hzFifo[73];
size_t hSize;
float tFifo[256];
size_t tSize;
} MPU9250_SPI_I2C;
int MPU9250_begin_SPI(MPU9250_SPI_I2C *mpu, SPI_HandleTypeDef *hspi, GPIO_TypeDef *MPU_CS_GPIO_Port, uint16_t MPU_CS_GPIO_Pin);
int MPU9250_begin_I2C(MPU9250_SPI_I2C *mpu, I2C_HandleTypeDef *hi2c, uint8_t address);
int MPU9250_setAccelRange(MPU9250_SPI_I2C *mpu, AccelRange range);
int MPU9250_setGyroRange(MPU9250_SPI_I2C *mpu, GyroRange range);
int MPU9250_setDlpfBandwidth(MPU9250_SPI_I2C *mpu, DlpfBandwidth bandwidth);
int MPU9250_setSrd(MPU9250_SPI_I2C *mpu, uint8_t srd);
int MPU9250_enableDataReadyInterrupt(MPU9250_SPI_I2C *mpu);
int MPU9250_disableDataReadyInterrupt(MPU9250_SPI_I2C *mpu);
int MPU9250_enableWakeOnMotion(MPU9250_SPI_I2C *mpu, float womThresh_mg, LpAccelOdr odr);
int MPU9250FIFO_enableFifo(MPU9250_SPI_I2C *mpu, bool accel, bool gyro, bool mag, bool temp);
int MPU9250_readSensor(MPU9250_SPI_I2C *mpu);
float MPU9250_getAccelX_mss(MPU9250_SPI_I2C *mpu);
float MPU9250_getAccelY_mss(MPU9250_SPI_I2C *mpu);
float MPU9250_getAccelZ_mss(MPU9250_SPI_I2C *mpu);
float MPU9250_getGyroX_rads(MPU9250_SPI_I2C *mpu);
float MPU9250_getGyroY_rads(MPU9250_SPI_I2C *mpu);
float MPU9250_getGyroZ_rads(MPU9250_SPI_I2C *mpu);
float MPU9250_getMagX_uT(MPU9250_SPI_I2C *mpu);
float MPU9250_getMagY_uT(MPU9250_SPI_I2C *mpu);
float MPU9250_getMagZ_uT(MPU9250_SPI_I2C *mpu);
float MPU9250_getTemperature_C(MPU9250_SPI_I2C *mpu);
int MPU9250FIFO_readFifo(MPU9250_SPI_I2C *mpu);
void MPU9250FIFO_getFifoAccelX_mss(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
void MPU9250FIFO_getFifoAccelY_mss(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
void MPU9250FIFO_getFifoAccelZ_mss(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
void MPU9250FIFO_getFifoGyroX_rads(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
void MPU9250FIFO_getFifoGyroY_rads(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
void MPU9250FIFO_getFifoGyroZ_rads(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
void MPU9250FIFO_getFifoMagX_uT(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
void MPU9250FIFO_getFifoMagY_uT(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
void MPU9250FIFO_getFifoMagZ_uT(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
void MPU9250FIFO_getFifoTemperature_C(MPU9250_SPI_I2C *mpu, size_t *size, float *data);
int MPU9250_calibrateGyro(MPU9250_SPI_I2C *mpu);
float MPU9250_getGyroBiasX_rads(MPU9250_SPI_I2C *mpu);
float MPU9250_getGyroBiasY_rads(MPU9250_SPI_I2C *mpu);
float MPU9250_getGyroBiasZ_rads(MPU9250_SPI_I2C *mpu);
void MPU9250_setGyroBiasX_rads(MPU9250_SPI_I2C *mpu, float bias);
void MPU9250_setGyroBiasY_rads(MPU9250_SPI_I2C *mpu, float bias);
void MPU9250_setGyroBiasZ_rads(MPU9250_SPI_I2C *mpu, float bias);
int MPU9250_calibrateAccel(MPU9250_SPI_I2C *mpu);
float MPU9250_getAccelBiasX_mss(MPU9250_SPI_I2C *mpu);
float MPU9250_getAccelScaleFactorX(MPU9250_SPI_I2C *mpu);
float MPU9250_getAccelBiasY_mss(MPU9250_SPI_I2C *mpu);
float MPU9250_getAccelScaleFactorY(MPU9250_SPI_I2C *mpu);
float MPU9250_getAccelBiasZ_mss(MPU9250_SPI_I2C *mpu);
float MPU9250_getAccelScaleFactorZ(MPU9250_SPI_I2C *mpu);
void MPU9250_setAccelCalX(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor);
void MPU9250_setAccelCalY(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor);
void MPU9250_setAccelCalZ(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor);
int MPU9250_calibrateMag(MPU9250_SPI_I2C *mpu);
float MPU9250_getMagBiasX_uT(MPU9250_SPI_I2C *mpu);
float MPU9250_getMagScaleFactorX(MPU9250_SPI_I2C *mpu);
float MPU9250_getMagBiasY_uT(MPU9250_SPI_I2C *mpu);
float MPU9250_getMagScaleFactorY(MPU9250_SPI_I2C *mpu);
float MPU9250_getMagBiasZ_uT(MPU9250_SPI_I2C *mpu);
float MPU9250_getMagScaleFactorZ(MPU9250_SPI_I2C *mpu);
void MPU9250_setMagCalX(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor);
void MPU9250_setMagCalY(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor);
void MPU9250_setMagCalZ(MPU9250_SPI_I2C *mpu, float bias, float scaleFactor);
#endif /* SRC_MPU9250_MPU9250_H_ */