基于单片机的电机转速PID控制

发布者:Xiaoxue666最新更新时间:2022-06-24 来源: eefocus关键字:单片机  电机转速  PID控制 手机看文章 扫描二维码
随时随地手机看文章

0、引言&实验器材

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


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


以下为本次所使用的材料

image.png

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/f

set_ECAP;//使能输入捕获中断(位于拓展中断中)

set_TR2;  //定时器2计数使能  


set_T2DIV1;//16分频,通过PWM计算、测试(10ms)

set_PCAP;

set_PCAPH;//设定输入捕获为最高中断优先级


计算频率


while(1)

{

if(i>=6)//由于周期会发生变化,该方法会造成一定不等延时

{

//周期转换,单位us---->ms

time=10000/(temp[5]/100);//转换为频率

Send_Data_To_UART0(time);//测试PID参数速度用if

i=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;//软件置0

TI=0;//同时打开,需要对TI也置低

UART0_RX_BUF[UART0_RX_STA]=SBUF-48;//从SBUF缓存中读取接收到的数据

UART0_RX_STA++ ;                //计算接收长度

//进行数据校验,通过RX_BUF&RX_STA

if(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/8

PWMPH = 0x07;//1999

PWMPL = 0xcf;

    set_SFRPAGE;//PWM4 and PWM5 duty seting is in SFP page 1

    PWM5H = 0x03;//999          

    PWM5L = 0xe7;

    clr_SFRPAGE;                                            

    set_LOAD;//载入周期和占空比

    set_PWMRUN;//开始输出PWM


PID函数&重装PWM值


#define Kp 3.0

#define Ki 0.9

#define Kd 4.1


int 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为高电平持续脉宽,初值为1000

PWM_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 1

PWM_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 67


uint 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 1

PWM_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/f

set_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;//00

PWMPL = 0xcf;//0f

    set_SFRPAGE;//PWM4 and PWM5 duty seting is in SFP page 1

    PWM5H = 0x03;//00               

    PWM5L = 0xe7;//08

    clr_SFRPAGE;                                            

    set_LOAD;//载入周期和占空比

    set_PWMRUN;//开始输出PWM

//----------串口1、串口0配置----------------

InitialUART0_Timer1(9600);

//在不配置SM1,SM2寄存器的情况下,默认工作在模式0(半双工)  

IE = 0x90;//允许总中断中断,串口0中断

//---------输入你自己的代码-------------------

while(1)

{

if(i>=6)//由于周期会发生变化,该方法会造成一定不等延时

{

//周期转换,单位us---->ms

time=10000/(temp[5]/100);//转换为频率

if(start)Send_Data_To_UART0(time);//测试PID参数速度用if

i=0;

    PID(Ev,time);

}

}

}


/****************串口0中断服务程序*****************/

void Uart0_test() interrupt 4

{

if(RI)//串口0接收中断标志(有数据时,硬件置1)

{

clr_ECAP;//关闭输入捕获中断

RI=0;//软件置0

TI=0;//同时打开,需要对TI也置低

UART0_RX_BUF[UART0_RX_STA]=SBUF-48;//从SBUF缓存中读取接收到的数据

UART0_RX_STA++ ;                //计算接收长度

//进行数据校验,通过RX_BUF&RX_STA

if(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、调参思路

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

关键字:单片机  电机转速  PID控制 引用地址:基于单片机的电机转速PID控制

上一篇:N76E003控制双路步进电机(开环)
下一篇:N76E003 驱动 UC1705并口屏(8080)

推荐阅读最新更新时间:2024-11-20 00:18

用AT89C2051单片机制作水族箱加氧泵自控开关源程序
以下程序已实际调试运行通过) ; ---AT89C2051加氧泵控制器源程序-OK! org 0000h ajmp main nop org 01bh clr tr1 ajmp timon org 30h main:mov 40h,#00h mov 41h,#00h mov 42h,#00h mov 43h,#02h mov 44h,#00h mov 45h,#00h
[单片机]
基于AtmelAVR Flash微控制器的基本原理及在汽车中的应用研究
  车上可自动关闭的电动车窗或车门设备潜藏着卡死,挤压以及可能伤人的危险。它们必须能够反向移动以防止马达所施加的力超出正常限制。这种特性意味着必须持续监视速度、电流和玻璃的位置。   现代汽车中的电动设备   目前,在高端客用汽车中电子组件和系统在成本中已占20%以上。增加电子设备的数目可以更好的控制传感器和致动器,从而增强汽车的舒适性和安全性。可以预测,大部分的中等或汽车将会系统性的装备电动车窗或车门系统。这些设备中的绝大多数是全自动的,这意味着它们必须附带安全系统以防止伤人或机械故障已有法规设立了电动系统必须遵守的规则。这一点在车窗的升起和车门的滑动上尤其正确的。这篇应用笔记介绍了如何实现一个防夹算法,该算法初是用于电动车
[单片机]
基于AtmelAVR Flash<font color='red'>微控制器</font>的基本原理及在汽车中的应用研究
基于51单片机交通灯课程设计
1 绪论1.1设计目的 单片机具有性价比高、集成度高、可靠性好、抗干扰性强等特点,广泛运用于各种智能仪器中。基于新型规则的可编程交通控制系统,可以实现对车辆、行人的控制,使的交通便于管理。所以,采用单片机自动控制交通灯有现实的社会意义。 通过本次设计,使学生不仅更加深刻领会微型计算机从硬件组成到软件编程的基本原理和知识,而且更要学会应用,务必做到理论和实践相结合,掌握硬件分析、软件设计的基本思想和方法,提高分析问题、解决问题和工程实践的能力。 1.2设计内容 1)设计一个十字路口交通灯控制器。用单片机控制LED灯模拟指示。模拟东西方向的十字路口交通信号控制情况。南北方向主干道计时时间为60s,东西方向次干道计时时间为45s。
[单片机]
基于51<font color='red'>单片机</font>交通灯课程设计
基于AT89C52单片机的多用户密码锁设计
  安全防盗已成为社会问题。而锁自古以来就是把守门户的铁将军,人们对它要求甚高,既要安全可靠地防盗,又要使用方便,这也是制锁者长期以来研制的主题。   文中设计的电子密码锁和市面销售的AB锁有类似之处,但主要区别在于设计的这个密码锁由主人决定客人进入的密码,不需要通过换锁来防止用过该锁的人再次进入,而且只有主人才有对密码的修改权。    1 方案设计思想   文中的多用户密码锁设有一个管理员用户,管理员对密码有修改权。另设有两个来宾用户,可以根据管理员提供的密码开锁,自己则不可以任意修改密码。更换住户时,只需要管理员更换密码即可,这样就避免了换锁带来的麻烦,节约了成本。   密码锁的设计采用通用板制作,所以涉及到元器件的排
[单片机]
基于AT89C52<font color='red'>单片机</font>的多用户密码锁设计
单片机(AVR)串口接收和发送
//串口初始化 void UART_Init(void) { UCSRB = UBRRH = 0; UBRRL = (ClockCPU/Baud)/16-1; UCSRB = (1 RXEN) | (1 TXEN); //enable UART receiver and transmitter UCSRC = (1 URSEL)|(1 USBS)|(3 UCSZ0);//设置帧格式: 8 个数据位, 2 个停止位 } //串口中断使能或屏蔽 void UART_int_enable(void) { UCSRB |= (1 RXCIE); // UCSRB &= ~(
[单片机]
基于AT89C51单片机控制LED摇摇棒的研究
0 引言 随着现代科技的发展,高科技产品以其简洁化、便携等,给人们带来了很大的方便。而“摇摇棒”以其更加简捷与新颖的信息传递方式给人们带来耳目一新的感受,也必将会给人们带来一种新的方便的文化传递方式,常用在晚会及大型的娱乐节目场合。 本文通过研究和设计一个利用事先编好程序来控制16个LED发光二极管,并配合左右手的摇晃来显示字符和简易图形的电子装置(简称为“摇摇棒”),来传递有趣的信息。此装置利用AT89C51单片机对发光二极管阵列进行控制。用滚珠开关检测当前摇动状态,单片机控制16个发光二极管进行不同频率的亮灭刷新,则只要摇动就可以可显示输出文字及图案等信息,从而达到在该视觉平面上传达信息的作用。 1 硬件系统的组成
[单片机]
基于AT89C51<font color='red'>单片机</font>控制LED摇摇棒的研究
PIC单片机的bank和PC的出错问题
1、 BANK设置错误: 先来看一段程序: include p16f877.inc PORTDB EQU 20H …… START movlw b‘11110000’ movwf PORTDB clrf TRISD MAIN bcf STATUS,C rlf PORTDB,1 btfsc STATUS,C bsf PORTDB,0 movf PORTDB,W movwf PORTD call DELAY goto MAIN …… 上面的是一个将D口的发光二极管循环点亮的小程序,实际运行发现并不能达到点亮的效果。通过设置断点和观察变量的手段发现,单片机在执行“clrf TRISD”这一语句后,T
[单片机]
Microchip加倍LCD PIC18单片机闪存及RAM容量以降低成本
PIC18F85J90系列单片机可提供集成的LCD模块、32 KB闪存及内部电压控制器,瞄准成本敏感的嵌入式显示应用 全球领先的单片机和模拟半导体供应商——Microchip Technology Inc.(美国微芯科技公司)推出6款集成了液晶显示器(LCD)模块的8位PIC单片机系列新产品。PIC18F85J90系列的闪存及RAM存储器容量比现有的64及80引脚系列器件增加了1倍,适用于需要嵌入式控制的高成本效益的人机接口应用,包括恒温器、民用表具及医疗仪器。存储容量的增加有助于用户增加更多诸如语音回放的复杂功能,拥有更多的自编程存储器分配,同时利用3V PIC18 J系列的制造工艺技术节省了成本。 具有片上LCD模块的PI
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved