123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 |
- /*
- * MPU6050.c
- *
- * Created on: Oct 26, 2021
- * Author: Administrator
- */
- #include "MPU6050.h"
- #include <stdio.h>
- extern int a;
- extern int t;
- u8 IIC_Write_Byte(u8 reg, u8 value)
- {
- return IIC_Write_Len(a, reg, 1, &value);
- }
- u8 IIC_Read_Byte(u8 reg)
- {
- u8 value = 0;
- IIC_Read_Len(a, reg, 1, &value);
- return value;
- }
- //IIC连续写
- u8 IIC_Write_Len(u8 addr,u8 reg, u8 len, u8 *buf)
- {
-
- addr = a;
-
- addr = (addr << 1) | 0;
- u8 data[10] = {0};
- data[0] = reg;
- for(int i = 0; i < len; i++)
- {
- data[1 + i] = buf[i];
- }
- if(t==1){
- if(HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)addr, (uint8_t*)data, len + 1, 10000)!= HAL_OK)
- {
- printf("++write len byte fail\r\n");
- return 1;
- }
- }
- else if(t==2){
- if(HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)addr, (uint8_t*)data, len + 1, 10000)!= HAL_OK)
- {
- printf("++write len byte fail\r\n");
- return 1;
- }
- }
- else if(t==3){
- if(HAL_I2C_Master_Transmit(&hi2c3, (uint16_t)addr, (uint8_t*)data, len + 1, 10000)!= HAL_OK)
- {
- printf("++write len byte fail\r\n");
- return 1;
- }
- }
- return 0;
- }
- //IIC连续读
- u8 IIC_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
- {
-
- addr = a;
- if(t==1){
- u8 tmp = (addr << 1) | 0;
- if(HAL_I2C_Master_Transmit(&hi2c1, (uint16_t)tmp, (uint8_t*)®, 1, 10000)!= HAL_OK)
- {
- printf("++write byte fail\r\n");
- return 1;
- }
- tmp = (addr << 1) | 1;
- if(HAL_I2C_Master_Receive(&hi2c1, (uint16_t)tmp, (uint8_t *)buf, len, 10000) != HAL_OK)
- {
- printf("--read byte fail\r\n");
- }
- }
- else if(t==2){
- u8 tmp = (addr << 1) | 0;
- if(HAL_I2C_Master_Transmit(&hi2c2, (uint16_t)tmp, (uint8_t*)®, 1, 10000)!= HAL_OK)
- {
- printf("++write byte fail\r\n");
- return 1;
- }
- tmp = (addr << 1) | 1;
- if(HAL_I2C_Master_Receive(&hi2c2, (uint16_t)tmp, (uint8_t *)buf, len, 10000) != HAL_OK)
- {
- printf("--read byte fail\r\n");
- }
- }
- else if(t==3){
- u8 tmp = (addr << 1) | 0;
- if(HAL_I2C_Master_Transmit(&hi2c3, (uint16_t)tmp, (uint8_t*)®, 1, 10000)!= HAL_OK)
- {
- printf("++write byte fail\r\n");
- return 1;
- }
- tmp = (addr << 1) | 1;
- if(HAL_I2C_Master_Receive(&hi2c3, (uint16_t)tmp, (uint8_t *)buf, len, 10000) != HAL_OK)
- {
- printf("--read byte fail\r\n");
- }
- }
- }
- //初始化MPU6050
- //返回值: 0,成功
- // 其他,错误代码
- u8 MPU_Init(void)
- {
- u8 res = 0;
- IIC_Write_Byte(MPU_PWR_MGMT1_REG,0X80);//复位MPU6050
- HAL_Delay(100);
- IIC_Write_Byte(MPU_PWR_MGMT1_REG,0X00);//唤醒MPU6050
- MPU_Set_Gyro_Fsr(3); //陀螺仪传感器,±2000dps
- MPU_Set_Accel_Fsr(0); //加速度传感器 ±2g
- MPU_Set_Rate(50); //设置采样率50HZ
- IIC_Write_Byte(MPU_INT_EN_REG,0X00); //关闭所有中断
- IIC_Write_Byte(MPU_USER_CTRL_REG,0X00);//I2C主模式关闭
- IIC_Write_Byte(MPU_FIFO_EN_REG,0X00);//关闭FIFO
- IIC_Write_Byte(MPU_INTBP_CFG_REG,0X80);//INT引脚低电平有效
- res=IIC_Read_Byte(MPU_DEVICE_ID_REG);
- printf("the addr is:%d\r\n", res);
- if(res==a)//器件ID正确
- {
- IIC_Write_Byte(MPU_PWR_MGMT1_REG,0X01);//设置CLKSEL,PLL X 轴为参考
- IIC_Write_Byte(MPU_PWR_MGMT2_REG,0X00);//加速度陀螺仪都工作
- MPU_Set_Rate(50); //设置采样率为50HZ
- }
- else
- {
- return 1;
- }
- return 0;
- }
- //设置MPU6050陀螺仪传感器满量程范围
- //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
- //返回值:0,设置成功
- // 其他,设置失败
- u8 MPU_Set_Gyro_Fsr(u8 fsr)
- {
- return IIC_Write_Byte(MPU_GYRO_CFG_REG, fsr<<3);//设置陀螺仪满量程范围
- }
- //设置MPU6050加速度传感器满量程范围
- //fsr:0,±2g;1,±4g;2,±8g;3,±16g
- //返回值:0,设置成功
- // 其他,设置失败
- u8 MPU_Set_Accel_Fsr(u8 fsr)
- {
- return IIC_Write_Byte(MPU_ACCEL_CFG_REG, fsr<<3);//设置加速度传感器满量程范围
- }
- //设置MPU6050的数字低通滤波器
- //lpf:数字低通滤波频率(Hz)
- //返回值:0,设置成功
- // 其他,设置失败
- u8 MPU_Set_LPF(u16 lpf)
- {
- u8 data=0;
- if(lpf>=188) data=1;
- else if(lpf>=98) data=2;
- else if(lpf>=42) data=2;
- else if(lpf>=42) data=3;
- else if(lpf>=20) data=4;
- else if(lpf>=10) data=5;
- else data=6;
- return IIC_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器
- }
- //设置MPU6050的采样率(假定Fs=1KHz)
- //rate:4~1000(Hz)
- //返回值:0,设置成功
- // 其他,设置失败
- u8 MPU_Set_Rate(u16 rate)
- {
- u8 data;
- if(rate>1000)rate=1000;
- if(rate<4)rate=4;
- data=1000/rate-1;
- data=IIC_Write_Byte(MPU_SAMPLE_RATE_REG, data); //设置数字低通滤波器
- return MPU_Set_LPF(rate/2); //自动设置LPF为采样率的一半
- }
- //得到温度值
- //返回值:温度值(扩大了100倍)
- short MPU_Get_Temperature(void)
- {
- u8 buf[2];
- short raw;
- float temp;
- IIC_Read_Len(a, MPU_TEMP_OUTH_REG, 2, buf);
- raw=((u16)buf[0]<<8)|buf[1];
- temp=36.53+((double)raw)/340;
- return temp*100;;
- }
- //得到陀螺仪值(原始值)
- //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
- //返回值:0,成功
- // 其他,错误代码
- u8 MPU_Get_Gyroscope(short *gx,short *gy,short *gz)
- {
- u8 buf[6],res;
- res=IIC_Read_Len(a,MPU_GYRO_XOUTH_REG,6,buf);
- if(res==0)
- {
- *gx=((u16)buf[0]<<8)|buf[1];
- *gy=((u16)buf[2]<<8)|buf[3];
- *gz=((u16)buf[4]<<8)|buf[5];
- }
- return res;
- }
- //得到加速度值(原始值)
- //ax,ay,az:陀螺仪x,y,z轴的原始读数(带符号)
- //返回值:0,成功
- // 其他,错误代码
- u8 MPU_Get_Accelerometer(short *ax,short *ay,short *az)
- {
- u8 buf[6],res;
- res=IIC_Read_Len(a,MPU_ACCEL_XOUTH_REG,6,buf);
- if(res==0)
- {
- *ax=((u16)buf[0]<<8)|buf[1];
- *ay=((u16)buf[2]<<8)|buf[3];
- *az=((u16)buf[4]<<8)|buf[5];
- }
- return res;;
- }
- /*--------------------以下为使用板载固件DMP的相关代码,这个融合得到的姿态角效果很好*/
- /**
- * @brief 获取当前毫秒值
- * @param 存储最新毫秒值的变量
- * @retval 无
- */
- int get_tick_count(unsigned long *count)
- {
- count[0] = HAL_GetTick();
- return 0;
- }
- #include "inv_mpu.h"
- #include "inv_mpu_dmp_motion_driver.h"
- /* Data requested by client. */
- #define PRINT_ACCEL (0x01)
- #define PRINT_GYRO (0x02)
- #define PRINT_QUAT (0x04)
- #define ACCEL_ON (0x01)
- #define GYRO_ON (0x02)
- #define MOTION (0)
- #define NO_MOTION (1)
- /* Starting sampling rate. */ //100
- #define DEFAULT_MPU_HZ (50)
- struct rx_s {
- unsigned char header[3];
- unsigned char cmd;
- };
- struct hal_s {
- unsigned char sensors;
- unsigned char dmp_on;
- unsigned char wait_for_tap;
- volatile unsigned char new_gyro;
- unsigned short report;
- unsigned short dmp_features;
- unsigned char motion_int_mode;
- struct rx_s rx;
- };
- static struct hal_s hal = {0};
- /* USB RX binary semaphore. Actually, it's just a flag. Not included in struct
- * because it's declared extern elsewhere.
- */
- volatile unsigned char rx_new;
- /* The sensors can be mounted onto the board in any orientation. The mounting
- * matrix seen below tells the MPL how to rotate the raw data from thei
- * driver(s).
- * TODO: The following matrices refer to the configuration on an internal test
- * board at Invensense. If needed, please modify the matrices to match the
- * chip-to-body matrix for your particular set up.
- */
- static signed char gyro_orientation[9] = {-1, 0, 0,
- 0,-1, 0,
- 0, 0, 1};
- /* Every time new gyro data is available, this function is called in an
- * ISR context. In this example, it sets a flag protecting the FIFO read
- * function.
- */
- static void gyro_data_ready_cb(void)
- {
- hal.new_gyro = 1;
- }
- enum packet_type_e {
- PACKET_TYPE_ACCEL,
- PACKET_TYPE_GYRO,
- PACKET_TYPE_QUAT,
- PACKET_TYPE_TAP,
- PACKET_TYPE_ANDROID_ORIENT,
- PACKET_TYPE_PEDO,
- PACKET_TYPE_MISC
- };
- #define BYTE u_char
- /* Send data to the Python client application.
- * Data is formatted as follows:
- * packet[0] = $
- * packet[1] = packet type (see packet_type_e)
- * packet[2+] = data
- */
- void send_packet(char packet_type, void *data)
- {
- #define MAX_BUF_LENGTH (18)
- char buf[MAX_BUF_LENGTH], length;
- memset(buf, 0, MAX_BUF_LENGTH);
- buf[0] = '$';
- buf[1] = packet_type;
- if (packet_type == PACKET_TYPE_ACCEL || packet_type == PACKET_TYPE_GYRO) {
- short *sdata = (short*)data;
- buf[2] = (char)(sdata[0] >> 8);
- buf[3] = (char)sdata[0];
- buf[4] = (char)(sdata[1] >> 8);
- buf[5] = (char)sdata[1];
- buf[6] = (char)(sdata[2] >> 8);
- buf[7] = (char)sdata[2];
- length = 8;
- } else if (packet_type == PACKET_TYPE_QUAT) {
- long *ldata = (long*)data;
- buf[2] = (char)(ldata[0] >> 24);
- buf[3] = (char)(ldata[0] >> 16);
- buf[4] = (char)(ldata[0] >> 8);
- buf[5] = (char)ldata[0];
- buf[6] = (char)(ldata[1] >> 24);
- buf[7] = (char)(ldata[1] >> 16);
- buf[8] = (char)(ldata[1] >> 8);
- buf[9] = (char)ldata[1];
- buf[10] = (char)(ldata[2] >> 24);
- buf[11] = (char)(ldata[2] >> 16);
- buf[12] = (char)(ldata[2] >> 8);
- buf[13] = (char)ldata[2];
- buf[14] = (char)(ldata[3] >> 24);
- buf[15] = (char)(ldata[3] >> 16);
- buf[16] = (char)(ldata[3] >> 8);
- buf[17] = (char)ldata[3];
- length = 18;
- } else if (packet_type == PACKET_TYPE_TAP) {
- buf[2] = ((char*)data)[0];
- buf[3] = ((char*)data)[1];
- length = 4;
- } else if (packet_type == PACKET_TYPE_ANDROID_ORIENT) {
- buf[2] = ((char*)data)[0];
- length = 3;
- } else if (packet_type == PACKET_TYPE_PEDO) {
- long *ldata = (long*)data;
- buf[2] = (char)(ldata[0] >> 24);
- buf[3] = (char)(ldata[0] >> 16);
- buf[4] = (char)(ldata[0] >> 8);
- buf[5] = (char)ldata[0];
- buf[6] = (char)(ldata[1] >> 24);
- buf[7] = (char)(ldata[1] >> 16);
- buf[8] = (char)(ldata[1] >> 8);
- buf[9] = (char)ldata[1];
- length = 10;
- } else if (packet_type == PACKET_TYPE_MISC) {
- buf[2] = ((char*)data)[0];
- buf[3] = ((char*)data)[1];
- buf[4] = ((char*)data)[2];
- buf[5] = ((char*)data)[3];
- length = 6;
- }
- // cdcSendDataWaitTilDone((BYTE*)buf, length, CDC0_INTFNUM, 100);
- }
- /* These next two functions converts the orientation matrix (see
- * gyro_orientation) to a scalar representation for use by the DMP.
- * NOTE: These functions are borrowed from Invensense's MPL.
- */
- static inline unsigned short inv_row_2_scale(const signed char *row)
- {
- unsigned short b;
- if (row[0] > 0)
- b = 0;
- else if (row[0] < 0)
- b = 4;
- else if (row[1] > 0)
- b = 1;
- else if (row[1] < 0)
- b = 5;
- else if (row[2] > 0)
- b = 2;
- else if (row[2] < 0)
- b = 6;
- else
- b = 7; // error
- return b;
- }
- static inline unsigned short inv_orientation_matrix_to_scalar(
- const signed char *mtx)
- {
- unsigned short scalar;
- /*
- XYZ 010_001_000 Identity Matrix
- XZY 001_010_000
- YXZ 010_000_001
- YZX 000_010_001
- ZXY 001_000_010
- ZYX 000_001_010
- */
- scalar = inv_row_2_scale(mtx);
- scalar |= inv_row_2_scale(mtx + 3) << 3;
- scalar |= inv_row_2_scale(mtx + 6) << 6;
- return scalar;
- }
- static inline void run_self_test(void)
- {
- int result;
- char test_packet[4] = {0};
- long gyro[3], accel[3];
- result = mpu_run_self_test(gyro, accel);
- if (result == 0x7) {
- /* Test passed. We can trust the gyro data here, so let's push it down
- * to the DMP.
- */
- float sens;
- unsigned short accel_sens;
- mpu_get_gyro_sens(&sens);
- gyro[0] = (long)(gyro[0] * sens);
- gyro[1] = (long)(gyro[1] * sens);
- gyro[2] = (long)(gyro[2] * sens);
- dmp_set_gyro_bias(gyro);
- mpu_get_accel_sens(&accel_sens);
- accel[0] *= accel_sens;
- accel[1] *= accel_sens;
- accel[2] *= accel_sens;
- dmp_set_accel_bias(accel);
- }
- /* Report results. */
- test_packet[0] = 't';
- test_packet[1] = result;
- send_packet(PACKET_TYPE_MISC, test_packet);
- }
- #define INT_EXIT_LPM0 12
- void DMP_Init(void)
- {
- struct int_param_s int_param;
- /* Set up gyro.
- * Every function preceded by mpu_ is a driver function and can be found
- * in inv_mpu.h.
- */
- int_param.cb = gyro_data_ready_cb;
- int_param.pin = 16;
- int_param.lp_exit = INT_EXIT_LPM0;
- int_param.active_low = 1;
- int result = mpu_init(&int_param);
- printf("mpu_init, %d\r\n", result);
- if(result == 0) //mpu初始化
- {
- if(!mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL)) //设置需要的传感器
- printf("mpu_set_sensor complete ......\r\n");
- if(!mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL)) //设置fifo
- printf("mpu_configure_fifo complete ......\r\n");
- if(!mpu_set_sample_rate(DEFAULT_MPU_HZ)) //设置采集样率
- printf("mpu_set_sample_rate complete ......\r\n");
- unsigned short gyro_rate = 0, gyro_fsr = 0;
- unsigned char accel_fsr = 0;
- mpu_get_sample_rate(&gyro_rate);
- mpu_get_gyro_fsr(&gyro_fsr);
- mpu_get_accel_fsr(&accel_fsr);
- printf("gyro_rate %d, gyro_fsr %d, accel_fsr %d\r\n", gyro_rate, gyro_fsr, accel_fsr);
- if(!dmp_load_motion_driver_firmware()) //加载dmp固件
- printf("dmp_load_motion_driver_firmware complete ......\r\n");
- if(!dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation)))
- printf("dmp_set_orientation complete ......\r\n"); //设置陀螺仪方向
- if(!dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP |
- DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO |
- DMP_FEATURE_GYRO_CAL))
- printf("dmp_enable_feature complete ......\r\n");
- if(!dmp_set_fifo_rate(DEFAULT_MPU_HZ)) //设置速率
- printf("dmp_set_fifo_rate complete ......\r\n");
- run_self_test(); //自检(非必要)
- if(!mpu_set_dmp_state(1)) //使能
- printf("mpu_set_dmp_state complete ......\r\n");
- }
- }
- #define q30 1073741824.0
- uint8_t Read_DMP(float* Pitch,float* Roll,float* Yaw)
- {
- short gyro[3], accel[3], sensors;
- float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;
- unsigned long sensor_timestamp;
- unsigned char more;
- long quat[4];
- int ret = dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors, &more);
- // printf("dmp_read_fifo, %d\r\n", ret);
- if(ret)
- {
- return 1;
- }
- if (sensors & INV_WXYZ_QUAT)
- {
- q0=quat[0] / q30;
- q1=quat[1] / q30;
- q2=quat[2] / q30;
- q3=quat[3] / q30;
- *Pitch = (float)asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3;
- *Roll = (float)atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
- *Yaw = (float)atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3;
- return 0;
- }
- else
- {
- return 2;
- }
- }
|