传感器的基本功能便是把外界不同的物理量,化学量和生物量变换容易处理的电信号或者数字信号并输出。 而由于实际上传感器中在放大,滤波,采样等过程不可避免地引入噪声,其中一个重要的噪声便是热噪声。热噪声是指由于电子热运动产生的随机电信号,热噪声导致 IMU 数据偏移是 IMU 会产生零漂现象的重要原因之一。

零漂现象是指当物理量输入为零, 传感器测量的输出量不为零的现象。即 IMU 没有任何运动,陀螺仪和加速度计也会读取到一定大小的数据,并将其当作是由 IMU 运动产生的。因此需要在 IMU 上电时首先测量出零漂的大小,将 IMU 测量到的值与零漂值相减,从而减少零漂的影响。这种方法的前提是 IMU 的零漂值保持固定,否则依然会引入误差。

热噪声的幅度和温度成正相关,所以零漂值受到温度的影响,因此需要控制 IMU 的温度保持一个恒定的范围内,从而减少零漂带来的影响。

但是比较尴尬的是c板里只能做温度低于基准后做升温处理,如果温度过高,只能自行散热

关于PID的知识可以看我前面的文章,这里不在赘述。

然后想和大家说的是大疆写着篇程序是使用的是FreeRTOS系统下写的,如果没学确实不太能看懂,也挺麻烦,所以我下面讲的就是把大疆的主要控制程序全部拆解出来,让大家即使不会FreeRTOS也能使用,如果想加上FreeRTOS也很简单自己移植就可以了

下面直接讲配置,CubeMX的配置和上一张的BMI088大差不差,要加一点东西

但是要开启定时器10PIM的通道1,切记要用PF6作为通道,

然后建立程序就行了,

然后打开文件

把这三个文件的所有文件都放打你自己的工程里去

打开你自己建立的CubeMX工程,找到Core并打开

.c 文件在Src  .h文件放到Inc中

然后在MdkARM中打开Keil

大致步骤像这样创立一个自己的文件夹,并在里面加入这些文件

有些同学可能找不到刚刚放进去的文件,由于添加文件只会默认打开本层目录但是我们的文件刚刚防,但是我们刚刚帮文件都放到了上层目录下的Core文件中,所以要回到上层都Core文件里找,

创建好之后打开

#include "imu_temp_control_task.c"

文件

把这些头文件复制到你自己的main.c中去

#include "imu_temp_control_task.h"
#include "BMI088driver.h"
#include "pid.h"
#include "bsp_imu_pwm.h"

然后复制或定义这些宏和变量

#define IMU_temp_PWM(pwm)  imu_pwm_set(pwm)                    //pwm����

#define TEMPERATURE_PID_KP 1600.0f //kp of temperature control PID 
#define TEMPERATURE_PID_KI 0.2f    //ki of temperature control PID 
#define TEMPERATURE_PID_KD 0.0f    //kd of temperature control PID 

#define TEMPERATURE_PID_MAX_OUT 4500.0f  //max out of temperature control PID 
#define TEMPERATURE_PID_MAX_IOUT 4400.0f //max iout of temperature control PID 

extern SPI_HandleTypeDef hspi1;

volatile uint8_t imu_start_flag = 0;

uint16_t tempPWM;


fp32 gyro[3], accel[3], temp;

//kp, ki,kd three params
const fp32 imu_temp_PID[3] = {TEMPERATURE_PID_KP, TEMPERATURE_PID_KI, TEMPERATURE_PID_KD};
//pid struct 
pid_type_def imu_temp_pid;

然后为了方便,打开main.h文件添加这些东西

#define CS1_ACCEL_GPIO_Port GPIOA
#define CS1_ACCEL_Pin  GPIO_PIN_4
#define CS1_GYRO_GPIO_Port GPIOB
#define CS1_GYRO_Pin GPIO_PIN_0
"struct_typedef.h"

本来前面没用到

"struct_typedef.h"头文件,但是改太多定义有点麻烦,现在感觉香

然后下一步,可能会由于CubeMX的版本不同情况不一样,有的版本在开启后会自动打开PWM但是有的不行,但是重复开启也没啥大问题

HAL_TIM_PWM_Start(&htim10,TIM_CHANNEL_1);

然后再复制这些

PID_init(&imu_temp_pid, PID_POSITION, imu_temp_PID, TEMPERATURE_PID_MAX_OUT, TEMPERATURE_PID_MAX_IOUT);

    
    while(BMI088_init())
    {
        ;
    }
    //set spi frequency
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
    
    if (HAL_SPI_Init(&hspi1) != HAL_OK)
    {
        Error_Handler();
    }

然后再

while(1)中添加这些


        BMI088_read(gyro, accel, &temp);

        PID_calc(&imu_temp_pid, temp, 40.0f);
        if (imu_temp_pid.out < 0.0f)
        {
            imu_temp_pid.out = 0.0f;
        }
        tempPWM = (uint16_t)imu_temp_pid.out;
        IMU_temp_PWM(tempPWM);

最后的最后,由于我们不用FreeRTOS,所以直接把

#include "imu_temp_control_task.c"

这个文件里面的内容全部注释掉就可了

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐