0、引言&实验器材

2020的国庆节一个人呆在实验室有点无聊,翻了翻还未填上的坑,发现对PID的理解一直停留在纸面上,不曾在现实中的系统中实际操作过(倒立摆和小四轴这些DIY入门训练都还没完整的做过,实在不甘心),于是从零搭建实验平台,以便深入理解PID算法,最后便有了此篇博客,仅作为记录本人学习之用,如有错误,还望指出,谢谢。

由于使用的串口助手没有曲线绘制功能,故暂无实际效果图(PID参数效果通过时间计算比较)

以下为本次所使用的材料

类目 型号
MCU N76e003
电机驱动 TB6612
电机 单霍尔编码器测速电机
电源 30V2A可调电源(10V)
串口模块 CH340C
示波器 普源 DS5062ME
编译环境 Keil4

1、PID算法

假设已对闭环控制有了最基本的认识(如无,可参考这篇文章),参考下图1可以得知,Setpoint为设定值(你所期望系统能达到的值),设定值和反馈值经过计算后得到当前Error(误差),后Error经过PID算法计算得到U,参考下图2,U经过执行机构(如电机)处理、输出,再通过测量元件(如编码器)得到反馈值,再与设定值进行计算,得到下一轮的误差,如此往复,直到设定值与反馈值一致。(位置型)


由上可知PID算法是一种通过对误差值的计算,控制执行机构达到设定值的一种算法。
其中Kp:比例调节、Ki:积分调节、Kd:微分调节,PID算法的公式如下式1所示

需要注意的是,以下所使用的各个计算公式,均是对PID算法进行离散化处理后得到的。

1.1、Kp:比例调节

比例调节的计算:Kp*Error
由上式可以看出,在比例调节中,输入与输出的信号成比例关系,但如果仅有P调节,系统将可能出现稳态误差。

关于稳态误差:控制系统的输出响应在过渡过程结束后的变化形态称为稳态。稳态误差为期望的稳态输出量与实际的稳态输出量之差。
比例调节作用:是按比例反应系统的偏差,系统一旦出现了偏差,比例调节立即产生调节作用用以减少偏差。比例作用大,可以加快调节,减少误差,但是过大的比例,使系统的稳定性下降,甚至造成系统的不稳定。

1.2、Ki:积分调节

积分调节的计算:Ki*(Error1+Error2+Error3+…+Error k)
简单来说,积分调节的计算过程就将积分系数*误差的累加值
积分调节是为了对稳态误差进行处理,同时提供系统精度,作用原理和效果可参考上方动图。

1.2.1、积分饱和现象:简单来说可理解为Error过大时,积分调节得到的数值过大,所以需要对最大输出值进行限制,防止出现积分饱和的发生。

1.2.2、为方便积分调节原理的理解,可假设系统出现稳态误差时,Error恒定不变,此时Kp与Kd调节均失效,但Ki并不受稳态误差影响,依然累积误差值,从而使PID调节不陷于稳态误差中。

为了消除稳态误差,在控制器中必须引入“积分项”。积分项对误差取决于时间的积分,随着时间的增加,积分项会增大。这样,即便误差很小,积分项也会随着时间的增加而加大,它推动控制器的输出增大使稳态误差进一步减小,直到等于零。因此,比例+积分(PI)控制器,可以使系统在进入稳态后无稳态误差。积分调节作用:是使系统消除稳态误差,提高无差度。因为有误差,积分调节就进行,直至无差,积分调节停止,积分调节输出一常值。积分作用的强弱取决与积分时间常数Ti, Ti越小,积分作用就越强。反之Ti大则积分作用弱,加入积分调节可使系统稳定性下降,动态响应变慢。积分作用常与另两种调节规律结合,组成PI调节器或PID调节器。

1.3、Kd:微分调节

微分调节的计算:Kd*(Erorr2-Erorr1)
其中Erorr1为上次的误差,Erorr2为本次的误差。
微分调节可以理解为对被控对象所产生的“阻尼”,当误差变化过快时,微分调节将出现较大“负值”(与误差变化方向相反值),抑制误差继续上升/下降(拉平曲线,参考动图)。

在微分控制中,控制器的输出与输入误差信号的微分(即误差的变化率)成正比关系。自动控制系统在克服误差的调节过程中可能会出现振荡甚至失稳。其原因是由于存在有较大惯性组件(环节)或有滞后(delay)组件,具有抑制误差的作用,其变化总是落后于误差的变化。解决的办法是使抑制误差的作用的变化“超前”,即在误差接近零时,抑制误差的作用就应该是零。这就是说,在控制器中仅引入 “比例”项往往是不够的,比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势,这样,具有比例+微分的控制器,就能够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调。所以对有较大惯性或滞后的被控对象,比例+微分(PD)控制器能改善系统在调节过程中的动态特性。微分调节作用:微分作用反映系统偏差信号的变化率,具有预见性,能预见偏差变化的趋势,因此能产生超前的控制作用,在偏差还没有形成之前,已被微分调节作用消除。因此,可以改善系统的动态性能。在微分时间选择合适情况下,可以减少超调,减少调节时间。微分作用对噪声干扰有放大作用,因此过强的加微分调节,对系统抗干扰不利。此外,微分反应的是变化率,而当输入没有变化时,微分作用输出为零。微分作用不能单独使用,需要与另外两种调节规律相结合,组成PD或PID控制器。

2、运行逻辑

2.1、计算转速

单片机通过使用输入捕获功能(上升沿触发),计算得到电机周期T,再通过T=1/f计算当前电机转动频率。
(备注:其中输入捕获采样6次以消除初值可能不稳的情况,由于串口中断优先级高于输入捕获优先级,所以人为将输入捕获设置为最高优先级,防止系统bug)
有关输入N76E003捕获的博文见此

初始化

 P00_Input_Mode;//将P00设置为输入模式P00 = 1;set_ENF0;//打开0通道噪声滤波TIMER2_CAP0_Capture_Mode;//采用CAP0组捕获信道
//  TIMER2_CAP1_Capture_Mode;
//  TIMER2_CAP2_Capture_Mode;// IC3_P00_CAP0_BothEdge_Capture;//设定P00通过CAP0通道,双边沿触发
//  IC3_P00_CAP0_FallingEdge_Capture;//下降沿触发IC3_P00_CAP0_RisingEdge_Capture;//上升沿触发,得到的是周期T=1/fset_ECAP;//使能输入捕获中断(位于拓展中断中)set_TR2;  //定时器2计数使能  set_T2DIV1;//16分频,通过PWM计算、测试(10ms)set_PCAP;set_PCAPH;//设定输入捕获为最高中断优先级

计算频率

 while(1){if(i>=6)//由于周期会发生变化,该方法会造成一定不等延时{//周期转换,单位us---->mstime=10000/(temp[5]/100);//转换为频率Send_Data_To_UART0(time);//测试PID参数速度用ifi=0;// PID(Ev,time);}}

输入捕获中断

void Capture_ISR (void) interrupt 12
{clr_CAPF0; //清除CAP0 通道中断标志 temp[i]=(C0H*256)+C0L;//将高八位低八位合并i++;clr_TF2;//清除定时器2溢出标志
}

2.2、数据收发

单片机在收到PC端下发的设定值后,将其放入PID函数中进行计算,后变为PWM占空比的脉宽,通过电机驱动器,调节电机转速。

(备注:为了保证串口中断不被更高优先级的输入捕获打断,所以串口接收中断时会关闭输入捕获,接收完成后再打开输入捕获中断使能。)

初始化

//----------串口1、串口0配置----------------    InitialUART0_Timer1(9600);//在不配置SM1,SM2寄存器的情况下,默认工作在模式0(半双工)    IE = 0x90;//允许总中断中断,串口0中断

串口接收中断

/****************串口0中断服务程序***************************/
void Uart0_test() interrupt 4
{if(RI)//串口0接收中断标志(有数据时,硬件置1){clr_ECAP;//关闭输入捕获中断RI=0;//软件置0TI=0;//同时打开,需要对TI也置低UART0_RX_BUF[UART0_RX_STA]=SBUF-48;//从SBUF缓存中读取接收到的数据UART0_RX_STA++ ;                //计算接收长度//进行数据校验,通过RX_BUF&RX_STAif(UART0_RX_STA==3){//收到期望值Ev=UART0_RX_BUF[0]*100+UART0_RX_BUF[1]*10+UART0_RX_BUF[2];UART0_RX_STA=0;//清空接收计数器uFlag=1;}}if(uFlag)//接收完成进入{//      start=1;//测试PID参数速度用
//      PID(Ev,time);uFlag=0;//清除接收完成标志位set_ECAP;//开启输入捕获中断}
}

2.3、PID计算&变频

当串口中断接收到新的设定值后,Err=设定值-当前电机频率,后通过PID算法进行计算,得到的值为PWM高电平的时间(脉宽),再放入PWM中,通过电机驱动器控制电机变频,再通过测量与电机轴同轴转动的霍尔编码器所产生的脉冲信号(输入捕获),计算当前频率,再更新Err,同时将前一个Err进行累积和赋值给Err1,再放入PID计算,如此往复。(待补图)
如需了解PWM中断及在运行中变频,可参考N76E003 PWM中断及设定新的占空比
本程序使用的是位置式PID。

初始化PWM

//-----------------------------产生1KHz占空比50%的PWM---------------------------------------------     P03_PushPull_Mode;PWM5_P03_OUTPUT_ENABLE;//使能PWM5,通过P03引脚输出clr_PWMTYP;//边沿对齐模式clr_PWMMOD0;//设置为独立输出模式clr_PWMMOD1;PWM_CLOCK_DIV_8;//8分频模式16MHz/8PWMPH = 0x07;//1999PWMPL = 0xcf;set_SFRPAGE;//PWM4 and PWM5 duty seting is in SFP page 1PWM5H = 0x03;//999          PWM5L = 0xe7;clr_SFRPAGE;                                            set_LOAD;//载入周期和占空比set_PWMRUN;//开始输出PWM

PID函数&重装PWM值

#define Kp 3.0
#define Ki 0.9
#define Kd 4.1int Err=0,Err1=0;//PID过程中使用的算法
uint Ev=100;//初始期望值
int ErrAdd;//存放误差累积
uint PWM_Value;//需要改变的占空比值//    SHz为设定值,EHz为当前值(time
void PID(uint SHz,uint EHz)
{Err1=Err;//获得上次的值Err=SHz-EHz;//计算得到当前差值if(Err>1||Err<-1)//由于实际系统中存在各类干扰,所以设定阈值为±1,提高系统稳定性{ErrAdd+=Err;//累积误差值//PWM_Value为高电平持续脉宽,初值为1000PWM_Value=1000+((Kp*Err)+(Ki*ErrAdd)+(Kd*(Err-Err1)));//PID计算//防止积分饱和,由于PWM_Value为无符号整数型,为负值时会大于2000。if(PWM_Value>2000)PWM_Value=1999;//--------PWM重装初值---------------clr_LOAD;//关闭载入之前的值set_SFRPAGE;//PWM4 and PWM5 duty seting is in SFP page 1PWM_Value-=1;PWM5H= PWM_Value/256;//得到高八位PWM5L= PWM_Value%256;//得到第八位clr_SFRPAGE;   set_LOAD;//设定完成,开始载入}
}

3、程序代码&电路

#include "N76E003.h"
#include "Common.h"
#include "Delay.h"
#include "SFR_Macro.h"
#include "Function_define.h"#define uint unsigned int
#define uchar unsigned char #define Kp 3.0
#define Ki 0.9
#define Kd 4.1//#define TH0_INIT 67uint time;//频率
uint temp[10];//存放输入捕获值
int i=0;uint PWM_Value;//需要改变的占空比值uchar UART0_RX_BUF[3];//串口0,串口1数据接收缓冲区
uchar UART0_RX_STA=0;//串口0,串口1接收计数器
uchar uFlag=0;//串口中断指令接收完成标志int Err=0,Err1=0;//PID过程中使用的算法
uint Ev=100;//期望值
int ErrAdd;//存放误差累积char start=0;
/*SHz为设定值,EHz为当前值(time
*/
void PID(uint SHz,uint EHz)
{Err1=Err;//获得上次的值Err=SHz-EHz;//计算得到当前差值if(Err>1||Err<-1)
//  if(SHz!=EHz){ErrAdd+=Err;PWM_Value=1000+((Kp*Err)+(Ki*ErrAdd)+(Kd*(Err-Err1)));//PID计算if(PWM_Value>2000)PWM_Value=1999;//--------PWM重装初值---------------clr_LOAD;//关闭载入之前的值set_SFRPAGE;//PWM4 and PWM5 duty seting is in SFP page 1PWM_Value-=1;PWM5H= PWM_Value/256;//得到高八位PWM5L= PWM_Value%256;//得到第八位clr_SFRPAGE;   set_LOAD;//设定完成,开始载入}
}/*
通过输入捕获得到的周期,计算当前频率,采样6次发送中间值
由于串口中断优先级高于输入捕获,所以人为将输入捕获设置为最高优先级,防止系统bug
串口中断中会关闭输入捕获,接收完成后再打开输入捕获
PWM需要在运行中变频。
PID函数是对参数进行设定,使用位置式(直接赋值)
电压10V
*/void main (void)
{Set_All_GPIO_Quasi_Mode;//所有IO设置为双向模式P03_PushPull_Mode;P00_Input_Mode;//将P00设置为输入模式P00 = 1;set_ENF0;//打开0通道噪声滤波TIMER2_CAP0_Capture_Mode;//采用CAP0组捕获信道
//  TIMER2_CAP1_Capture_Mode;
//  TIMER2_CAP2_Capture_Mode;// IC3_P00_CAP0_BothEdge_Capture;//设定P00通过CAP0通道,双边沿触发
//  IC3_P00_CAP0_FallingEdge_Capture;//下降沿触发IC3_P00_CAP0_RisingEdge_Capture;//上升沿触发,得到的是周期T=1/fset_ECAP;//使能输入捕获中断(位于拓展中断中)set_TR2;  //定时器2计数使能  set_T2DIV1;//16分频,通过PWM计算、测试(10ms)set_PCAP;set_PCAPH;//设定输入捕获为最高中断优先级
//      set_EA;
//-----------------------------产生1KHz占空比50%的PWM---------------------------------------------        PWM5_P03_OUTPUT_ENABLE;//使能PWM5,通过P03引脚输出clr_PWMTYP;//边沿对齐模式clr_PWMMOD0;//设置为独立输出模式clr_PWMMOD1;PWM_CLOCK_DIV_8;//16分频模式PWMPH = 0x07;//00PWMPL = 0xcf;//0fset_SFRPAGE;//PWM4 and PWM5 duty seting is in SFP page 1PWM5H = 0x03;//00               PWM5L = 0xe7;//08clr_SFRPAGE;                                            set_LOAD;//载入周期和占空比set_PWMRUN;//开始输出PWM
//----------串口1、串口0配置----------------   InitialUART0_Timer1(9600);//在不配置SM1,SM2寄存器的情况下,默认工作在模式0(半双工)    IE = 0x90;//允许总中断中断,串口0中断
//---------输入你自己的代码-------------------while(1){if(i>=6)//由于周期会发生变化,该方法会造成一定不等延时{//周期转换,单位us---->mstime=10000/(temp[5]/100);//转换为频率if(start)Send_Data_To_UART0(time);//测试PID参数速度用ifi=0;PID(Ev,time);}}
}/****************串口0中断服务程序*****************/
void Uart0_test() interrupt 4
{if(RI)//串口0接收中断标志(有数据时,硬件置1){clr_ECAP;//关闭输入捕获中断RI=0;//软件置0TI=0;//同时打开,需要对TI也置低UART0_RX_BUF[UART0_RX_STA]=SBUF-48;//从SBUF缓存中读取接收到的数据UART0_RX_STA++ ;                //计算接收长度//进行数据校验,通过RX_BUF&RX_STAif(UART0_RX_STA==3){//收到期望值Ev=UART0_RX_BUF[0]*100+UART0_RX_BUF[1]*10+UART0_RX_BUF[2];UART0_RX_STA=0;//清空接收计数器uFlag=1;}}if(uFlag)//接收完成进入{start=1;//测试PID参数速度用
//      PID(Ev,time);uFlag=0;//清除接收完成标志位set_ECAP;//开启输入捕获中断}
}/****************输入捕获中断服务程序*****************/
void Capture_ISR (void) interrupt 12
{clr_CAPF0; //清除CAP0 通道中断标志 temp[i]=(C0H*256)+C0L;i++;clr_TF2;//清除定时器2溢出标志
}

4、调参思路





5、参考资料

简易PID算法的快速扫盲(超详细+过程推导+C语言程序)
PID(比例积分微分)介绍

基于单片机的电机转速PID控制相关推荐

  1. linux pwm控制蜂鸣器 滴滴_51单片机PWM直流电机PID控制转速源程序

    \ AT89C51单片机PWM直流电机转速PID控制源程序,重点介绍利用MCS-51系列单片机控制PWM信号从而实现对直流电机转速进行控制的方法.设计中采用了专门的芯片组成了PWM信号的发生系统并且对 ...

  2. 智能窗帘传感器c语言程序,基于单片机的智能窗帘控制系统设计(附程序代码)

    基于单片机的智能窗帘控制系统设计(附程序代码)(论文18000字,程序代码) 摘要:二十一世纪初以来,科学技术不断发展,智能家居涌现于各家各户,人们越来越重视生活质量的提高.但是传统的手动开合窗帘耗时 ...

  3. 交通灯控制系统c语言编程,基于单片机的交通灯控制系统设计(本科)毕业论文设计.doc...

    基于单片机的交通灯控制系统设计 摘 要 当你路过一个十字路口时,你是否注意到各个方向车辆和行人有有条不紊的通过十字路口.这样井然有序的情境靠什么来实现的呢?靠的是交通灯控制系统.在论文中我使用单片机S ...

  4. 基于单片机c语言的豆浆机,基于单片机的全自动豆浆机控制系统设计.doc

    论文题目: 基于单片机的全自动豆浆机控制系统设计 摘 要 全自动豆浆机基本工作过程是将事先泡好的大豆放入豆浆机内,并加入适量冷水后将电热管通电加热至80°C,粉碎电机通电工作.进行磨豆浆期间断续工作三 ...

  5. 基于单片机双路温度检测报警系统设计-基于单片机声光控智能开关控制灯设计-基于单片机热电偶智能体温检测设计-基于单片机小型家用燃气锅炉控制系统设计-基于单片机一氧化碳有毒气体采集报警系统设计

    1628基于单片机双路温度检测报警系统设计(串口上位机控制) 基于pcf8591 tlc2543的双路温度检测报警系统 带串口上位机控制带仿真 源程序 温度传感器是 LM35 两路测温通道所用的ad芯 ...

  6. 【分享】基于单片机嵌入式的家用智能节水淋浴控制器的设计-基于单片机的电子贺卡控制系统设计-基于单片机的倒计时牌控制系统设计-基于单片机的彩灯控制器系统设计-多模式彩灯-单片机的八路路数字电压表控制设计

    1334基于单片机嵌入式的家用智能节水淋浴控制器的设计-全套毕设课设设计资料 三个ds18b20分别采集进水口热水  冷水 和温水的水温,然后分别显示出来,按下开始按键,系统初始化,自动设置出水温度为 ...

  7. 基于单片机室内节能灯光控制系统设计(毕业设计资料)

    摘要: 室内照明节能系统,本设计设有定时模式.检测是否有人模式.检测光线强度模式和手动模块等四种控等模式,各种模式之间可以通过按键互相切换,方便使用. 1.通过继电器来控制照明灯的开启或关闭: 2.有 ...

  8. cmac神经网络 matlab,基于CMAC 神经网络的PID 控制.pdf

    基于CMAC 神经网络的PID 控制 基于 CMAC 神经网络的 PID 控制 PID Control System Based on CMAC Neural Network 洪云飞 陈孚 付兴武 H ...

  9. 基于单片机音频放大器声控灯控制电路设计(毕设课设资料)

    139[毕设课设]基于单片机音频放大器声控灯控制电路设计 [资源下载]下载地址如下: https://docs.qq.com/doc/DTlRSd01BZXNpRUxl

  10. 单片机升降机c语言程序,基于单片机的货运升降机控制系统设计

    基于单片机的货运升降机控制系统设计 本文介绍以MSP430F2232单片机为核心的货运升降机控制系统.该系统完成了各楼层呼叫.货运升降机运行.急停.货运升降机位置.货运升降机门.照明.故障等 (本文共 ...

最新文章

  1. 生信服务器 | 防火墙基本配置
  2. java面向对象思维导图_2020年Java进阶架构师的必备思维导图,让你少走弯路!
  3. 俄罗斯机器人雄鹿_世界上最''倒霉''的机器人:逼真到难以置信,为忍受痛苦而生...
  4. C++基础-string截取、替换、查找子串函数
  5. hdu3117 斐波那契前后4位
  6. php 定义title,HTML5中对title属性的定义与规定
  7. 第5章-Vue.js交互及生命周期练习
  8. 【转载】IT新曙光——“遇事不决,量子力学” 的问与答
  9. 测试硬盘读写速度软件_机械硬盘回春:2023年容量破40TB 读写速度媲美SATA SSD
  10. 笔试算法复习——数组去重
  11. UILabel 详解
  12. 让划动 listview时 没有黑色背景
  13. 《About Multi-Touch(多点触摸是个什么东西?)》:Sony PS3Eye 介绍、拆解与使用全指南...
  14. Linux普通用户查看本机域名,域名的解析过程
  15. 在idea中使用git详解
  16. 2022中国汽车品牌魅力指数排名:广汽传祺、吉利、东风风行、荣威位居自主品牌前列 | 美通社头条...
  17. 弘扬中华传统文化 讲好中国故事
  18. python matlab 普朗克公式黑体光谱辐射出射度 绘图
  19. 申请https证书的过程
  20. react项目Menu菜单栏、iconfont图标引用

热门文章

  1. 步进电机驱动器细分功能的介绍以及设置
  2. Linux下pgadmin4启动报错,如何在UBUNTU 16.04上安装桌面模式中的PGADMIN 4
  3. 【IAR】 This device has been locked for debugging
  4. git(icode)分支及发布管理方式
  5. 智能配电房综合环境监控系统
  6. 阿里云云服务器部署HTML静态网页
  7. 基于Android的家庭财务管理流程图,基于android的个人财务管理系统的设计与实现.pdf...
  8. STK之Commu模块之二-仿真同步卫星与地面站通信显示EIRP分布
  9. 30个必会的Axure小技巧
  10. mysql批量入库values限制_mysql批量插入数据方法