2.11 PID控制算法(三)----PID结果与实际值的关联

2023-11-14

1、讲解

1、AD采样,经过PID计算的值,怎么和PWM对应起来?
2、电机编码采样,经过PID计算的值,怎么与速度对应起来?

这个简单,PID控制原理就是输出一个控制量,然后检测反馈,由反馈得到的数据计算当前实际输出是多少,由这个实际输出和目标输出得到差值,最后由这个差值计算一个新的输出控制量。
举例(数据都是乱拟的,只为好计算):假设你的PWM是用来控制电机速度的,0%占空比对应的电机速度是0r,100%占空比对应的电机速度是100r。你目标电机速度是50r,那么调控步骤如下:

  1. 输出50%占空比的PWM
  2. AD采样并计算当前电机速度,假设计算得到的当前实际电机速度是40r,比目标速度50r差10r,这个10r送到PID计算得到一个增量结果,假设结果是5r
  3. 由5r计算对应的PWM占空比,即5%
  4. 更新PWM输出占空比,就是:50%+5%=55%,返回到第1步
    我个人理解,它们之间实际上就是一个比例关系。

2、举例1

我们来分析一个例子:步进电机PID速度闭环控制,它原理:预先设置好需要达到的速度,然后每隔一段时间读取编码器的值反馈当前速度,经过PID计算慢慢到达设定的速度。

#define FEEDBACK_CONST                        (SPR/ENCODER_SPR)   //编码器和步进电机驱动器的比值

typedef struct 
{
  __IO float SetPoint;    // 目标值  单位:mm/s
  __IO int LastError;     // 前一次误差    
  __IO int PrevError;     // 前两次误差
  __IO long SumError;     // 累计误差
  __IO double Proportion; // Kp系数
  __IO double Integral;   // Ki系数
  __IO double Derivative; // Kd系数
}PID_Typedef;

__IO PID_Typedef vPID;
 Vel_Target = (vPID.SetPoint*P_PERIOD);//每单位采样周期内的脉冲数(频率)
 
 
/**
  * 函数功能:增量式PID速度环计算
  * 输入参数:NextPoint     由编码器得到的速度值 
  *           TargetVal    目标值
  * 返 回 值:经过PID运算得到的增量值
  * 说    明:增量式 PID 速度环控制设计,计算得到的结果仍然是速度值
  */
float IncPIDCalc(__IO float NextPoint,__IO float TargetVal)    //临时变量,期望值 
{
  __IO float iError = 0,iIncpid = 0;                    //当前误差
  iError = TargetVal - NextPoint;                  // 增量计算
//  if((iError<0.5f)&&(iError>-0.5f))
//    iError = 0;                                    // |e| < 0.5,不做调整
  
  iIncpid=(vPID.Proportion * iError)               // E[k]项
              -(vPID.Integral * vPID.LastError)    // E[k-1]项
              +(vPID.Derivative * vPID.PrevError); // E[k-2]项
  
  vPID.PrevError=vPID.LastError;                   // 存储误差,用于下次计算
  vPID.LastError = iError;
  return(iIncpid);                                 // 返回增量值
}

/**
  * 函数功能: 系统滴答定时器中断回调函数
  * 输入参数: 无
  * 返 回 值: 无
  * 说    明: 每发生一次滴答定时器中断进入该回调函数一次
  */
void HAL_SYSTICK_Callback(void)
{
  __IO static uint16_t time_count = 0; // 时间计数,每1ms增加一(与滴答定时器频率有关)
  __IO static int32_t Last_CaptureNumber=0;       // 上一次捕获值
  // 每1ms自动增一
  time_count++; 
  if(Start_Flag == ENABLE)
  {
    if(time_count >= SAMPLING_PERIOD)// 20ms控制周期
    {
      time_count = 0;
      //获得编码器的脉冲值
      CaptureNumber = OverflowCount*65536 + __HAL_TIM_GET_COUNTER(&htimx_Encoder);
      //M法 测速度
      MSF = CaptureNumber - Last_CaptureNumber;
      Last_CaptureNumber = CaptureNumber;
      MSF = abs(MSF);
      
      Exp_Val += IncPIDCalc((float)MSF,Vel_Target);
	  //编码器输出期望值
      Exp_Val = abs(Exp_Val);
      /* 经过PID计算得到的结果是编码器的输出期望值的增量,
         需要转换为步进电机的控制量(频率值),这里乘上一个系数6400/2400
      */
      //乘上一个系数,6400/2400,将PID计算结果转换为步进电机的频率(速度)
      STEPMOTOR_Motion_Ctrl(MotorDir,Exp_Val*FEEDBACK_CONST);
    }
  }
}

/**
  * 函数功能: 步进电机运动控制
  * 输入参数: Dir:步进电机运动方向 0:反转 1正转
  *           Frequency:步进电机频率,0:停止
  * 返 回 值: void
  * 说    明: 无
  */
void STEPMOTOR_Motion_Ctrl(uint8_t Dir , float Frequency)
{
  uint16_t Step_Delay = 0;  //步进延时

  if(Frequency == 0)
    STEPMOTOR_OUTPUT_DISABLE();
  else
  {
    if(Dir==MOTOR_DIR_CCW)
    {
      STEPMOTOR_DIR_REVERSAL();
    }
    else STEPMOTOR_DIR_FORWARD();//方向控制
    /*
      步进电机速度由定时器输出脉冲频率(f)决定,
        f = c/F;c是计数器的计数值,F是定时器频率
      推导过程:(T是定时器输出脉冲周期)
        T=c*t => T=c*F => f = 1/T = F/c;
    
    */
    Step_Delay = (uint16_t)(FREQ_UINT/Frequency);
    
    Toggle_Pulse = Step_Delay>>1;//算出来的结果是周期,这里除以2,半周期翻转一次
  }
}

我们来分析一下它PID是怎么PID输出结果与速度量的关系:
从上面我可以知道,PID算法
输入参数:
1、MSF :单位采样周期内(20mS)编码器的值。
2、Vel_Target:每单位采样周期内编码器的脉冲数(频率);它由SetPoint(标 值 单位:mm/s),经过一定的计算而来。
输出参数:
1、编码器的输出期望值

步进电机的频率(速度)与PID结果的关系:Exp_Val*FEEDBACK_CONST ;从整个公式我们可发现,它们仅仅一个比例系数而已。

3、举例2

再举一例PWM控制温度

int iDataSigma
void PIDCalc(uint32_t Channel,int16_t set_temp,int16_t actualTemp)//温度放大100倍
{
	int  En,out_temp,controlOut; 

	En= set_temp-actualTemp;  //本次偏差
	if(abs(En) > 500)         //积分分离
	{
		index=0;
	}
	else
	{
		index=1;
		iDataSigma += En*iData; //历史偏差总和
	}
//	out_temp = Kp*En+index*Ki*iDataSigma; //P+I
	out_temp = Kp*En+index*Ki*iDataSigma+Kd(En-En_1);//P+I+D
	En_1 = En;
			 
	controlOut=_TIM3_ARR/500*out_temp;
	
	if (controlOut <= 0)
		bsp_SetPWM_TEMP_CCRx(Channel,0); //停止加热
	else
		bsp_SetPWM_TEMP_CCRx(Channel,abs(controlOut));//加热	
}

//占空比
 void bsp_SetPWM_TEMP_CCRx(uint32_t Channel,uint16_t duty)
{
	if(duty <= _TIM3_ARR)
	{
		__HAL_TIM_SET_COMPARE(&htim3, Channel, duty);		
	}
}

//STM32 PWM_1模式 初始化设置PWM周期
bsp_SetPWM_TEMP_ARR(_TIM3_ARR);		                 //周期 T=1000uS  _TIM3_ARR 

4、举例3

举例三:PWM控温

//定时器装载1000,相当于1mS
void PID_Init1(void)
{
    spid1.Uplimit = 999;
    spid1.Downlimit = 0;
    spid1.Kp = 20;
    spid1.Ki = 0.1;
    spid1.Kd = 0;
    spid1.e_0 = 0;
    spid1.e_1 = 0;
    spid1.e_2 = 0;
    spid1.ei = 0;
    spid1.ed = 0;
}
void PID_Init2(void)
{
    spid2.Uplimit = 999;
    spid2.Downlimit = 0;
    spid2.Kp = 20;
    spid2.Ki = 0.1;
    spid2.Kd = 0;
    spid2.e_0 = 0;
    spid2.e_1 = 0;
    spid2.e_2 = 0;
    spid2.ei = 0;
    spid2.ed = 0;
}
//位置式
u32 pid_calc(sPID *pid,float target ,float feedback)  
{     
    pid->target = target;
    pid->feedback = feedback;
    pid->e_0 = target - feedback;
    #if 0 
    if(pid->Ki*pid->ei + pid->Kp*pid->e_0 <= pid->Uplimit)//限制累积值
        pid->ei += pid->e_0;  
    else if(pid->e_0 < 0)
       pid->ei += pid->e_0;
    else;
    #endif
    pid->ei += pid->e_0;
    if(pid->Ki*pid->ei > 500)//限制累积值
    {
        pid->ei = 500/pid->Ki;
    }
    if(pid->ei < (-100))
    {
        pid->ei = (-100);
    }
#if 0
    pid->ed = pid->e_0 - 2*pid->e_1 + pid->e_2;  
 #else 
    pid->ed = pid->e_1 - pid->e_0;  //个人以为这个才是对的 
 #endif   
    pid->Out = pid->Kp*pid->e_0 + pid->Ki*pid->ei + pid->Kd*pid->ed;  

    if(pid->Out > pid->Uplimit)
    {
        pid->Out = pid->Uplimit;
    }
    else if(pid->Out < pid->Downlimit)
    {
        pid->Out = pid->Downlimit;
    }
    else
    {}
    
    pid->e_2 = pid->e_1;  
    pid->e_1 = pid->e_0;  
    
    return (u32)pid->Out;     
}

 pid_calc(&spid1,(float)TempCtrler[PURE_TEMP_LYSIS].target,(float)TempForCal[PURE_TEMP_LYSIS]);
 __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,spid1.Out);

5、调试PID参数

调试PID参数链接
在这里插入图片描述

3.1 PID参数的整定原则

U(t)=P*[e(t)+ 1/Ti∫0te(t)dt+Tdde(t)/dt]
a.在输出不振荡时,增大比例增益P。(即增开Kp)
b.在输出不振荡时,减小积分时间常数Ti。(即增大Ki)
c.在输出不振荡时,增大微分时间常数Td。(即减小Kd)

P环很好理解,我们将误差乘以P值加在执行机构上面,当误差越小时P环所得值也就越小,给到执行机构的值也就越小,执行机构反应也就越慢,很符合这种闭环反馈的思想。但是当有一种情况,误差很小的时候P环得出的值给到执行机构上面不足以驱动执行机构工作,这时系统距离期望值仍有一段距离,该距离便被称为静差。

I环的作用是对过去状态的累加,本质上是对误差的积分,当系统存在静差时,I环会持续累加静差值,直到累加值大到足以驱动执行机构工作。这是I环的优点,可以有效地处理静差。但是I环本质上是对过去状态的处理,所以加上I环以后整个系统会变得有些不可控制,这里可以采用积分分离式的思想,只有当误差小于一定范围才开始进行进行误差的累加。如果是对稳定性要求比较高的系统,比如平衡小车直立环,就尽量不要用I环,单PD控制器控制即可。

D环,这个环比较的神奇,它可以预测将来,本质上是对误差的微分。也可以理解成对系统的阻尼,打个比方,在一个理想的环境下有个单摆一直在摆动,它摆动的波形是个正弦波形。如果不加阻尼那么它便可以一直摆动,但是现实中总会有各种各样的阻尼作用迫使单摆运动停下来。D环起的就是这个作用。D环一般运用在角度环比较多,因为你不可以进入弯道才想到转弯,而是在进入弯道之前就要有这个转弯的意识。做智能车的小伙伴们注意了!!

下面式复制别人图片,讲的挺好的,链接如下:
PID参数整定

在这里插入图片描述

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

2.11 PID控制算法(三)----PID结果与实际值的关联 的相关文章

  • STM32在Debug时程序运行时间不对,Debug时定时器中断每次进入断点时间不对,定时器一开启就进入中断的解决办法

    一 Debug时程序时间不对解决办法 1 点击魔术棒 2 点击Debug 点击Settings 3 点击Trace 在Core Clock里修改为你的系统时钟 二 Debug时定时器中断每次进入断点时间不对 在Debug时 程序停下来 定时
  • 51单片机 数码管中断操作

    实践目的 1 掌握中断的概念和思想 2 掌握51单片机中断系统和相关软硬件设计 实践内容 1 利用单片机的P0口接数码管的字段脚 P1 0脚接共阴极 P3 2 P3 3引脚接独立按键产生外部中断信号 编写程序 当程序正常运行时数码管显示H字
  • c项目makefile多重定义错误

    这个问题是一个对应于创建的repexthis问题 在我的嵌入式 C 项目中 我有两个独立的板 我想为每个板创建两个 c 文件 master c 和 Slave c 其中包含自己的特定main 功能 我使用 stm32cumbemx 生成带有
  • 如何让printf在STM32F103上工作?

    我是 STM32F103 世界的新手 我有一个STM32F103的演示代码 我正在使用arm none eabi来编译它 我尝试了在谷歌上可以找到的内容 但到目前为止没有任何效果 我已经花了三天时间来解决这个问题 任何人都可以给我一个运行良
  • 136-基于stm32单片机家庭温湿度防漏水系统设计Proteus仿真+源程序

    资料编号 136 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 蜂鸣器 制作一个基于stm32单片机家庭温湿度防漏水系统设计Proteus仿真 2 通过DHT11传感器检测当前温湿度 并且显示到L
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • STM32F103

    提示 来源正点原子 参考STM32F103 战舰开发指南V1 3PDF资料 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 开发环境硬件普中科技 接线图在g
  • STM32超声波——HC_SR04

    文章目录 一 超声波图片 二 时序图 三 超声波流程 四 单位换算 五 取余计算 六 换算距离 七 超声波代码 一 超声波图片 测量距离 2cm 400cm 二 时序图 1 以下时序图要先提供一个至少10us的脉冲触发信号 告诉单片机我准备
  • SHT10温湿度传感器——STM32驱动

    实验效果 硬件外观 接线 3 3V供电 IIC通讯 代码获取 查看下方 END
  • HAL 锁定和解锁函数如何使用以及为什么?

    我试图理解另一位程序员编写的代码 它使用了I C http en wikipedia org wiki I C2 B2C通信以将数据写入 STM32 微控制器的 EEPROM 一般来说 我理解他的代码是如何工作的 但我不明白他为什么使用HA
  • 解决KEIL编译慢问题

    两种方案 使用v6版本的ARM Compiler 如果v6版本编译不过 必须使用v5版本的 则可以勾选掉Browse Information选项 提升很明显 1分多钟能优化到几秒 看代码量 但是这个有个弊端 在KEIL中会影响函数跳转 建议
  • STM32 暂停调试器时冻结外设

    当到达断点或用户暂停代码执行时 调试器可以停止 Cortex 中代码的执行 但是 当皮质停止在暂停状态下执行代码时 调试器是否会冻结其他外设 例如 DMA UART 和定时器 您只能保留时间 r 取决于外围设备 我在进入主函数时调用以下代码
  • STM32的HAL中实现单按、长按和双按功能

    我正在尝试实现单击 双击和长按功能来执行不同的功能 到目前为止 我已经理解了单击和长按的逻辑 但我不知道如何检测双击 至于代码 我使用计数器实现了单击和长按 但代码仅停留在第一个 if 条件上 bool single press false
  • Freertos低功耗管理

    空闲任务中的低功耗Tickless处理 在整个系统运行得过程中 其中大部分时间都是在执行空闲任务的 空闲任务之所以执行 因为在系统中的其他任务处于阻塞或者被挂起时才会执行 因此可以将空闲任务的执行时间转换成低功耗模式 在其他任务解除阻塞而准
  • STM32F4XX的12位ADC采集数值超过4096&右对齐模式设置失败

    文章目录 一 前言 二 问题1 数值超过4096 三 问题1的排错过程 四 问题2 右对齐模式设置失败 五 问题2的解决方法 5 1 将ADC ExternalTrigConv设置为0 5 2 使用ADC StructInit 函数 一 前
  • STM32H5 Nucleo-144 board开箱

    文章目录 开发板资料下载 目标 点亮LD1 绿 LD2 黄 和LD3 红 三个LED灯 开箱过程 博主使用的是STM32CubeMX配置生成代码 具体操作如下 打开STM32CubeMX File gt New project 选择开发板型
  • PWM DMA 到整个 GPIO

    我有一个 STM32F4 我想对一个已与掩码进行 或 运算的 GPIO 端口进行 PWM 处理 所以 也许我们想要 PWM0b00100010一段时间为 200khz 但随后 10khz 后 我们现在想要 PWM0b00010001 然后
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d
  • 移动数组中的元素

    我需要一点帮助 我想将数组中的元素向上移动一个元素 以便新位置 1 包含位置 1 中的旧值 new 2 包含 old 1 依此类推 旧的最后一个值被丢弃 第一个位置的新值是我每秒给出的新值 我使用大小为 10 的数组 uint32 t TE
  • stm32l0: 执行MI命令失败。使用 vFlashErase 数据包擦除闪存时出错

    我正在使用 Nucleo STM32L031 和 AC6 STM32 工作台 eclipse 我编写应用程序并进入调试模式 一切正常 直到我在应用程序中添加另一个功能 我注意到当我删除 评论 新函数 软件可以再次进入调试模式 但是当我添加

随机推荐

  • 网络吞吐量详解

    吞吐量 简单的讲 对于P2P系统而言 当主机A到主机B传送一个文件 任何时间瞬间的瞬时吞吐量都是主机B接收到该文件的速率 以bps计算 如果文件由F比特组成 主机B接收到所有F比特用去T秒 则文件传送的平均吞吐量是F T bps 举个例子服
  • List>排序

    package com test import java util ArrayList import java util Collections import java util Comparator import java util Ha
  • Android 6.0 miracast 学习

    Miracast是Wi Fi Alliance对支持Wi Fi Display功能的设备的认证名称 Miracast认证的设备将在最大程度内保持对Wi Fi Display功能的支持和兼容 所以从这一个方面可以说Miracast等价于WiF
  • css实现文字渐变

    效果如图 text class text align left font size 36px font weight bold line height 36px background image linear gradient 19f7ff
  • 大数据毕设项目 深度学习+opencv+python实现车道线检测 - 自动驾驶

    文章目录 0 前言 1 课题背景 2 实现效果 3 卷积神经网络 3 1卷积层 3 2 池化层 3 3 激活函数 3 4 全连接层 3 5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV5 6 数据集处理 7 模型
  • 什么是全真互联网?腾讯版Web3元宇宙?

    2020年12月底 马化腾提出全真互联网的概念 即互联网的下一波升级 称为全真互联网 小马哥对新技术的趋势很有前瞻性 这跟今年大火特火的Web3 0和元宇宙可以说是异曲同工 只是不同的描述而已 但马化腾口中的全真互联网和扎克伯格口中的元宇宙
  • Vue实现大文件分片上传、断点续传

    前言 实现大文件分片上传的断点续传以及上传进度条是一个在前端开发中常见且具有挑战性的问题 本篇博客将介绍如何使用Vue框架来实现这个功能 并给出代码示例 概述 大文件分片上传指的是将一个大文件切割成多个小文件 或称为分片 然后依次上传这些小
  • matlab 读取labview,用matlab读取labview存储的二进制

    用matlab读取labview存储的二进制 在labview中 将N个double型数组 内部有9个数字 N个double型数组 内部有4个数字 N个double型数字 N个表示时间的字符串捆绑成簇后 Write To Binary Fi
  • C/C++语言实现的一个缓存队列

    C C 语言实现的一个缓存队列 完整代码下载地址 https gitee com yzhengBTT QueueBuffer 使用方法 对于C语言 队列的创建分两种 1 静态创建 队列大小 define QUEUE SIZE 10 队列数据
  • 一起学Vue3源码,实现最简Vue3【06】 - 实现 readonly 功能

    实现 readonly 功能 什么是readonly 顾名思义 就是只能读 不能修改 TDD编码思维 测试 gt 实现 gt 重构代码 gt 优化 readonly spec ts describe readonly gt it happy
  • vim设置tab为4个空格

    版本为Ubuntu14 04 3 仅当前文本使用 vim默认tab为8个空格 不知道是不是因为linux内核代码的规范中 tab为8个空格 可以使用set ts 4 将tab设置为4个空格 执行完指令 tab缩进变为4个空格 同时再使用ta
  • Struts的优点/缺点

    lt 一 gt 优点 1 struts简单 易懂 容易被人采用 功能强大
  • STM32程序软件复位

    set FAULTMASK 1 STM32程序软件复位 NVIC SystemReset
  • python使用t-sne算法降维,方便可视化

    常用的降维算法有LDA PCA 但通常为了方便可视化 我们使用t sne降维算法 PCA的算法可以参考 异常检测2 PCA异常检测 t san的算法可以参考 t SNE算法 示例代码 import pandas as pd import m
  • 超详细的html+css基础知识树状图~HTML标签

    前言 学习任何新知识 最重要的永远都是搭建属于自己的知识框架 随后学习的细碎知识点往框架里面填入 最后形成一棵属于自己的知识大树 本系列的博客专注更新总结好的思维导图 希望可以帮助大家快速理清知识结构 具体知识树状图 一 HTML标签 1
  • java jinfo_JDK工具-Jinfo命令

    Jinfo是JDK自带Java配置信息工具 位于java的bin目录下 jinfo的作用是实时地查看和调整虚拟机的各项参数 虽然使用Jps命令的 v参数可以查看虚拟机启动时显示指定的参数列表 但是如果想要知道没有被明确指出的系统默认值 就需
  • linux编译安装含义,linux源码包编译安装详解

    linux下安装软件包有两种方法 源文件编译安装 source 和 rpm 安装 1 源文件包安装的通用方法 一般安装源代码的程序你得要看它的README 一般在它的目录下都有的 01 配置 构建应用的第一步就是执行configure脚本
  • OpenCV-Python实战(2)——图像与视频文件的处理

    OpenCV Python实战 2 图像与视频文件的处理 0 前言 1 图像与视频文件处理基础 2 图像的读取与写入 2 1 在 OpenCV 中读取图像 2 2 使用 OpenCV 写入图像 2 3 计算机视觉项目处理流程示例 3 读取相
  • jQuery最佳实践:如何用好jQuery

    一 用对选择器 在jQuery中 你可以用多种选择器 选择同一个网页元素 每种选择器的性能是不一样的 你应该了解它们的性能差异 1 最快的选择器 id选择器和元素标签选择器 举例来说 下面的语句性能最佳 id form 遇到这些选择器的时候
  • 2.11 PID控制算法(三)----PID结果与实际值的关联

    文章目录 1 讲解 2 举例1 3 举例2 4 举例3 5 调试PID参数 1 讲解 1 AD采样 经过PID计算的值 怎么和PWM对应起来 2 电机编码采样 经过PID计算的值 怎么与速度对应起来 这个简单 PID控制原理就是输出一个控制