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

2023-05-16

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 Limit
		if((gCompensate+cmax)>0.95)
		{
			fpCompensate = fpCompensate * (0.95-gCompensate)/(cmax);
		}

		// Min Value Limit
		if((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);
}

}
}
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • HNU软件能力实训2-9. 字符串压缩

    写在前面 你好 xff01 欢迎来到我的博客 xff0c 希望我的思路能够帮到你 xff01 问题描述 给定一个由n个小写字母组成的字符串s xff0c 需要使用最少数量的钱币来压缩它 压缩该字符串 xff0c 必须将s表示为多个相互连接的
  • HNU软件能力实训2-21. 新型冠状病毒(COVID19)传播

    写在前面 你好 xff01 欢迎来到我的博客 xff0c 希望我的思路能够帮到你 xff01 问题描述 防控新冠病毒 xff0c 必须时刻引起大家的足够重视 xff0c 特别是人员集中活动场所 xff0c 保持好社交距离 然而 xff0c
  • HNU软件能力实训3-8. ab串

    写在前面 你好 xff01 欢迎来到我的博客 xff0c 希望我的思路能够帮到你 xff01 问题描述 给定一个由字符 a 和字符 b 组成的字符串 xff0c 可以删除若干字符 xff0c 使得剩下来的字符串满足前后段为a xff0c 中
  • HNU软件能力实训3-9. 占座位

    写在前面 你好 xff01 欢迎来到我的博客 xff0c 希望我的思路能够帮到你 xff01 问题描述 一个人可以去占多个座位 xff0c 而且一定是要连续的座位 xff0c 如果占不到他所要求的这么多座位 xff0c 那么他就一个座位也不
  • ROS编程入门(C++ 及 思路)

    使用Autolabor官方入门教程 xff0c 笔记内容为注意事项 首页 Autolabor开源ROS机器人底盘 官方网站 一 ROS通信机制的解释 例如在生活中 xff0c 我们在家里有一个放零食的箱子 xff0c 而操作服务器就是这个箱
  • HNU软件能力实训4-5. 小希的数表

    写在前面 你好 xff01 欢迎来到我的博客 xff0c 希望我的思路能够帮到你 xff01 问题描述 Gardon 昨天给小希布置了一道作业 xff0c 即根据一张由不超过 5000 的 N 3 lt 61 N lt 61 100 个正整
  • HNU软件能力实训4-12. 疫情期间

    写在前面 你好 xff01 欢迎来到我的博客 xff0c 希望我的思路能够帮到你 xff01 问题描述 正值新冠疫情期间 xff0c 阿迪没法返回学校学习 xff0c 他希望通过参加一些比赛来提高一下编程技能 xff0c 同时做做运动 他收
  • HNU软件能力实训4-14. 组个最小数

    写在前面 你好 xff01 欢迎来到我的博客 xff0c 希望我的思路能够帮到你 xff01 问题描述 给定数字0 9各若干个 你可以以任意顺序排列这些数字 xff0c 但必须全部使用 目标是使得最后得到的数尽可能小 xff08 注意0不能
  • CMakeLists.txt的编写

    首先是编写好的CMakeLists txt文件 span class token function cmake minimum required span span class token punctuation span VERSION
  • 第一课 神经网络与深度学习 第二周 神经网络基础(已完结(虽然有坑))

    视频地址 二分分类 怎么说 xff0c 第一段话就颠覆了我的想象 xff0c 遍历m个样本不需要用for循环 这里是介绍了图片的预处理 xff0c 将图片切分为rgb三个颜色空间 xff08 这个我熟 xff09 xff0c 然后将所有的分
  • leetcode 1200. 最小绝对差

    1200 最小绝对差 span class token keyword class span span class token class name Solution span span class token punctuation sp
  • 648. 单词替换

    648 单词替换 span class token keyword class span span class token class name Solution span span class token punctuation span
  • 1217. 玩筹码

    1217 玩筹码 span class token comment 由题目描述可知 xff0c 移动1步成本为1 移动2步没有成本 那么我们可以不耗费成本的将不同奇数位置的筹码移动到某一个奇数位置 此时的成本为0 同理 也可以将不同偶数位置
  • dronekit控制实体无人机起飞降落

    摘要 xff1a 本文基于dronekit在实体无人机上实现最基本的起飞和降落 xff0c 测试了这一过程中速度的变化以及起落位置的偏移 实体实验环境 树莓派4BUbuntu mate 20 04飞控Pixhawk 2 4 8飞控固件APM
  • Gazebo中针对Gazebo软件或生成模型出现process has died问题的参考方案

    在基于ROS机器人仿真时 xff0c 打开Gazebo经常出现一些问题 xff0c 比如Gazebo窗口打开了 xff0c 终端却显示gazebo进程已死 本文记录了一次遇到的类似问题 xff0c 并给出了在部分情况下能够适用的参考方案 问
  • ROS 入门 (launch文件)

    本章主要内容介绍在ROS中上述问题的解决策略 见本章目录 xff0c 预期达成学习目标也与上述问题对应 xff1a 掌握元功能包使用语法 xff1b 掌握launch文件的使用语法 xff1b 理解什么是ROS工作空间覆盖 xff0c 以及
  • 报错:Multiple annotations found at this line: - user cannot be resolved

    问题 xff1a Multiple annotations found at this line user cannot be resolved 第一步 xff1a 右键找到Build Path 点击Configure Build Path
  • Nuxt 生命周期

    目录 服务端生命周期1 nuxtServerInit nuxt中第一个运行的生命周期 2 RouteMiddleware 第二个 xff1a 中间键 xff0c 路由导航守卫 4 validate 是用来校验url参数符不符合5 async
  • 使用ESP-idf-4.23一次编译通过ESP32-Drone四旋翼无人机代码

    为了编译ESP32 Drone四旋翼无人机代码 xff0c 试用了几种编译环境 xff0c 折腾一个上午 xff0c 最后使用ESP idf 4 23一次性编译通过 记录一下过程 1 获取ESP32 Drone四旋翼无人机项目源代码 xff
  • 基于ESP32四旋翼无人机如何根据PID算法进行电机的PWM duty补偿

    1 计算模型 电机位置和补偿输出的关系 xff0c 需要求解的是C1 C2 C3 C4的电机输出补偿值 分别对应M1 M2 M3 M4四个电机 2 推导过程 xff08 可以跳过不看 xff0c 直接到第三步 xff09 3 四个电机的PI