(五)麒麟座读取MPU6050
时间:10-02
整理:3721RD
点击:
平衡车的陀螺仪部件,我使用的MPU6050模块。左侧那个洞洞板上,上方红色的是电机驱动。中间蓝色的小模块就是MPU6050。连线如图,可能看不清,下面会详细介绍。
查看麒麟座开发板的原理图可以看到,有一些没有用到的引脚。之所以不占用板子上其他资源的IO口,主要是考虑到,小车跑起来之后 还要用板子上的传感器采集信息。所以只能用剩下的引脚东拼西凑了。
决定用PB3引脚做IIC通讯的SCK时钟线,PB4引脚做SDA数据线。右侧 PA8-PA11为定时器1的4个通道,后面可以用来做PWM输出作为直流电机驱动的输入信号。或者给电机编码器使用。左侧的PC0-PC3被1602占用了。可以说如果不放弃板子原本就带的一些传感器的话,可用的引脚资源非常少 - -
IIC通讯采用软件模拟的方式,下面是IIC底层驱动程序。
- <blockquote>/**************************êμ??oˉêy********************************************
MPU6050初始化,数据读取。
- /**************************êμ??oˉêy********************************************
- 将新的ADC数据更新到FIFO数组,做滤波处理
- *******************************************************************************/
- void MPU6050_newValues(int16_t ax,int16_t ay,int16_t az,int16_t gx,int16_t gy,int16_t gz)
- {
- unsigned char i ;
- int32_t sum=0;
- for(i=1;i<10;i++){ //FIFO 2ù×÷
- MPU6050_FIFO[0][i-1]=MPU6050_FIFO[0][i];
- MPU6050_FIFO[1][i-1]=MPU6050_FIFO[1][i];
- MPU6050_FIFO[2][i-1]=MPU6050_FIFO[2][i];
- MPU6050_FIFO[3][i-1]=MPU6050_FIFO[3][i];
- MPU6050_FIFO[4][i-1]=MPU6050_FIFO[4][i];
- MPU6050_FIFO[5][i-1]=MPU6050_FIFO[5][i];
- }
- MPU6050_FIFO[0][9]=ax;//??D?μ?êy?Y·???μ? êy?Yμ?×?oó??
- MPU6050_FIFO[1][9]=ay;
- MPU6050_FIFO[2][9]=az;
- MPU6050_FIFO[3][9]=gx;
- MPU6050_FIFO[4][9]=gy;
- MPU6050_FIFO[5][9]=gz;
- sum=0;
- for(i=0;i<10;i++){ //?óμ±?°êy×éμ?o?£??ùè????ù?μ
- sum+=MPU6050_FIFO[0][i];
- }
- MPU6050_FIFO[0][10]=sum/10;
- sum=0;
- for(i=0;i<10;i++){
- sum+=MPU6050_FIFO[1][i];
- }
- MPU6050_FIFO[1][10]=sum/10;
- sum=0;
- for(i=0;i<10;i++){
- sum+=MPU6050_FIFO[2][i];
- }
- MPU6050_FIFO[2][10]=sum/10;
- sum=0;
- for(i=0;i<10;i++){
- sum+=MPU6050_FIFO[3][i];
- }
- MPU6050_FIFO[3][10]=sum/10;
- sum=0;
- for(i=0;i<10;i++){
- sum+=MPU6050_FIFO[4][i];
- }
- MPU6050_FIFO[4][10]=sum/10;
- sum=0;
- for(i=0;i<10;i++){
- sum+=MPU6050_FIFO[5][i];
- }
- MPU6050_FIFO[5][10]=sum/10;
- }
- /**************************êμ??oˉêy********************************************
- 设置MPU6050的时钟源
- * CLK_SEL | Clock Source
- * --------+--------------------------------------
- * 0 | Internal oscillator
- * 1 | PLL with X Gyro reference
- * 2 | PLL with Y Gyro reference
- * 3 | PLL with Z Gyro reference
- * 4 | PLL with external 32.768kHz reference
- * 5 | PLL with external 19.2MHz reference
- * 6 | Reserved
- * 7 | Stops the clock and keeps the timing generator in reset
- *******************************************************************************/
- void MPU6050_setClockSource(uint8_t source){
- IICwriteBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source);
- }
- /** Set full-scale gyroscope range.
- * @param range New full-scale gyroscope range value
- * [url=home.php?mod=space&uid=1466806]@SEE[/url] getFullScaleRange()
- * @see MPU6050_GYRO_FS_250
- * @see MPU6050_RA_GYRO_CONFIG
- * @see MPU6050_GCONFIG_FS_SEL_BIT
- * @see MPU6050_GCONFIG_FS_SEL_LENGTH
- */
- void MPU6050_setFullScaleGyroRange(uint8_t range) {
- IICwriteBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range);
- }
- /**************************êμ??oˉêy********************************************
- 设置加速度计的最大量程
- *******************************************************************************/
- void MPU6050_setFullScaleAccelRange(uint8_t range) {
- IICwriteBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range);
- }
- /**************************êμ??oˉêy********************************************
- 设置是否进入睡眠模式
- *******************************************************************************/
- void MPU6050_setSleepEnabled(uint8_t enabled) {
- IICwriteBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled);
- }
- /**************************êμ??oˉêy********************************************
- 读取芯片ID
- *******************************************************************************/
- uint8_t MPU6050_getDeviceID(void) {
- IICreadBytes(devAddr, MPU6050_RA_WHO_AM_I, 1, buffer);
- return buffer[0];
- }
- /**************************êμ??oˉêy********************************************
- 检测是否已连接
- *******************************************************************************/
- uint8_t MPU6050_testConnection(void) {
- if(MPU6050_getDeviceID() == 0x68) //0b01101000;
- return 1;
- else return 0;
- }
- /**************************êμ??oˉêy********************************************
- 设置MPU6050是否做AUX IIC主机
- *******************************************************************************/
- void MPU6050_setI2CMasterModeEnabled(uint8_t enabled) {
- IICwriteBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled);
- }
- /**************************êμ??oˉêy********************************************
- *******************************************************************************/
- void MPU6050_setI2CBypassEnabled(uint8_t enabled) {
- IICwriteBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled);
- }
- /**************************êμ??oˉêy********************************************
- 初始化
- *******************************************************************************/
- void MPU6050_initialize(void) {
- MPU6050_setClockSource(MPU6050_CLOCK_PLL_YGYRO); //éè??ê±?ó
- MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_2000);//íó?Yò?×?′óá?3ì +-1000?è????
- MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2); //?ó?ù?è?è×?′óá?3ì +-2G
- MPU6050_setSleepEnabled(0); //??è?1¤×÷×′ì?
- MPU6050_setI2CMasterModeEnabled(0); //2?è?MPU6050 ????AUXI2C
- MPU6050_setI2CBypassEnabled(0); //?÷?????÷μ?I2Có? MPU6050μ?AUXI2C ?±í¨?£?????÷?éò??±?ó·??êHMC5883L
- }
- /**************************************************************************
- <span style="background-color: rgb(255, 255, 255);">获取姿态信息</span>
- **************************************************************************/
- void Get_Angle(u8 way)
- {
- float Accel_Y,Accel_X,Accel_Z,Gyro_Y,Gyro_Z;
- Temperature=Read_Temperature(); //===?áè?MPU6050?ú?????è′??D?÷êy?Y£??ü??±íê??÷°????è?£
- if(way==1) //===DMPμ??áè??úêy?Y2é?ˉ?D??ìáD?μ?ê±oò£?????×??-ê±Dòòa?ó
- {
- Read_DMP(); //===?áè??ó?ù?è?¢???ù?è?¢????
- Angle_Balance=Pitch; //===?üD???oa????
- Gyro_Balance=gyro[1]; //===?üD???oa???ù?è
- Gyro_Turn=gyro[2]; //===?üD?×a?ò???ù?è
- Acceleration_Z=accel[2]; //===?üD?Z?á?ó?ù?è??
- }
- else
- {
- Gyro_Y=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_YOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_YOUT_L); //?áè?Y?áíó?Yò?
- Gyro_Z=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_L); //?áè?Z?áíó?Yò?
- Accel_X=(I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_XOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_XOUT_L); //?áè?X?á?ó?ù?è??
- Accel_Z=(I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_ZOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_ZOUT_L); //?áè?Z?á?ó?ù?è??
- if(Gyro_Y>32768) Gyro_Y-=65536; //êy?YààDí×a?? ò2?éí¨1yshort????ààDí×a??
- if(Gyro_Z>32768) Gyro_Z-=65536; //êy?YààDí×a??
- if(Accel_X>32768) Accel_X-=65536; //êy?YààDí×a??
- if(Accel_Z>32768) Accel_Z-=65536; //êy?YààDí×a??
- Gyro_Balance=-Gyro_Y; //?üD???oa???ù?è
- Accel_Y=atan2(Accel_X,Accel_Z)*180/PI; //????????
- Gyro_Y=Gyro_Y/16.4; //íó?Yò?á?3ì×a??
- if(Way_Angle==2) Kalman_Filter(Accel_Y,-Gyro_Y);//?¨???ü??2¨
- else if(Way_Angle==3) Yijielvbo(Accel_Y,-Gyro_Y); //?¥21??2¨
- Angle_Balance=angle; //?üD???oa????
- Gyro_Turn=Gyro_Z; //?üD?×a?ò???ù?è
- Acceleration_Z=Accel_Z; //===?üD?Z?á?ó?ù?è??
- }
- }
通过IO引脚模拟I2C程序,读取MPU6050的ADC转换结果。进行姿态解算。麒麟座的PA9 PA10两个IO引脚虽然作为USRAT1串口,可以打印姿态到电脑上,但是由于资源有限,这两个引脚打算作为PWM输出信号给直流电机驱动板。暂时把姿态信息显示在1602液晶屏上看看效果。