/* * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 *//** * @file * @brief MPU6050 driver */#pragma once#ifdef __cplusplusextern"C"{#endif#include"driver/i2c.h"#include"driver/gpio.h"#include"i2c.h"#define MPU6050_I2C_ADDRESS 0x68u /*!< I2C address with AD0 pin low */#define MPU6050_I2C_ADDRESS_1 0x69u /*!< I2C address with AD0 pin high */#define MPU6050_WHO_AM_I_VAL 0x68utypedefenum{ACCE_FS_2G=0,/*!< Accelerometer full scale range is +/- 2g */ACCE_FS_4G=1,/*!< Accelerometer full scale range is +/- 4g */ACCE_FS_8G=2,/*!< Accelerometer full scale range is +/- 8g */ACCE_FS_16G=3,/*!< Accelerometer full scale range is +/- 16g */}mpu6050_acce_fs_t;typedefenum{GYRO_FS_250DPS=0,/*!< Gyroscope full scale range is +/- 250 degree per sencond */GYRO_FS_500DPS=1,/*!< Gyroscope full scale range is +/- 500 degree per sencond */GYRO_FS_1000DPS=2,/*!< Gyroscope full scale range is +/- 1000 degree per sencond */GYRO_FS_2000DPS=3,/*!< Gyroscope full scale range is +/- 2000 degree per sencond */}mpu6050_gyro_fs_t;typedefenum{INTERRUPT_PIN_ACTIVE_HIGH=0,/*!< The mpu6050 sets its INT pin HIGH on interrupt */INTERRUPT_PIN_ACTIVE_LOW=1/*!< The mpu6050 sets its INT pin LOW on interrupt */}mpu6050_int_pin_active_level_t;typedefenum{INTERRUPT_PIN_PUSH_PULL=0,/*!< The mpu6050 configures its INT pin as push-pull */INTERRUPT_PIN_OPEN_DRAIN=1/*!< The mpu6050 configures its INT pin as open drain*/}mpu6050_int_pin_mode_t;typedefenum{INTERRUPT_LATCH_50US=0,/*!< The mpu6050 produces a 50 microsecond pulse on interrupt */INTERRUPT_LATCH_UNTIL_CLEARED=1/*!< The mpu6050 latches its INT pin to its active level, until interrupt is cleared */}mpu6050_int_latch_t;typedefenum{INTERRUPT_CLEAR_ON_ANY_READ=0,/*!< INT_STATUS register bits are cleared on any register read */INTERRUPT_CLEAR_ON_STATUS_READ=1/*!< INT_STATUS register bits are cleared only by reading INT_STATUS value*/}mpu6050_int_clear_t;typedefstruct{gpio_num_tinterrupt_pin;/*!< GPIO connected to mpu6050 INT pin */mpu6050_int_pin_active_level_tactive_level;/*!< Active level of mpu6050 INT pin */mpu6050_int_pin_mode_tpin_mode;/*!< Push-pull or open drain mode for INT pin*/mpu6050_int_latch_tinterrupt_latch;/*!< The interrupt pulse behavior of INT pin */mpu6050_int_clear_tinterrupt_clear_behavior;/*!< Interrupt status clear behavior */}mpu6050_int_config_t;externconstuint8_tMPU6050_DATA_RDY_INT_BIT;/*!< DATA READY interrupt bit */externconstuint8_tMPU6050_I2C_MASTER_INT_BIT;/*!< I2C MASTER interrupt bit */externconstuint8_tMPU6050_FIFO_OVERFLOW_INT_BIT;/*!< FIFO Overflow interrupt bit */externconstuint8_tMPU6050_MOT_DETECT_INT_BIT;/*!< MOTION DETECTION interrupt bit */externconstuint8_tMPU6050_ALL_INTERRUPTS;/*!< All interrupts supported by mpu6050 */typedefstruct{int16_traw_acce_x;int16_traw_acce_y;int16_traw_acce_z;}mpu6050_raw_acce_value_t;typedefstruct{int16_traw_gyro_x;int16_traw_gyro_y;int16_traw_gyro_z;}mpu6050_raw_gyro_value_t;typedefstruct{floatacce_x;floatacce_y;floatacce_z;}mpu6050_acce_value_t;typedefstruct{floatgyro_x;floatgyro_y;floatgyro_z;}mpu6050_gyro_value_t;typedefstruct{floattemp;}mpu6050_temp_value_t;typedefstruct{floatroll;floatpitch;}complimentary_angle_t;typedefvoid*mpu6050_handle_t;externmpu6050_handle_tmpu6050;typedefgpio_isr_tmpu6050_isr_t;/** * @brief Create and init sensor object and return a sensor handle * * @param port I2C port number * @param dev_addr I2C device address of sensor * * @return * - NULL Fail * - Others Success */mpu6050_handle_tmpu6050_create(i2c_port_tport,constuint16_tdev_addr);/** * @brief Delete and release a sensor object * * @param sensor object handle of mpu6050 */voidmpu6050_delete(mpu6050_handle_tsensor);/** * @brief Get device identification of MPU6050 * * @param sensor object handle of mpu6050 * @param deviceid a pointer of device ID * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_get_deviceid(mpu6050_handle_tsensor,uint8_t*constdeviceid);/** * @brief Wake up MPU6050 * * @param sensor object handle of mpu6050 * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_wake_up(mpu6050_handle_tsensor);/** * @brief Enter sleep mode * * @param sensor object handle of mpu6050 * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_sleep(mpu6050_handle_tsensor);/** * @brief Set accelerometer and gyroscope full scale range * * @param sensor object handle of mpu6050 * @param acce_fs accelerometer full scale range * @param gyro_fs gyroscope full scale range * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_config(mpu6050_handle_tsensor,constmpu6050_acce_fs_tacce_fs,constmpu6050_gyro_fs_tgyro_fs);/** * @brief Get accelerometer sensitivity * * @param sensor object handle of mpu6050 * @param acce_sensitivity accelerometer sensitivity * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_get_acce_sensitivity(mpu6050_handle_tsensor,float*constacce_sensitivity);/** * @brief Get gyroscope sensitivity * * @param sensor object handle of mpu6050 * @param gyro_sensitivity gyroscope sensitivity * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_get_gyro_sensitivity(mpu6050_handle_tsensor,float*constgyro_sensitivity);/** * @brief Configure INT pin behavior and setup target GPIO. * * @param sensor object handle of mpu6050 * @param interrupt_configuration mpu6050 INT pin configuration parameters * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG A parameter is NULL or incorrect * - ESP_FAIL Failed to configure INT pin on mpu6050 */esp_err_tmpu6050_config_interrupts(mpu6050_handle_tsensor,constmpu6050_int_config_t*constinterrupt_configuration);/** * @brief Register an Interrupt Service Routine to handle mpu6050 interrupts. * * @param sensor object handle of mpu6050 * @param isr function to handle interrupts produced by mpu6050 * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG A parameter is NULL or not valid * - ESP_FAIL Failed to register ISR */esp_err_tmpu6050_register_isr(mpu6050_handle_tsensor,constmpu6050_isr_tisr);/** * @brief Enable specific interrupts from mpu6050 * * @param sensor object handle of mpu6050 * @param interrupt_sources bit mask with interrupt sources to enable * * This function does not disable interrupts not set in interrupt_sources. To disable * specific mpu6050 interrupts, use mpu6050_disable_interrupts(). * * To enable all mpu6050 interrupts, pass MPU6050_ALL_INTERRUPTS as the argument * for interrupt_sources. * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG A parameter is NULL or not valid * - ESP_FAIL Failed to enable interrupt sources on mpu6050 */esp_err_tmpu6050_enable_interrupts(mpu6050_handle_tsensor,uint8_tinterrupt_sources);/** * @brief Disable specific interrupts from mpu6050 * * @param sensor object handle of mpu6050 * @param interrupt_sources bit mask with interrupt sources to disable * * This function does not enable interrupts not set in interrupt_sources. To enable * specific mpu6050 interrupts, use mpu6050_enable_interrupts(). * * To disable all mpu6050 interrupts, pass MPU6050_ALL_INTERRUPTS as the * argument for interrupt_sources. * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG A parameter is NULL or not valid * - ESP_FAIL Failed to enable interrupt sources on mpu6050 */esp_err_tmpu6050_disable_interrupts(mpu6050_handle_tsensor,uint8_tinterrupt_sources);/** * @brief Get the interrupt status of mpu6050 * * @param sensor object handle of mpu6050 * @param out_intr_status[out] bit mask that is assigned a value representing the interrupts triggered by the mpu6050 * * This function can be used by the mpu6050 ISR to determine the source of * the mpu6050 interrupt that it is handling. * * After this function returns, the bits set in out_intr_status are * the sources of the latest interrupt triggered by the mpu6050. For example, * if MPU6050_DATA_RDY_INT_BIT is set in out_intr_status, the last interrupt * from the mpu6050 was a DATA READY interrupt. * * The behavior of the INT_STATUS register of the mpu6050 may change depending on * the value of mpu6050_int_clear_t used on interrupt configuration. * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG A parameter is NULL or not valid * - ESP_FAIL Failed to retrieve interrupt status from mpu6050 */esp_err_tmpu6050_get_interrupt_status(mpu6050_handle_tsensor,uint8_t*constout_intr_status);/** * @brief Determine if the last mpu6050 interrupt was due to data ready. * * @param interrupt_status mpu6050 interrupt status, obtained by invoking mpu6050_get_interrupt_status() * * @return * - 0: The interrupt was not produced due to data ready * - Any other positive integer: Interrupt was a DATA_READY interrupt */externuint8_tmpu6050_is_data_ready_interrupt(uint8_tinterrupt_status);/** * @brief Determine if the last mpu6050 interrupt was an I2C master interrupt. * * @param interrupt_status mpu6050 interrupt status, obtained by invoking mpu6050_get_interrupt_status() * * @return * - 0: The interrupt is not an I2C master interrupt * - Any other positive integer: Interrupt was an I2C master interrupt */externuint8_tmpu6050_is_i2c_master_interrupt(uint8_tinterrupt_status);/** * @brief Determine if the last mpu6050 interrupt was triggered by a fifo overflow. * * @param interrupt_status mpu6050 interrupt status, obtained by invoking mpu6050_get_interrupt_status() * * @return * - 0: The interrupt is not a fifo overflow interrupt * - Any other positive integer: Interrupt was triggered by a fifo overflow */externuint8_tmpu6050_is_fifo_overflow_interrupt(uint8_tinterrupt_status);/** * @brief Read raw accelerometer measurements * * @param sensor object handle of mpu6050 * @param raw_acce_value raw accelerometer measurements * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_get_raw_acce(mpu6050_handle_tsensor,mpu6050_raw_acce_value_t*constraw_acce_value);/** * @brief Read raw gyroscope measurements * * @param sensor object handle of mpu6050 * @param raw_gyro_value raw gyroscope measurements * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_get_raw_gyro(mpu6050_handle_tsensor,mpu6050_raw_gyro_value_t*constraw_gyro_value);/** * @brief Read accelerometer measurements * * @param sensor object handle of mpu6050 * @param acce_value accelerometer measurements * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_get_acce(mpu6050_handle_tsensor,mpu6050_acce_value_t*constacce_value);/** * @brief Read gyro values * * @param sensor object handle of mpu6050 * @param gyro_value gyroscope measurements * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_get_gyro(mpu6050_handle_tsensor,mpu6050_gyro_value_t*constgyro_value);/** * @brief Read temperature values * * @param sensor object handle of mpu6050 * @param temp_value temperature measurements * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_get_temp(mpu6050_handle_tsensor,mpu6050_temp_value_t*consttemp_value);/** * @brief Use complimentory filter to calculate roll and pitch * * @param sensor object handle of mpu6050 * @param acce_value accelerometer measurements * @param gyro_value gyroscope measurements * @param complimentary_angle complimentary angle * * @return * - ESP_OK Success * - ESP_FAIL Fail */esp_err_tmpu6050_complimentory_filter(mpu6050_handle_tsensor,constmpu6050_acce_value_t*constacce_value,constmpu6050_gyro_value_t*constgyro_value,complimentary_angle_t*constcomplimentary_angle);/** * @brief i2c master initialization * @note Must do i2c_bus_init() before calling this function, which is provided by i2c.c */voidi2c_sensor_mpu6050_init(void);#ifdef __cplusplus}#endif
/* * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */#include<stdio.h>#include<math.h>#include<time.h>#include<sys/time.h>#include"esp_system.h"#include"driver/i2c.h"#include"mpu6050.h"#define ALPHA 0.99f /*!< Weight of gyroscope */#define RAD_TO_DEG 57.27272727f /*!< Radians to degrees *//* MPU6050 register */#define MPU6050_GYRO_CONFIG 0x1Bu#define MPU6050_ACCEL_CONFIG 0x1Cu#define MPU6050_INTR_PIN_CFG 0x37u#define MPU6050_INTR_ENABLE 0x38u#define MPU6050_INTR_STATUS 0x3Au#define MPU6050_ACCEL_XOUT_H 0x3Bu#define MPU6050_GYRO_XOUT_H 0x43u#define MPU6050_TEMP_XOUT_H 0x41u#define MPU6050_PWR_MGMT_1 0x6Bu#define MPU6050_WHO_AM_I 0x75uconstuint8_tMPU6050_DATA_RDY_INT_BIT=(uint8_t)BIT0;constuint8_tMPU6050_I2C_MASTER_INT_BIT=(uint8_t)BIT3;constuint8_tMPU6050_FIFO_OVERFLOW_INT_BIT=(uint8_t)BIT4;constuint8_tMPU6050_MOT_DETECT_INT_BIT=(uint8_t)BIT6;constuint8_tMPU6050_ALL_INTERRUPTS=(MPU6050_DATA_RDY_INT_BIT|MPU6050_I2C_MASTER_INT_BIT|MPU6050_FIFO_OVERFLOW_INT_BIT|MPU6050_MOT_DETECT_INT_BIT);mpu6050_handle_tmpu6050=NULL;typedefstruct{i2c_port_tbus;gpio_num_tint_pin;uint16_tdev_addr;uint32_tcounter;floatdt;/*!< delay time between two measurements, dt should be small (ms level) */structtimeval*timer;}mpu6050_dev_t;staticesp_err_tmpu6050_write(mpu6050_handle_tsensor,constuint8_treg_start_addr,constuint8_t*constdata_buf,constuint8_tdata_len){mpu6050_dev_t*sens=(mpu6050_dev_t*)sensor;esp_err_tret;i2c_cmd_handle_tcmd=i2c_cmd_link_create();ret=i2c_master_start(cmd);assert(ESP_OK==ret);ret=i2c_master_write_byte(cmd,sens->dev_addr|I2C_MASTER_WRITE,true);assert(ESP_OK==ret);ret=i2c_master_write_byte(cmd,reg_start_addr,true);assert(ESP_OK==ret);ret=i2c_master_write(cmd,data_buf,data_len,true);assert(ESP_OK==ret);ret=i2c_master_stop(cmd);assert(ESP_OK==ret);ret=i2c_master_cmd_begin(sens->bus,cmd,1000/portTICK_PERIOD_MS);i2c_cmd_link_delete(cmd);returnret;}staticesp_err_tmpu6050_read(mpu6050_handle_tsensor,constuint8_treg_start_addr,uint8_t*constdata_buf,constuint8_tdata_len){mpu6050_dev_t*sens=(mpu6050_dev_t*)sensor;esp_err_tret;i2c_cmd_handle_tcmd=i2c_cmd_link_create();ret=i2c_master_start(cmd);assert(ESP_OK==ret);ret=i2c_master_write_byte(cmd,sens->dev_addr|I2C_MASTER_WRITE,true);assert(ESP_OK==ret);ret=i2c_master_write_byte(cmd,reg_start_addr,true);assert(ESP_OK==ret);ret=i2c_master_start(cmd);assert(ESP_OK==ret);ret=i2c_master_write_byte(cmd,sens->dev_addr|I2C_MASTER_READ,true);assert(ESP_OK==ret);ret=i2c_master_read(cmd,data_buf,data_len,I2C_MASTER_LAST_NACK);assert(ESP_OK==ret);ret=i2c_master_stop(cmd);assert(ESP_OK==ret);ret=i2c_master_cmd_begin(sens->bus,cmd,1000/portTICK_PERIOD_MS);i2c_cmd_link_delete(cmd);returnret;}mpu6050_handle_tmpu6050_create(i2c_port_tport,constuint16_tdev_addr){mpu6050_dev_t*sensor=(mpu6050_dev_t*)calloc(1,sizeof(mpu6050_dev_t));sensor->bus=port;sensor->dev_addr=dev_addr<<1;sensor->counter=0;sensor->dt=0;sensor->timer=(structtimeval*)calloc(1,sizeof(structtimeval));return(mpu6050_handle_t)sensor;}voidmpu6050_delete(mpu6050_handle_tsensor){mpu6050_dev_t*sens=(mpu6050_dev_t*)sensor;free(sens);}esp_err_tmpu6050_get_deviceid(mpu6050_handle_tsensor,uint8_t*constdeviceid){returnmpu6050_read(sensor,MPU6050_WHO_AM_I,deviceid,1);}esp_err_tmpu6050_wake_up(mpu6050_handle_tsensor){esp_err_tret;uint8_ttmp;ret=mpu6050_read(sensor,MPU6050_PWR_MGMT_1,&tmp,1);if(ESP_OK!=ret){returnret;}tmp&=(~BIT6);ret=mpu6050_write(sensor,MPU6050_PWR_MGMT_1,&tmp,1);returnret;}esp_err_tmpu6050_sleep(mpu6050_handle_tsensor){esp_err_tret;uint8_ttmp;ret=mpu6050_read(sensor,MPU6050_PWR_MGMT_1,&tmp,1);if(ESP_OK!=ret){returnret;}tmp|=BIT6;ret=mpu6050_write(sensor,MPU6050_PWR_MGMT_1,&tmp,1);returnret;}esp_err_tmpu6050_config(mpu6050_handle_tsensor,constmpu6050_acce_fs_tacce_fs,constmpu6050_gyro_fs_tgyro_fs){uint8_tconfig_regs[2]={gyro_fs<<3,acce_fs<<3};returnmpu6050_write(sensor,MPU6050_GYRO_CONFIG,config_regs,sizeof(config_regs));}esp_err_tmpu6050_get_acce_sensitivity(mpu6050_handle_tsensor,float*constacce_sensitivity){esp_err_tret;uint8_tacce_fs;ret=mpu6050_read(sensor,MPU6050_ACCEL_CONFIG,&acce_fs,1);acce_fs=(acce_fs>>3)&0x03;switch(acce_fs){caseACCE_FS_2G:*acce_sensitivity=16384;break;caseACCE_FS_4G:*acce_sensitivity=8192;break;caseACCE_FS_8G:*acce_sensitivity=4096;break;caseACCE_FS_16G:*acce_sensitivity=2048;break;default:break;}returnret;}esp_err_tmpu6050_get_gyro_sensitivity(mpu6050_handle_tsensor,float*constgyro_sensitivity){esp_err_tret;uint8_tgyro_fs;ret=mpu6050_read(sensor,MPU6050_GYRO_CONFIG,&gyro_fs,1);gyro_fs=(gyro_fs>>3)&0x03;switch(gyro_fs){caseGYRO_FS_250DPS:*gyro_sensitivity=131;break;caseGYRO_FS_500DPS:*gyro_sensitivity=65.5;break;caseGYRO_FS_1000DPS:*gyro_sensitivity=32.8;break;caseGYRO_FS_2000DPS:*gyro_sensitivity=16.4;break;default:break;}returnret;}esp_err_tmpu6050_config_interrupts(mpu6050_handle_tsensor,constmpu6050_int_config_t*constinterrupt_configuration){esp_err_tret=ESP_OK;if(NULL==interrupt_configuration){ret=ESP_ERR_INVALID_ARG;returnret;}if(GPIO_IS_VALID_GPIO(interrupt_configuration->interrupt_pin)){// Set GPIO connected to MPU6050 INT pin only when user configures interrupts.mpu6050_dev_t*sensor_device=(mpu6050_dev_t*)sensor;sensor_device->int_pin=interrupt_configuration->interrupt_pin;}else{ret=ESP_ERR_INVALID_ARG;returnret;}uint8_tint_pin_cfg=0x00;ret=mpu6050_read(sensor,MPU6050_INTR_PIN_CFG,&int_pin_cfg,1);if(ESP_OK!=ret){returnret;}if(INTERRUPT_PIN_ACTIVE_LOW==interrupt_configuration->active_level){int_pin_cfg|=BIT7;}if(INTERRUPT_PIN_OPEN_DRAIN==interrupt_configuration->pin_mode){int_pin_cfg|=BIT6;}if(INTERRUPT_LATCH_UNTIL_CLEARED==interrupt_configuration->interrupt_latch){int_pin_cfg|=BIT5;}if(INTERRUPT_CLEAR_ON_ANY_READ==interrupt_configuration->interrupt_clear_behavior){int_pin_cfg|=BIT4;}ret=mpu6050_write(sensor,MPU6050_INTR_PIN_CFG,&int_pin_cfg,1);if(ESP_OK!=ret){returnret;}gpio_int_type_tgpio_intr_type;if(INTERRUPT_PIN_ACTIVE_LOW==interrupt_configuration->active_level){gpio_intr_type=GPIO_INTR_NEGEDGE;}else{gpio_intr_type=GPIO_INTR_POSEDGE;}gpio_config_tint_gpio_config={.mode=GPIO_MODE_INPUT,.intr_type=gpio_intr_type,.pin_bit_mask=(BIT0<<interrupt_configuration->interrupt_pin)};ret=gpio_config(&int_gpio_config);returnret;}esp_err_tmpu6050_register_isr(mpu6050_handle_tsensor,constmpu6050_isr_tisr){esp_err_tret;mpu6050_dev_t*sensor_device=(mpu6050_dev_t*)sensor;if(NULL==sensor_device){ret=ESP_ERR_INVALID_ARG;returnret;}ret=gpio_isr_handler_add(sensor_device->int_pin,((gpio_isr_t)*(isr)),((void*)sensor));if(ESP_OK!=ret){returnret;}ret=gpio_intr_enable(sensor_device->int_pin);returnret;}esp_err_tmpu6050_enable_interrupts(mpu6050_handle_tsensor,uint8_tinterrupt_sources){esp_err_tret;uint8_tenabled_interrupts=0x00;ret=mpu6050_read(sensor,MPU6050_INTR_ENABLE,&enabled_interrupts,1);if(ESP_OK!=ret){returnret;}if(enabled_interrupts!=interrupt_sources){enabled_interrupts|=interrupt_sources;ret=mpu6050_write(sensor,MPU6050_INTR_ENABLE,&enabled_interrupts,1);}returnret;}esp_err_tmpu6050_disable_interrupts(mpu6050_handle_tsensor,uint8_tinterrupt_sources){esp_err_tret;uint8_tenabled_interrupts=0x00;ret=mpu6050_read(sensor,MPU6050_INTR_ENABLE,&enabled_interrupts,1);if(ESP_OK!=ret){returnret;}if(0!=(enabled_interrupts&interrupt_sources)){enabled_interrupts&=(~interrupt_sources);ret=mpu6050_write(sensor,MPU6050_INTR_ENABLE,&enabled_interrupts,1);}returnret;}esp_err_tmpu6050_get_interrupt_status(mpu6050_handle_tsensor,uint8_t*constout_intr_status){esp_err_tret;if(NULL==out_intr_status){ret=ESP_ERR_INVALID_ARG;returnret;}ret=mpu6050_read(sensor,MPU6050_INTR_STATUS,out_intr_status,1);returnret;}inlineuint8_tmpu6050_is_data_ready_interrupt(uint8_tinterrupt_status){return(MPU6050_DATA_RDY_INT_BIT==(MPU6050_DATA_RDY_INT_BIT&interrupt_status));}inlineuint8_tmpu6050_is_i2c_master_interrupt(uint8_tinterrupt_status){return(uint8_t)(MPU6050_I2C_MASTER_INT_BIT==(MPU6050_I2C_MASTER_INT_BIT&interrupt_status));}inlineuint8_tmpu6050_is_fifo_overflow_interrupt(uint8_tinterrupt_status){return(uint8_t)(MPU6050_FIFO_OVERFLOW_INT_BIT==(MPU6050_FIFO_OVERFLOW_INT_BIT&interrupt_status));}esp_err_tmpu6050_get_raw_acce(mpu6050_handle_tsensor,mpu6050_raw_acce_value_t*constraw_acce_value){uint8_tdata_rd[6];esp_err_tret=mpu6050_read(sensor,MPU6050_ACCEL_XOUT_H,data_rd,sizeof(data_rd));raw_acce_value->raw_acce_x=(int16_t)((data_rd[0]<<8)+(data_rd[1]));raw_acce_value->raw_acce_y=(int16_t)((data_rd[2]<<8)+(data_rd[3]));raw_acce_value->raw_acce_z=(int16_t)((data_rd[4]<<8)+(data_rd[5]));returnret;}esp_err_tmpu6050_get_raw_gyro(mpu6050_handle_tsensor,mpu6050_raw_gyro_value_t*constraw_gyro_value){uint8_tdata_rd[6];esp_err_tret=mpu6050_read(sensor,MPU6050_GYRO_XOUT_H,data_rd,sizeof(data_rd));raw_gyro_value->raw_gyro_x=(int16_t)((data_rd[0]<<8)+(data_rd[1]));raw_gyro_value->raw_gyro_y=(int16_t)((data_rd[2]<<8)+(data_rd[3]));raw_gyro_value->raw_gyro_z=(int16_t)((data_rd[4]<<8)+(data_rd[5]));returnret;}esp_err_tmpu6050_get_acce(mpu6050_handle_tsensor,mpu6050_acce_value_t*constacce_value){esp_err_tret;floatacce_sensitivity;mpu6050_raw_acce_value_traw_acce;ret=mpu6050_get_acce_sensitivity(sensor,&acce_sensitivity);if(ret!=ESP_OK){returnret;}ret=mpu6050_get_raw_acce(sensor,&raw_acce);if(ret!=ESP_OK){returnret;}acce_value->acce_x=raw_acce.raw_acce_x/acce_sensitivity;acce_value->acce_y=raw_acce.raw_acce_y/acce_sensitivity;acce_value->acce_z=raw_acce.raw_acce_z/acce_sensitivity;returnESP_OK;}esp_err_tmpu6050_get_gyro(mpu6050_handle_tsensor,mpu6050_gyro_value_t*constgyro_value){esp_err_tret;floatgyro_sensitivity;mpu6050_raw_gyro_value_traw_gyro;ret=mpu6050_get_gyro_sensitivity(sensor,&gyro_sensitivity);if(ret!=ESP_OK){returnret;}ret=mpu6050_get_raw_gyro(sensor,&raw_gyro);if(ret!=ESP_OK){returnret;}gyro_value->gyro_x=raw_gyro.raw_gyro_x/gyro_sensitivity;gyro_value->gyro_y=raw_gyro.raw_gyro_y/gyro_sensitivity;gyro_value->gyro_z=raw_gyro.raw_gyro_z/gyro_sensitivity;returnESP_OK;}esp_err_tmpu6050_get_temp(mpu6050_handle_tsensor,mpu6050_temp_value_t*consttemp_value){uint8_tdata_rd[2];esp_err_tret=mpu6050_read(sensor,MPU6050_TEMP_XOUT_H,data_rd,sizeof(data_rd));temp_value->temp=(int16_t)((data_rd[0]<<8)|(data_rd[1]))/340.00+36.53;returnret;}esp_err_tmpu6050_complimentory_filter(mpu6050_handle_tsensor,constmpu6050_acce_value_t*constacce_value,constmpu6050_gyro_value_t*constgyro_value,complimentary_angle_t*constcomplimentary_angle){floatacce_angle[2];floatgyro_angle[2];floatgyro_rate[2];mpu6050_dev_t*sens=(mpu6050_dev_t*)sensor;sens->counter++;if(sens->counter==1){acce_angle[0]=(atan2(acce_value->acce_y,acce_value->acce_z)*RAD_TO_DEG);acce_angle[1]=(atan2(acce_value->acce_x,acce_value->acce_z)*RAD_TO_DEG);complimentary_angle->roll=acce_angle[0];complimentary_angle->pitch=acce_angle[1];gettimeofday(sens->timer,NULL);returnESP_OK;}structtimevalnow,dt_t;gettimeofday(&now,NULL);timersub(&now,sens->timer,&dt_t);sens->dt=(float)(dt_t.tv_sec)+(float)dt_t.tv_usec/1000000;gettimeofday(sens->timer,NULL);acce_angle[0]=(atan2(acce_value->acce_y,acce_value->acce_z)*RAD_TO_DEG);acce_angle[1]=(atan2(acce_value->acce_x,acce_value->acce_z)*RAD_TO_DEG);gyro_rate[0]=gyro_value->gyro_x;gyro_rate[1]=gyro_value->gyro_y;gyro_angle[0]=gyro_rate[0]*sens->dt;gyro_angle[1]=gyro_rate[1]*sens->dt;complimentary_angle->roll=(ALPHA*(complimentary_angle->roll+gyro_angle[0]))+((1-ALPHA)*acce_angle[0]);complimentary_angle->pitch=(ALPHA*(complimentary_angle->pitch+gyro_angle[1]))+((1-ALPHA)*acce_angle[1]);returnESP_OK;}/** * @brief i2c master initialization * @note Must do i2c_bus_init() before calling this function, which is provided by i2c.c */voidi2c_sensor_mpu6050_init(void){esp_err_tret;mpu6050=mpu6050_create(I2C_MASTER_NUM,MPU6050_I2C_ADDRESS);TEST_ASSERT_NOT_NULL_MESSAGE(mpu6050,"MPU6050 create returned NULL");ret=mpu6050_config(mpu6050,ACCE_FS_4G,GYRO_FS_500DPS);TEST_ASSERT_EQUAL(ESP_OK,ret);ret=mpu6050_wake_up(mpu6050);TEST_ASSERT_EQUAL(ESP_OK,ret);}