Vad har jag för Gyro? MPU9250 eller MPU9255?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
DanielM
Inlägg: 2194
Blev medlem: 5 september 2019, 14:19:58

Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av DanielM »

Jag köpte en 9DOF gyro (gyro, acc, magnet) från Bangood
Sélection_019.png
Sedan hittade jag ett Arduino C++ bibliotek till den. Då skrev jag av biblioteket till STM32 C kod.

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);
Jag kollade upp varför. I denna funktion så var mpu->buffer[0] == 3 och data == 1. 3:an kommer alltså från gyron. Då började jag söka i databladet. Då hittade jag denna gyro MPU9255 och även ett bibliotek till denna gyro.

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_ */
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43178
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av sodjan »

Bangood länken fungerar inte...
Men vad står det på själva chippet?
DanielM
Inlägg: 2194
Blev medlem: 5 september 2019, 14:19:58

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av DanielM »

https://www.banggood.com/MPU-9250-GY-92 ... rehouse=CN

På mitt chip så står det MPU-9250/6500. Men det kan även betyda att det är en MPU-9255 med tanke på att det bibliotek jag har skrivit av fungerar inte med mitt chip. Jag har ju bara rakt kopierat över C++ kod och tagit bort klassen och ersatt allt bara med en struct. Mer än så behövs inte får att få "objektorienterad" C kod.
hummel
Inlägg: 2268
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av hummel »

Hur kan det betyda att chippet är ett MPU-9255 om det står MPU-9250 tryckt på det? Är det någon piratvariant eller?
Användarvisningsbild
hawkan
Inlägg: 2635
Blev medlem: 14 augusti 2011, 10:27:40

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av hawkan »

Gör en enkel i2c scanner som letar fram vilka enheter som finns på bussen med adresser.

Det är inte alltid så, men första tanken borde vara att det är fel på mjukvaran.
DanielM
Inlägg: 2194
Blev medlem: 5 september 2019, 14:19:58

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av DanielM »

Jag gjorde en enkel i2c scanner som letade reda på adressen. Då fick jag två adresser. En till lcd och en till MPU.
DanielM
Inlägg: 2194
Blev medlem: 5 september 2019, 14:19:58

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av DanielM »

hummel skrev:Hur kan det betyda att chippet är ett MPU-9255 om det står MPU-9250 tryckt på det? Är det någon piratvariant eller?
För mpu-9250 och 9255 ser likadana ut.
hummel
Inlägg: 2268
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av hummel »

Hur menar du ser likadana ut, dom har väl olika beteckning?
Mr Andersson
Inlägg: 1397
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av Mr Andersson »

DanielM skrev:På mitt chip så står det MPU-9250/6500.
Står det så är det garanterat fake eller pirat.
Äkta chip är märkta MP92 för 9250 eller M925 för 9255.
DanielM
Inlägg: 2194
Blev medlem: 5 september 2019, 14:19:58

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av DanielM »

Mr Andersson skrev:
DanielM skrev:På mitt chip så står det MPU-9250/6500.
Står det så är det garanterat fake eller pirat.
Äkta chip är märkta MP92 för 9250 eller M925 för 9255.
Klart det är äkta. Även elektrokit köper från Kina. Sällan Made In USA nu för tiden. Kanske något relä på 90-tals volvo.
DanielM
Inlägg: 2194
Blev medlem: 5 september 2019, 14:19:58

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av DanielM »

hummel skrev:Hur menar du ser likadana ut, dom har väl olika beteckning?
Det är kina saker. Klart dom skiljer sig.

Hur som helst. När jag kör denna kod

Steg 1:

Kod: Markera allt

/* 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;
   }
Steg 2:

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;
   }
}
Steg 3:

Kod: Markera allt

/* 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;
   }
}
Med

Kod: Markera allt

subAddress = PWR_MGMNT_1 = 0x6B
data = CLOCK_SEL_PLL = 0x01
Då får jag att mpu->buffer[0] == 0x03 när mpu->buffer[0] skall vara lika med CLOCK_SEL_PLL.
ToPNoTCH
Inlägg: 4890
Blev medlem: 21 december 2009, 17:59:48

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av ToPNoTCH »

MPU-9250 & MPU-9255 har samma adress och vad jag kommer ihåg samma register map.

Så du kan nog släppa att problemet skulle vara variant av chip.

Adressen 0x79 stämmer inte på något av dom. Oavsett hur du satt konfigurationspinnen (AD0)
Antingen är den 0x68 eller 0x69
The slave address of the MPU-9255 is b110100X which is 7 bits long. The LSB bit of the 7 bit address is
determined by the logic level on pin AD0. This allows two MPU-9255s to be connected to the same I2
C bus.
When used in this configuration, the address of the one of the devices should be b1101000 (pin AD0 is logic
low) and the address of the other should be b1101001 (pin AD0 is logic high).
The slave address of the MPU-9250 is b110100X which is 7 bits long. The LSB bit of the 7 bit address is
determined by the logic level on pin AD0. This allows two MPU-9250s to be connected to the same I2C bus.
When used in this configuration, the address of the one of the devices should be b1101000 (pin AD0 is logic
low) and the address of the other should be b1101001 (pin AD0 is logic high).
DanielM
Inlägg: 2194
Blev medlem: 5 september 2019, 14:19:58

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av DanielM »

Hmm..

Det lustiga är att jag hittar nu inte 0x68 eller 0x69. Ingen I2C address! :?
Jag är 100% säker att jag har kopplat rätt.
VCC = 3.3 volt
GND = GND
SDA = SDA
SCL = SCL
AD0 = GND

Edit:
Jag ger upp. Jag misstänker att chipet är sönder.
Zkronk
Inlägg: 1423
Blev medlem: 23 augusti 2005, 16:44:36
Ort: Uppsala

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av Zkronk »

Har kortet inbyggda pullup-resistorer på I2C-bussen?
Användarvisningsbild
electronix
Inlägg: 346
Blev medlem: 29 mars 2009, 10:48:08
Ort: Norrköping

Re: Vad har jag för Gyro? MPU9250 eller MPU9255?

Inlägg av electronix »

Ser ut att sitta 2st 10k på SDA, SCL, vilket verkar vara väl höga värden på I2C. Personligen så hade jag satt 2 st 2k7 parallellt med dessa om enheten körs på max hastighet.
Skriv svar