分享自己調通的 MPU9255 SPI 讀取 AK8963 代碼
本帖最后由 john800422 于 2015-7-18 14:17 编辑自己調通的代碼,透過 SPI 讀取 MPU9255 的加速度計、陀螺儀、磁力計資料,
使用 MPU6555 內建的自動讀取功能,設定好後就會連續自動讀取 AK8963 的資料,
只需要從 EXT_SENS_DATA_00 - EXT_SENS_DATA_07 讀取出來就可以了,
這個功能蠻方便的,下面放出幾個關鍵的部分,詳細的工程最下面可以下載,或是在 github 下載
https://github.com/KitSprout/RedBeanSprout/tree/master/Software/BSR_Module_MPU9255_SPI
使用 STM32F103C 實現,目前 400 Hz 還可以正常運作。
接收部分使用 MATLAB,詳細參考下面帖子
http://www.amobbs.com/forum.php?mod=viewthread&tid=5627278&extra=
#define MPU6555_InitRegNum 11
#define AK8963_InitRegNum2
uint8_t MPU9255_Init( MPU_InitTypeDef *MPUx )
{
uint8_t status = ERROR;
uint8_t MPU6555_InitData = {
{0x80, MPU6555_PWR_MGMT_1}, // Reset Device
{0x01, MPU6555_PWR_MGMT_1}, // Clock Source
{0x30, MPU6555_USER_CTRL}, // Set I2C_MST_EN, I2C_IF_DIS
{0x00, MPU6555_PWR_MGMT_2}, // Enable Acc & Gyro
{0x07, MPU6555_CONFIG}, // DLPF_CFG = 111;
{0x18, MPU6555_GYRO_CONFIG}, // +-2000dps
{0x08, MPU6555_ACCEL_CONFIG}, // +-4G
{0x48, MPU6555_ACCEL_CONFIG_2}, // Set Acc Data Rates
{0x10, MPU6555_INT_PIN_CFG}, // Set INT_ANYRD_2CLEAR
{0x10, MPU6555_INT_ENABLE}, //
{0x4D, MPU6555_I2C_MST_CTRL}, // I2C Speed 400 kHz
};
uint8_t AK8963_InitData = {
{0x01, AK8963_CNTL2}, // Reset Device
{0x06, AK8963_CNTL1}, // Continuous measurement mode 2
};
MPU6555_InitData = MPUx->MPU_Gyr_FullScale; // MPU6555_GYRO_CONFIG
MPU6555_InitData = MPUx->MPU_Gyr_LowPassFilter; // MPU6555_CONFIG
MPU6555_InitData = MPUx->MPU_Acc_FullScale; // MPU6555_ACCEL_CONFIG
MPU6555_InitData = MPUx->MPU_Acc_LowPassFilter; // MPU6555_ACCEL_CONFIG_2
AK8963_InitData |= MPUx->MPU_Mag_FullScale;
for(uint8_t i = 0; i < MPU6555_InitRegNum; i++) {
MPU9255_WriteReg(MPU6555_InitData, MPU6555_InitData);
Delay_1ms(1);
}
status = MPU9255_Check();
if(status != SUCCESS)
return ERROR;
Delay_10ms(1);
#ifdef _USE_MAG_AK8963
for(uint8_t i = 0; i < AK8963_InitRegNum; i++) {
MPU9255_Mag_WriteReg(AK8963_InitData, AK8963_InitData);
Delay_10ms(1);
}
MPU9255_WriteReg(MPU6555_I2C_SLV0_REG, AK8963_ST1);
MPU9255_WriteReg(MPU6555_I2C_SLV0_ADDR, AK8963_I2C_ADDR | 0x80);
MPU9255_WriteReg(MPU6555_I2C_SLV0_CTRL, 0x80 | 8);
#endif
MPU9255_SetSpeed(SPIx_SPEED_HIGH);
Delay_10ms(1);
return SUCCESS;
}
void MPU9255_getData( int16_t *dataIMU )
{
uint8_t tmpRead = {0};
#ifdef _USE_MAG_AK8963
MPU9255_ReadRegs(MPU6555_ACCEL_XOUT_H, tmpRead, 22);
#else
MPU9255_ReadRegs(MPU6555_ACCEL_XOUT_H, tmpRead, 14);
#endif
dataIMU = (Byte16(int16_t, tmpRead,tmpRead)); // Temp
dataIMU = (Byte16(int16_t, tmpRead,tmpRead)); // Acc.X
dataIMU = (Byte16(int16_t, tmpRead,tmpRead)); // Acc.Y
dataIMU = (Byte16(int16_t, tmpRead,tmpRead)); // Acc.Z
dataIMU = (Byte16(int16_t, tmpRead,tmpRead)); // Gyr.X
dataIMU = (Byte16(int16_t, tmpRead, tmpRead)); // Gyr.Y
dataIMU = (Byte16(int16_t, tmpRead, tmpRead)); // Gyr.Z
#ifdef _USE_MAG_AK8963
dataIMU = (Byte16(int16_t, tmpRead, tmpRead)); // Mag.X
dataIMU = (Byte16(int16_t, tmpRead, tmpRead)); // Mag.Y
dataIMU = (Byte16(int16_t, tmpRead, tmpRead)); // Mag.Z
#endif
}
void SysTick_Handler( void )
{
int16_t IMU_Buf = {0};
int16_t readData = {0};
LED_R_Toggle;
MPU9255_getData(readData);
readData = readData - Bx; // Acc.X
readData = readData - By; // Acc.Y
readData = readData - Bz; // Acc.Z
IMU_Buf = (int16_t)(readData * Sxx + readData * Sxy + readData * Sxz);// Acc.X
IMU_Buf = (int16_t)(readData * Syx + readData * Syy + readData * Syz);// Acc.Y
IMU_Buf = (int16_t)(readData * Szx + readData * Szy + readData * Szz);// Acc.Z
IMU_Buf = readData * MPU9255G_2000dps; // Gyr.X
IMU_Buf = readData * MPU9255G_2000dps; // Gyr.Y
IMU_Buf = readData * MPU9255G_2000dps; // Gyr.Z
IMU_Buf = readData * MPU9255M_4800uT; // Mag.X
IMU_Buf = readData * MPU9255M_4800uT; // Mag.Y
IMU_Buf = readData * MPU9255M_4800uT; // Mag.Z
IMU_Buf = readData * MPU9255T_85degC; // temp
Serial_sendDataMATLAB(IMU_Buf, 10);
}
首页一看繁体字 就知道是楼主! 芯片在哪买的? Shampoo 发表于 2015-7-18 14:17
首页一看繁体字 就知道是楼主!
感謝支持{:lol:} 沉默胜过白金 发表于 2015-7-18 14:52
芯片在哪买的?
目前是用模塊,芯片的話X寶應該可以買到。 我在搞 MPU9250,能不能将你的原理图贴出来参考下。 沉默胜过白金 发表于 2015-7-18 21:19
我在搞 MPU9250,能不能将你的原理图贴出来参考下。
實際是用 CJMCU-MPU 模塊,沒有要資料所以不清楚電路,
你可以參考我之前的設計 SmartIMU,裡面有 MPU9250 的電路,如果要相容 MPU6500,NC 腳不要接地。
https://github.com/Hom-Wang/SmartIMU john800422 发表于 2015-7-18 21:27
實際是用 CJMCU-MPU 模塊,沒有要資料所以不清楚電路,
你可以參考我之前的設計 SmartIMU,裡面有 MPU925 ...
Thanks a lot !{:smile:} 台湾哥{:lol:} 请教MPU9255跟之前MPU9250有什么区别?我还以为只能用IIC,有点郁闷呢 https://code.google.com/p/open-headtracker/downloads/list
这里他有个校准的工具,他用的是6050,如果楼主能够移植过来就太好了 Timingtime 发表于 2015-7-19 17:25
请教MPU9255跟之前MPU9250有什么区别?我还以为只能用IIC,有点郁闷呢
似乎只差在 AAR 庫,但好像只支援 ATMEL 的晶片,詳細可以看官網說明。
MPU9150 只支援 I2C,MPU9250 就支援 SPI / I2C 了,SPI 比 I2C 有更高的傳輸速度,
可以減少傳輸占用的時間,增加解算算法的更新頻率。 Timingtime 发表于 2015-7-19 17:29
https://code.google.com/p/open-headtracker/downloads/list
这里他有个校准的工具,他用的是6050,如果楼 ...
最近在重新做感測器的校正,有時間看看。 你好,今天看了一下关于MPU9250的数据手册,有这么几个疑问:
1、假使我使用I2C通信方式,并且我要读取9个轴的数据,是不是在配置的时候,先将芯片配置为Pass-Through Mode模式,使用单片机完成对磁力计的配置,然后转为I2C Master Mode,进而完成相应的配置,通过单片机对ACC,GYRO,以及MAG寄存器读数据?
2、如果1可行,那么,在我SPI方式时,如何对磁力计进行配置?难道要先将这两个引脚模拟成I2C,配置完成后再配置为SPI,对其进行操作,读写?或者说在SPI方式下是不需要对磁力计进行配置(我看手册上没有写,粗略介绍了一下SPI方式),直接可以对各个寄存器读取数据?
本帖最后由 john800422 于 2015-7-19 22:17 编辑
沉默胜过白金 发表于 2015-7-19 21:32
你好,今天看了一下关于MPU9250的数据手册,有这么几个疑问:
1、假使我使用I2C通信方式,并且我要读取9个 ...
I2C 讀取 MPU9250 的 AK8963 有兩種方法:
1。Pass-Through Mode,將 Auxiliary I2C 直接與 Primary I2C 連接,也就是說你可以將 MPU9250 看成掛在同一個 I2C 上的 MPU6500 和 AK8963。
2。I2C Master Mode,將 Auxiliary I2C 與 Primary I2C 斷開,透過 I2C_SLVx_ADDR、I2C_SLVx_REG、I2C_SLVx_CTRL 等寄存器來讀寫 AK8963。
SPI 讀取 MPU9250 的 AK8963 就只適用上述的 I2C Master Mode
透過 SPI 設定 MPU6500 上的 I2C_SLVx_ADDR、I2C_SLVx_REG、I2C_SLVx_CTRL ... 寄存器,來讓 MPU6500 自動透過 Auxiliary I2C 讀取 AK8963,不需要再模擬 I2C,詳細設定可以參考頂樓的程序。 john800422 发表于 2015-7-19 18:30
最近在重新做感測器的校正,有時間看看。
好的,谢了。
其他六轴倒是没有问题。磁力计校准有些看不懂。磁力计才8Hz感觉比较弱啊。。我是拿来校正方向的,不知道有没有影响 Timingtime 发表于 2015-7-21 09:26
好的,谢了。
其他六轴倒是没有问题。磁力计校准有些看不懂。磁力计才8Hz感觉比较弱啊。。我是拿来校正方 ...
AK8963 Continuous measurement mode 2 可以達到 100Hz,對於航向來說已經足夠了,
磁力計的校正可以參考我之前的帖子,橢圓擬合,針對2維平面做校正,
若需要校正到 3 維空間的話,論壇裡搜橢球擬合應該有。 john800422 发表于 2015-7-21 19:39
AK8963 Continuous measurement mode 2 可以達到 100Hz,對於航向來說已經足夠了,
磁力計的校正可以參考 ...
感谢
测试了下MPU9250_Write_Reg(AK8963_CNTL1, 0x06);
陀螺仪开始飘得很厉害,Z轴数值差了260多,一直在转,校准后每秒飘一点,好点,但是还漂移
大概是3-8,无法接受,可以感觉出来。所以没办法这么用,只能用8Hz。这一点真的很奇怪,弄了一晚上,不明所以。 Timingtime 发表于 2015-7-21 22:53
感谢
测试了下MPU9250_Write_Reg(AK8963_CNTL1, 0x06);
陀螺仪开始飘得很厉害,Z轴数值差了260多,一直 ...
不太懂你說的 ...
MPU9250_Write_Reg(AK8963_CNTL1, 0x06) 與陀螺儀輸出有甚麼關係? 本帖最后由 Timingtime 于 2015-7-22 09:14 编辑
john800422 发表于 2015-7-22 03:18
不太懂你說的 ...
MPU9250_Write_Reg(AK8963_CNTL1, 0x06) 與陀螺儀輸出有甚麼關係?
不知道,我也纳闷。。很古怪。
我是用1KHz的 Timingtime 发表于 2015-7-22 08:58
不知道,我也纳闷。。很古怪。
我是用1KHz的
搞错了,应该给AK8963发,抱歉。 1000Hz没问题,太帅。
请教怎么跑8000Hz? MPU9255 MPU9250有啥区别呢 你好,我现在有个疑问,为什么在读 暂存器的时候, 每个地址,都和 0x80 做了 或运算。
SPI_RW(SPIx, 0x80 | ReadAddr);? 沉默胜过白金 发表于 2015-8-2 19:17
你好,我现在有个疑问,为什么在读 暂存器的时候, 每个地址,都和 0x80 做了 或运算。
SPI_RW(SPIx, 0x ...
詳細自行參考 MPU9255 或 MPU9250 datasheet, SPI 協議部分。 请问哪位仁兄有MPU9255 (6555)的寄存器资料,谢谢! 有空搞个试试 在获取地磁数据的过程中,相同的程序有时烧录后成功读取到地磁ID 0x48,可有时烧录后却失败。
目前为止只成功过三次,很奇怪,不知道什么原因??
我用的是MPU9250
初始化程序按照您的移植,9250和9255寄存器地址都一样
MPU9250_Write_Reg(PWR_MGMT_1,0X80);
MPU9250_Write_Reg(PWR_MGMT_1,0X01);
MPU9250_Write_Reg(USER_CTRL,0X30);
MPU9250_Write_Reg(PWR_MGMT_2,0X00);
MPU9250_Write_Reg(SMPLRT_DIV,0x00);
// MPU9250_Write_Reg(CONFIG,0X06);
MPU9250_Write_Reg(CONFIG,0X03);
MPU9250_Write_Reg(GYRO_CONFIG,0X18);
MPU9250_Write_Reg(ACCEL_CONFIG,0x18);
MPU9250_Write_Reg(ACCEL_CONFIG2,0);
ret = MPU9250_Read_Regs(WHO_AM_I, 1, &id);
if(ret<0) return ret;
if(id!=0x71)
return -1;
osDelay(1);
id = MPU9250_Mag_ReadReg(AK8963_WIA);
if(ret<0) return ret;
if(id!=0x48)
return -1;
osDelay(1);
MPU9255_Mag_WriteReg(AK8963_CNTL2,0x01);
osDelay(10);
MPU9255_Mag_WriteReg(AK8963_CNTL1,0x16);
osDelay(10);
MPU9250_Write_Reg(MPU9250_I2C_SLV0_REG,AK8963_ST1);
MPU9250_Write_Reg(MPU9250_I2C_SLV0_ADDR,AK8963_I2C_ADDR | 0x80);
MPU9250_Write_Reg(MPU9250_I2C_SLV0_CTRL,0x80 | 8); 使用MPU9255成功读出了9轴的数据,但是后续加入DMP后反而无法读取磁力计的信号,不知道大家遇到这种情况没有? 谢谢分享!美丽的台湾朋友 恋芜 发表于 2018-11-30 04:55
谢谢分享!美丽的台湾朋友
Chinese Taipei!
页:
[1]