【手把手带你用pid算法控制电机】——(4)串级PID控制电机

2023-10-26

前言

1、该系列教程是基于stm32f103c8t6最小系统板的hal库开发,用最通俗易懂的方式手把手带你学会使用Pid算法的速度环、位置环以及速度位置串级pid。

2、出这一期Pid系列教程的想法是前段时间我参加了一个比赛,要用到串级Pid的功能,可是我发现网上的教程要么是零零散散的,没有集中一起讲解这三个功能的,要么就是写的内容不够简单直接,基础没那么好的同学学起来会很吃力。为了用最直观的步骤和最简单的代码带大家一起掌握使用pid控制电机的能力,我打算出一期完整的、通俗易懂的系列教程,同时也作为对我前段时间学习内容的总结。

3、Pid算法涉及到的内容很多,值得我们去深入地研究去发现它的美,pid算法的学习不仅仅是理论上的理解,要去实践,实现把速度、位置控制好的功能。移植好pid算法以后的调参也是一门学问呢!哈哈哈,所以掌握pid并不是一件容易的事情,不过我已经把串级pid实现了,请相信我会带着大家一起从头到尾一点一点实现!

1、本章节要实现的功能是使用串级pid控制电机,最终达到的效果是:电机可以以指定的速度转动到特定的位置,要求速度、位置准确,抗干扰能力强(转到目的角度以后,用手很难转动电机,并且电机在转动时以一定阻力难阻止电机运动,电机在受到干扰后会及时补充速度)。

2、大家会学会:使用串级PID(位置环与速度环)控制电机;注意:位置环与速度环都要先单独调好以后再合并为串级pid,一般来说合成后的串级pid是能用的,如果不准,也可以再调一下参数,先调速度环,将位置环注释掉,调好速度环后,取笑位置环注释,再继续调位置环,调到自己需要的效果。

3、学习本章前建议大家先学习完:【手把手带你用pid算法控制电机】——(1)编码器电机和0.96寸OLED显示屏的使用

【手把手带你用pid算法控制电机】——(2)PID速度环

【手把手带你用pid算法控制电机】——(3)PID位置环

在掌握使用速度环与位置环以后,串级PID控制就很简单了。

1. 串级PID原理

速度位置串级PID顾名思义,是速度环与位置环两个环串联一起使用;内环是速度环,外环是位置环,位置pid的输出作为速度pid的输入,把位置pid的输出作为速度pid的目标值去控制。

控制框图如下所示:

 2. 代码

本教程的代码是基于【手把手带你用pid算法控制电机】——(2)PID速度环

不需要再写代码,只需要在那篇文章的代码中改一些地方就行。

改成串级PID的代码。

/* USER CODE BEGIN PV */
int16_t  speed,encoder_counter;
 
float Position_KP=0.18,Position_KI=0.002,Position_KD=0; //位置PID系数
float Velocity_KP=4.5,Velocity_KI=0.1,Velocity_KD=0; //速度PID系数
int Encoder,Target_Velocity=30;
int Moto,Position_Moto;//电机PWM变量
int limit_a;
int Position,Target_Position=850; //位置和目标位置自己设定
 
 
/* USER CODE END PV */
/* USER CODE BEGIN 0 */
 
/**
 * @function: void GET_NUM(void)
 * @description: 使用STM32编码器模式,读取编码器产生的脉冲值
 * @param {*} 
 * @return {*}
 */
void GET_NUM(void)
{
	encoder_counter=(short) __HAL_TIM_GET_COUNTER(&htim3);
	__HAL_TIM_SET_COUNTER(&htim3,0);//将编码器模式的定时器清零
}
 
/**
 * @function:void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 * @description: 定时器中断回调函数,0.1S中断一次并计算转速,将电机转速以及编码器产生的脉冲数显示在OLED屏上
 * @param {TIM_HandleTypeDef *htim} 
 * @return {*}
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim==&htim1)
	{
		GET_NUM();//得到所记录的脉冲数 
		Position+=encoder_counter;//脉冲数积累
		Position_Moto = Position_PID(Position,Target_Position);
		limit_a=Xianfu(Position_Moto,myabs(Target_Velocity));
		Moto = Incremental_PI(encoder_counter,limit_a);
		//Moto = Incremental_PI(encoder_counter,Target_Velocity);
		//Moto =Xianfu(Position_Moto,(这里填PWM满幅));
		Set_Pwm(Moto);
		
		 //speed=(float)encoder_counter/2040/0.1;//转速为n,r/s  脉冲数转化为速度
		 //OLED_Showdecimal(0,4,speed,2,2,12,0);//在特定位置显示2位整数+2位小数的电机转速
	}
}
 
/*串口重定向*/
 #ifdef __GNUC__
     #define PUTCHAR_PROTOTYPE int _io_putchar(int ch)
 #else
     #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
 #endif /* __GNUC__*/
 
 /******************************************************************
     *@brief  Retargets the C library printf  function to the USART.
     *@param  None
     *@retval None
 ******************************************************************/
 PUTCHAR_PROTOTYPE
 {
     HAL_UART_Transmit(&huart1, (uint8_t *)&ch,1,0xFFFF);
     return ch;
 }
 
 
/* USER CODE END 0 */
/* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
		printf("%d,%d\n",Position,Target_Position);    //输出编码器的值(实际值)和目标值到vofa软件
  }

显示实际位置与目标位置的图像,观察图线是不是以一定的斜率上升到一个值就不变化了;原理:位置的导数就是速度,所以位置图像的斜率就表示速度的大小;

斜率不变代表速度大小不变,即速度环效果可以;

脉冲值达到一定值以后不上升,表示位置环效果可以;

同时有这两个现象表示串级PID效果可以。

3. 调参

3.1 速度内环整定

(1)我们要先调整速度内环,保证有阶跃响应的稳定,快速,准确性。

(2)速度环要调到的效果:从速度0到收到一个控制目标,速度迅速达到20;从速度20收到一个控制目标,速度迅速到达0。

(3)±1的偏差为编码器的最小量级,PID控制器是作用于偏差,有偏差后它才能生效,所以属于正常控制范围。

3.2 整合位置外环

因为位置环的输出要作为速度环的速度目标值,所以注意整定位置环参数时,位置环的输出要接近速度环的量级,这样理解:速度环的量级指的就是速度环的目标值指的是每个中断周期内捕捉到的脉冲数值,例如每10ms内电机的脉冲数值是比较小的,所以速度目标值也比较小,所以位置环的参数就也可能比较小。

总之:要根据速度环的需求去整定位置环的参数,并且还要对位置环限幅才能达到应该好的效果。

串级pid效果如下:横坐标为时间,纵坐标有两个,分别是位置目标值和位置实际值,其中实际速度值可以通过实际位置曲线的斜率得以体现,斜率恒定,表示实际速度值恒定。

4. 遇到的问题

理论上,把速度环和位置环单独调好以后,整合起来,串级pid的效果是比较好的,如果内外环参数单独调的时候都是正常的,整合以后电机乱转(没有按理想情况转),十有八九你现在是已经磨了很长一段时间了,你脑袋已经昏了,绝对是你代码写错了,注意位置环和速度环控制函数里输入的参量不要搞错,我就是凌晨3点还在调,没调好,第二天发现是自己函数的输入参量搞错了。

我是速度环的两个参量填错了,导致电机总是乱转,搞得我莫名其妙的。

所以大家移植代码的时候一定要从上到下仔细分析一下代码逻辑,理清楚,避免出现低级错误。 

5. 结语

说到最后,想到前言我说了是我本人最近做了一个用到了串级pid的项目,到了本系列教程的最后一节了,也该告诉大家我做的是项目具体是什么。我做了一个智能化电梯,用n20电机正反转模拟电梯的上下行,电机以恒定速度正反转不同圈数代表电梯上升或下降到不同的楼层,并且可以反复持续工作,电机运行都正常,每次误差也不会太大。通过这个项目对速度环,位置环,串级Pid都有了初步的认识。

后面在很多地方都再次用到了速度环、位置环、串级控制等操作,每次实操,我都感觉自己对pid控制算法有新的理解和体会,所以我觉得想一次就把一个知识完全掌握,或者说是掌握的较为全面,是不太可能的;初步学了一个知识以后,一定要在其他项目里多实操,以达到对知识更全面更可靠的理解,而不是只停留在会用,只是对知识一知半解。要知道,往往上爬,真正的高手过招,那都拼的是基础知识和能力!与众君共勉!

行文至此,此系列教程已经初步完稿,后续有新的体会与理解以后会不定时对文章进行改进,但是会确保每次发布的文章都是没有错误的,大家放心学习!

码字不易,希望喜欢的小伙伴别忘了点赞+收藏+关注,你们的肯定就是我创作的动力。

欢迎大家积极交流,本文未经允许谢绝转载!!!

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

【手把手带你用pid算法控制电机】——(4)串级PID控制电机 的相关文章

  • 【C++】继承详解

    文章目录 继承的概念 基类和派生类对象赋值转换 继承作用域 派生类的默认成员函数 继承和友元 静态成员变量的继承 菱形继承和虚拟继承 继承和组合 继承的概念 继承机制是面向对象程序设计使代码复用的重要手段 通过继承机制 可以利用已有的数据类
  • C++基础4:构造函数、析构函数、拷贝析构函数、静态成员函数

    构造函数 1 1构造函数 一个特殊的函数与类型名相同 没有返回值类型 保证创建一个对象时 自动调用一次 一个类可以有多个构造函数 作用 初始化对象 如果一个类不提供构造函数 则系统自动提供一个无参构造函数 但一旦提供构造函数 则系统的无参构
  • Head-Free Lightweight Semantic Segmentation with Linear Transformer 新颖的分割网络

    现有的语义分割网络基本都是编码解码结构 新的语义分割网络主要都是在解码阶段添加新的不同模块 提高解码阶段特征处理能力 从而实现语义分割 而这篇文章主要是去除了解码阶段 把工作重心放在了编码阶段 它采用并行架构来利用原型表示作为特定的可学习的
  • Linux Mii management/mdio子系统分析之六 fixed-mii_bus分析(mac2mac分析)

    前面几章我们介绍了MDIO模块的大部分内容 针对mii bus mdio bus phy device phy driver相关的注册 注销均进行了介绍 基本上把mdio模块的内容介绍完了 而本篇介绍的内容 主要是针对虚拟mii bus实现
  • python类基本语法笔记

    语言是工具 一段时间不用就会忘掉语法 静态方法和类方法 什么时候会用到这样的方法呢 类方法是针对类存在的 可以用类直接调用 主要用到的两个函数是staticmethod 和classmethod 简洁的用法是用Python的修饰器 需要注意
  • Vue总结第二天~自定义子组件、父子组件通信、插槽

    目录 一 组件 组件目录 1 注册组件 全局组件 局部组件和demo template模块 1 注册组件的基本步骤 2 全局组件demo 3 局部组件demo 4 template模块的简化 模板的分离写法 即将其内容封装到 templat
  • Matplotlib

    1 折线图 import matplotlib pyplot as plt import numpy as np x np linspace 1 1 50 1到1 有五十个点 y 2 x 1 plt figure num 1 figsize

随机推荐

  • 【计算机网络】第一章:计算机网络概述

    文章目录 1 1 计算机网络在信息时代的作用 1 2 因特网概述 1 3 三种交换方式 1 4 计算机网络的定义和分类 1 5 计算机网络的性能指标 1 6 计算机网络体系结构 计算机网络体系结构 计算机网络体系结构分层的必要性 计算机网络
  • 从gitHub当中更新项目synchronize Update fetch pull 项目的区别。

    11 从gitHub更新项目 方法一 右击你的项目 team synchronize workspace 这样他就会去gitHub那fetch回最新的版本 之后像svn一样 切换到team synchronize视图 注意服务器如有更新 而
  • Vue之插件的介绍

    简介 主要介绍Vue插件的概念 定义和使用 Vue的插件主要是用于增强功能 可以把它看作是一个工具库 可以提供很多强大的功能 比如一些强大的自定义指令 一些强大的工具方法 过滤器等 我们可以编写或者直接引入别人写的插件 就能获得强大的功能
  • odoo 权限

    创建安全组并分配用户 Odoo中的访问权限通过安全组成进行配置 给组指定权限 然后为组分配用户 每个功能区都有中枢应用所提供的基础安全组 在插件继承已有应用时 它们应对相应的组添加权限 参见本章稍后的向模型添加访问权限一节 在插件模块添中添
  • HDOJ 1058 Humble Numbers解题报告【DP】

    Humble Numbers 题目详见http acm hdu edu cn showproblem php pid 1058 开始拿到这个题目的时候还纠结了半天 英语很差的话这个题是不可能AC的 而我就是其中之一 Humber Numbe
  • spring-boot-maven-plugin报错的修改与版本号查看

    我报错的原因是因为没加版本号 版本号是多少 可以下个everything搜spring boot maven plugin 前面的号码就是版本号了
  • [转]出租车轨迹处理(二):时空分析

    接下来就要进行一些简单的分析了 今天的目标是如何对某一感兴趣区域进行出租车数据的时空分析 一 轨迹数据预处理 这一步在上一篇文章中已经有了介绍 步骤无非就是 1 使用pandas读取数据 import pandas as pd import
  • Matlab实现粒子群算法(附上完整仿真代码)

    粒子群算法 Particle Swarm Optimization PSO 是一种群体智能算法 通过模拟自然界中鸟群 鱼群等生物群体的行为 来解决优化问题 在PSO算法中 每个个体被称为粒子 每个粒子的位置表示解空间中的一个解 每个粒子的速
  • AVL树的插入与删除(均为递归实现)

    一 引言 AVL树是带有平衡条件的二叉查找树 这个平衡条件必须要容易保持 而且它必须保证树的深度是O logN 一颗AVL树是其每个节点的左子树和右子树的高度最多差一的二叉查找树 主要介绍插入算法和删除算法 二 AVL树的结点定义 type
  • (二)RK3566 Android11固件烧录

    上一篇 一 RK3566 Android11 系统编译 文章目录 1 固件包烧录步骤 2 固件统一打包 3 固件升级 1 固件包烧录步骤 烧录工具位置 RKTools windows AndroidTool AndroidTool Rele
  • e17 enlightenment 介绍及配置

    为什么要有一个窗口管理器 为什么一定要有一个桌面背景 甚至是标题栏 或是如果把一个应用程序如firefox当成桌面背景行不行 桌面能不能再快一点 我不想把资源浪费在那些用不到的地方 Linux那么多虚拟桌面 为什么我不能在一个桌面全屏运行一
  • python django框架ORM模型及ORM操作数据库 笔记

    ORM模型介绍 随着项目的越来越大 采用写原生SQL的方式在代码中会出现大量的SQL语句 那么问题就出现了 1 SQL语句重复利用率不高 越复杂的SQL语句条件越多 代码越长 会出现很多相近的SQL语句 2 很多SQL语句是在业务逻辑中拼出
  • 深度卷积神经网络中的patch

    转载 https blog csdn net wills798 article details 97974617 在阅读基于深度卷积神经网络的图像识别 分类或检测的文献时经常看到 patch 不是很能理解 后来就总结了一下 通过阅读 pat
  • 【深度学习——点云】PointNet++

    这篇文章发表于NIPS 2017 是在PointNet基础上的工作 论文地址 PointNet Deep Hierarchical Feature Learning on Point Sets in a Metric Space 1 Mot
  • vue实现简单轮播图

    实现思路 将vue的框架封装在function中 在界面刷新时调用 将要轮播的图片存放在data中 还有下面的列表也分别保存在data中的一个数组中 然后每隔一段时间进行自动切换的函数写在methods中 注意函数要调用的话 就要在生命周期
  • 如何fork GitHub上的官方仓库

    在GitHub中 fork表示复制一个仓库到你自己的GitHub账号下 创建一个独立的副本 通过fork操作 你可以在自己的副本中进行修改 改进和实验 而不会影响到原始仓库或其他人的工作 当你fork一个仓库时 GitHub将会为你创建一个
  • Spring Boot(二)SpringBoot是如何启动Spring容器源码

    SpringApplication run 调用SpringApplication run启动springboot应用 1 SpringApplication run Application class args 2 使用自定义Spring
  • 使用R语言绘制散点图

    文章目录 学习目标 学习内容 内容小结 学习目标 我们所采用的学习内容来自B站的Lizongzhang老师的R语言的学习分享 今天学习的主要内容是关于 绘制散点图 学习内容 下面是学习的主要内容 直接上代码 大家可以查看视频 我也的注释也比
  • 求阶乘的三种方法

    方法一 递归算法 include
  • 【手把手带你用pid算法控制电机】——(4)串级PID控制电机

    前言 1 该系列教程是基于stm32f103c8t6最小系统板的hal库开发 用最通俗易懂的方式手把手带你学会使用Pid算法的速度环 位置环以及速度位置串级pid 2 出这一期Pid系列教程的想法是前段时间我参加了一个比赛 要用到串级Pid