基于ESP32四旋翼无人机如何根据PID算法进行电机的PWM duty补偿

news/2024/11/23 23:52:30/

1.计算模型

电机位置和补偿输出的关系,需要求解的是C1,C2,C3,C4的电机输出补偿值。分别对应M1,M2,M3,M4四个电机。
在这里插入图片描述
在这里插入图片描述

2.推导过程(可以跳过不看,直接到第三步)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 四个电机的PID补偿输出的算法如下:

C1到C4的值是根据上面的公式C=A(−1)P,计算出来的。P是pc,rc,yc三个姿态角的力矩。A是转移矩阵。C1到C4是四个电机的PWM duty补偿值。
void dandelion_pid_update(const dandelion_pose_projection* pose,const dandelion_pose_projection* poseLast,const dandelion_pose_projection* target)
{
/* Pitch */
PIDController_PitchRoll2Pwm_Update(&mDandelion.pid.pitch_pose, target->pitch , pose->pitch);

/* Roll */
PIDController_PitchRoll2Pwm_Update(&mDandelion.pid.roll_pose, target->roll, pose->roll);/* Yaw */
PIDController_YawRate2Pwm_Update(&mDandelion.pid.yaw_rate, target->yawGyro, pose->yawGyro);mDandelion.pid.compensate[0] = 0;
mDandelion.pid.compensate[1] = 0;
mDandelion.pid.compensate[2] = 0;
mDandelion.pid.compensate[3] = 0;// pitch
mDandelion.pid.compensate[0] += mDandelion.pid.pitch_pose.out * mDandelion.pid.config_f[DANDELION_PID_CFG_PITCH_F] / 2.0f;
mDandelion.pid.compensate[1] -= mDandelion.pid.pitch_pose.out * mDandelion.pid.config_f[DANDELION_PID_CFG_PITCH_F] / 2.0f;
mDandelion.pid.compensate[2] -= mDandelion.pid.pitch_pose.out * mDandelion.pid.config_f[DANDELION_PID_CFG_PITCH_F] / 2.0f;
mDandelion.pid.compensate[3] += mDandelion.pid.pitch_pose.out * mDandelion.pid.config_f[DANDELION_PID_CFG_PITCH_F] / 2.0f;// roll
mDandelion.pid.compensate[0] += mDandelion.pid.roll_pose.out * mDandelion.pid.config_f[DANDELION_PID_CFG_ROLL_F] / 2.0f;
mDandelion.pid.compensate[1] += mDandelion.pid.roll_pose.out * mDandelion.pid.config_f[DANDELION_PID_CFG_ROLL_F] / 2.0f;
mDandelion.pid.compensate[2] -= mDandelion.pid.roll_pose.out * mDandelion.pid.config_f[DANDELION_PID_CFG_ROLL_F] / 2.0f;
mDandelion.pid.compensate[3] -= mDandelion.pid.roll_pose.out * mDandelion.pid.config_f[DANDELION_PID_CFG_ROLL_F] / 2.0f;// rotate
mDandelion.pid.compensate[0] -= mDandelion.pid.yaw_rate.out * mDandelion.pid.config_f[DANDELION_PID_CFG_YAW_F] / 2.0f;
mDandelion.pid.compensate[1] += mDandelion.pid.yaw_rate.out * mDandelion.pid.config_f[DANDELION_PID_CFG_YAW_F] / 2.0f;
mDandelion.pid.compensate[2] -= mDandelion.pid.yaw_rate.out * mDandelion.pid.config_f[DANDELION_PID_CFG_YAW_F] / 2.0f;
mDandelion.pid.compensate[3] += mDandelion.pid.yaw_rate.out * mDandelion.pid.config_f[DANDELION_PID_CFG_YAW_F] / 2.0f;memcpy(&mDandelion.dmp.poseLast, pose, sizeof(dandelion_pose_projection));

}

4.电机PWM duty输出

最终电机PWM duty输出需要加入遥控器传递过来的参数油门参数。
在dandelion_pwm_update函数中将遥控器的油门大小和PID duty结果相加,计算出最终的电机控制的PWM duty参数。它来自于下面两参数:
gCompensate和mDandelion.pid.compensate。将两个参数相加得到pid.output(也就是PWM duty)

void dandelion_pwm_update(float gCompensate)
{

/* Compensate Pose */float fpCompensate = 1.0; // limit compensate output 
if(1)
{float cmax = mDandelion.pid.compensate[0];float cmin = mDandelion.pid.compensate[0];for(int j=0;j<4;j++){if(mDandelion.pid.compensate[j]>cmax) cmax = mDandelion.pid.compensate[j];if(mDandelion.pid.compensate[j]<cmin) cmin = mDandelion.pid.compensate[j];}if(cmax*cmin<0) {// Max Value Limitif((gCompensate+cmax)>0.95){fpCompensate = fpCompensate * (0.95-gCompensate)/(cmax);}// Min Value Limitif((gCompensate+cmin*fpCompensate)<0.05){fpCompensate = fpCompensate * (0.05-gCompensate)/(cmin);}}
}/* ---------------------------------------------------------------- *//* Update Register */mDandelion.pid.output[0] = gCompensate + mDandelion.pid.compensate[0] * fpCompensate;
mDandelion.pid.output[1] = gCompensate + mDandelion.pid.compensate[1] * fpCompensate;
mDandelion.pid.output[2] = gCompensate + mDandelion.pid.compensate[2] * fpCompensate;
mDandelion.pid.output[3] = gCompensate + mDandelion.pid.compensate[3] * fpCompensate;bsp_motor_drive(mDandelion.pid.output);
//bsp_motor_drive(NULL);
return 0;

}
其中bsp_motor_drive(mDandelion.pid.output),该函数最终调用PWM控制函数,调整PWM波形控制电机转速。
void bsp_motor_drive(float* duty) //控制四个马达功率
{
if(duty==NULL)
{
// stop all
for(int i=0;i<4;i++)
{
ledc_set_duty(_pwm_ch_config[i].speed_mode,_pwm_ch_config[i].channel,0); //设置占空比
ledc_update_duty(_pwm_ch_config[i].speed_mode, _pwm_ch_config[i].channel);//使新配置生效

}
}
else
{
for(int i=0;i<4;i++)
{
if(duty[i]>=0&&duty[i]<=1)
{
ledc_set_duty(_pwm_ch_config[i].speed_mode,_pwm_ch_config[i].channel,duty[i] * BSP_MOTOR_OVERFLOW);
ledc_update_duty(_pwm_ch_config[i].speed_mode, _pwm_ch_config[i].channel);
}
else if(duty[i]>=1)
{
ledc_set_duty(_pwm_ch_config[i].speed_mode,_pwm_ch_config[i].channel,BSP_MOTOR_OVERFLOW);
ledc_update_duty(_pwm_ch_config[i].speed_mode, _pwm_ch_config[i].channel);
}
else
{
ledc_set_duty(_pwm_ch_config[i].speed_mode,_pwm_ch_config[i].channel,0);
ledc_update_duty(_pwm_ch_config[i].speed_mode, _pwm_ch_config[i].channel);
}

}
}
}


http://www.ppmy.cn/news/872432.html

相关文章

伺服增益参数简述及其调整

参考文献 [1] 颜嘉男. 伺服电机应用技术[M]. 第1版. 北京:科学出版社, 2010. [2] 台达. ASDA-B2伺服手册[EB/OL]. [3] 陈国强, Putra A S. 工业自动化中的驱动与控制[M]. 第1版. 北京:机械工业出版社, 2016 :86-105. 相关内容回顾&#xff1a; 伺服电机基本概念解析&#xff1…

ORACLE 表空间不足与用户配额(限额)不足的问题解决

表空间不足与用户配额不足是两种不同的概念。表空间的大小是指实际的用户表空间的大小&#xff0c;而配额大小指的是用户指定使用表空间的的大小。两者的解决方式亦不相同。(看看这里)配额问题的解决&#xff1a;alter user skate quota 2g on tablespace_name;视图&#xff1a…

MaxCompute-ODPS SQL报错:Quota not enough,配额组资源不足

MaxCompute-ODPS SQL报错&#xff1a;Quota not enough&#xff0c;配额组资源不足 ODPS SQL报错&#xff1a;ODPS-0010000:System internal error - fuxi job failed, caused by: |Quota not enough 问题原因&#xff1a; 配额组的资源不足。 由于我执行的是insert ... s…

摇臂升降电机的c语言程序,摇臂钻床摇臂的升降是如何控制的?

摇臂钻床摇臂的升降是如何控制的? 发布时间&#xff1a;2019-12-19 摇臂升降运动的运动过程为&#xff1a;摇臂放松——摇臂升降——摇臂夹紧。(夹紧必须在摇臂停止时进行) 摇臂上升与下降控制的工作过程如下&#xff1a; 按下上升或者下降控制按钮&#xff0c;断电延时继电器…

MMA7361三轴加速度模块使用注意的问题

MMA7361这个模块很多种类&#xff0c;看似长得都一样&#xff0c;用起来还是有区别的。对比三种用过的MMA7361模块 1.龙丘&#xff08;龙邱&#xff09;科技的MMA7361 各轴的信号在不运动或不被重力作用的作用的状态下&#xff08;0g&#xff09;&#xff0c;其输出为1.65V。如…

Android 四大布局使用详解

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、LinearLayout 线性布局二、RelativeLayout 关系布局三、FrameLayout 帧布局四、TableLayout 表格布局 在Android 中&#xff0c;有界面存在的地方就…

伺服驱动器--增益调整

增益调整 1.1 惯量辨识1.2 刚性等级1.2.1 刚性等级设定1.2.2微调参数 1.3 指令滤波1.4 机械特性曲线1.5 项目实战&#xff1a;3.1、刚性等级15 的情况下分析曲线3.2、刚性等级28 的情况下分析曲线3.3、刚性等级22 的情况下分析曲线**补充说明&#xff1a;**采样频率采样周期换算…

倍福PLC获取伺服驱动器扭矩值获取电流值

双击某个驱动器&#xff08;以松下伺服驱动器为例&#xff09;&#xff0c;在Process Data中&#xff0c;注意默认显示了PDO mapping1的数据&#xff08;Error code&#xff0c; status word等&#xff09; 注意左侧&#xff0c;2和3分别表示了与驱动器的所有数据输入和输出&a…