从代码中认识PID的应用

电机转速PID控制。两份网上的工程代码。

原理:PWM波控制电机转速,控制PWM波的高电平时间,即控制占空比来控制转速。

都是增量式PID,需要三次误差值,这次测的误差,error,上次测的误差,pre_error,上上次测的误差,pre_pre_error

转速是执行器的输出。

输入你想要的转速(设定的转速)Setspeed,测量得到的转速,Now_speed。

得到误差error=Setspeed-Now_speed

设定你的PID系数Kp,Ki,Kd

经过PID函数

Now_pwm = Per_pwm+Kp*(error-pre_error)+Ki*error+Kd*(pre_pre_error*pre_error+pre_pre_error)

得到输入执行器的PWM值。

void SpeedAdjust()
{long d_error,dd_error,error;                //声明变量error = (int)(speed_ept - now_speed);       //计算本次误差(期待速度-当前速度)d_error = error - pre_error;                //本次误差与上次误差之差dd_error = pre_error - pre_pre_error;       //上次误差与上上次误差之差pre_error = error;                          //将本次误差赋值给上次误差(下次计算用)pre_pre_error = pre_error;                  //将上次误差赋值给上上次误差(下次计算用)pwm_tmp = pwm_tmp + PID_P*d_error + PID_I*error + PID_D*dd_error;       //计算pwm宽度调整量if(now_speed>22)                            //如果当前速度大于22{Set_DCMotor(0,0);                       //不调整电机}else        //否则{if(pwm_tmp>=0)                      //如果pwm宽度调整为正(增加宽度){Set_DCMotor(pwm_tmp,0);         //增加直流电机转速}else        //否则{Set_DCMotor(pwm_tmp,1);         //降低直流电机转速}}before_speed = now_speed;               //讲本次速度赋值给上次速度(下次使用)
}
#include<reg52.h>
#include<stdio.h>#define uchar unsigned char
#define uint unsigned int
#define THC0 0xf8
#define TLC0 0xcc   //2msunsigned char code Duan[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//共阴极数码管,0-9段码表unsigned char Data_Buffer[8]={0,0,0,0,0,0,0,0};
unsigned char Data[4]={0,0,0,0};
unsigned char Arry[4]={0,0,0,0};bit flag1=0;
bit flag0=0;
uchar i=0;sbit AddSpeed=P1^1;
sbit SubSpeed=P1^2;
sbit PWM_FC=P1^0;int e=0,e1=0,e2=0;         //pid 偏差
float uk=0,uk1=0.0,duk=0.0;  //pid输出值
float Kp=5,Ki=1.5,Kd=0.9;    //pid控制系数
//float Kp=10;int out=0;
uint SpeedSet=1000;
uint cnt=0;
uint Inpluse=0,num=0;     //脉冲计数
uint PWMTime=0;                //脉冲宽度unsigned char arry[];void SendString(uint ch);
void PIDControl();
void SystemInit();
void delay(uchar x);
void PWMOUT();
void SetSpeed();
void SegRefre();/**************主函数************/
void main()
{SystemInit();//系统初始化while(1){SetSpeed();//设置速度SegRefre();//更新数码管显示PWMOUT();  //PWM输出if(flag0==1){flag0=0;ES=0;//关串口中断,避免TI引起串口中断TI=1;//printf前TI置1printf("%f",(float)(num>>8));//脉冲计数printf("%f",(float)num);     //脉冲计数while(!TI);TI=0;       //TI软件清除ES=1;      //允许串口中断}}
}//PID偏差控制计算
void PIDControl()        //pid偏差计算
{e=SpeedSet-num;//设置速度-实际速度,两者的差值 //对应于增量式PID的公式Δuk=uk-u(k-1)//  duk=(Kp*(e-e1))/100;//只调节Pduk=(Kp*(e-e1)+Ki*e)/100;//只调节PI
//  duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2))/100;//调节PIDuk=uk1+duk;//uk=u(k-1)+Δukout=(int)uk;//取整后输出if(out>250) //设置最大限制out=250;else if(out<0)//设置最小限制out=0;uk1=uk;         //为下一次增量做准备e2=e1;e1=e;PWMTime=out;  //out对应于PWM高电平的时间}//较短的延时。注意delay的值不要超过255
void delay(uchar x)
{uchar i,j;for(i=x;i>0;i--)for(j=50;j>0;j--);//接近500us
}//PWM输出
void PWMOUT()
{if(cnt<PWMTime)//若小于PWM的设定时间,则输出高电平PWM_FC=1;else           //否则输出低电平PWM_FC=0;if(cnt>250)    //超过限制清零cnt=0;
}//系统初始化
void SystemInit()
{TMOD=0X21;    //T1用于串口的波特率发生器 T0用于定时TH0=THC0;      //2ms定时,晶振频率是11.0592MHz,事先算好装入THC0中TL0=TLC0;     //2ms定时,晶振频率是11.0592MHz,实现算好装入TLCO中ET0=1;        //允许定时器0中断TR0=1;       //启动定时器0EX0=1;         //允许外部中断IT0=1;         //中断方式设置为下降沿//用于串口调试时用PCON=0x00;  //SMOD不加倍SCON=0x50;    //串口工作方式1,允许接收TH1=0xfd;     //波特率9600TL1=0xfd;     //波特率9600TR1=1;        //启动定时器1ES=1;      //开串口中断EA=1;       //开总中断e =0;        //PID的差值初值均为0e1=0;         e2=0;
}//设置转速
void SetSpeed()
{if(AddSpeed==0)//按键{delay(200);//消抖if(AddSpeed==0)//再次判断按键{SpeedSet+=100;//速度增加if(SpeedSet>9999)//超限SpeedSet=9999;//设置为最大9999}}if(SubSpeed==0)//按键{delay(200);//消抖if(SubSpeed==0)//按键{SpeedSet-=100;//速度减if(SpeedSet<0)//低于速度的最小值 SpeedSet=0;//速度置零}}
}//数码管显示更新
void SegRefre()       //显示刷新
{Data_Buffer[0]=SpeedSet/1000;Data_Buffer[1]=SpeedSet%1000/100;Data_Buffer[2]=SpeedSet%100/10;Data_Buffer[3]=SpeedSet%10;Data_Buffer[4]=num/1000;Data_Buffer[5]=num%1000/100;Data_Buffer[6]=num%100/10;Data_Buffer[7]=num%10;
}//外部中断,统计脉冲数目,实际上是统计电机的转速
//在实际中,电机没有一根线引出来可以表示他的转速,只能通过传感器如霍尔传感器的方式测量转速
//脉冲一次下降沿对应于一次自增
void int0() interrupt 0
{Inpluse++;
}//定时器T0操作
void t0() interrupt 1
{static unsigned char Bit=0;//静态变量,退出程序值保留static unsigned int time=0;static unsigned int aa=0;TH0=THC0;//重新赋初值TL0=TLC0;aa++;if(aa==50)//每100ms{aa=0;flag0=1;}cnt++; //pid 周期Bit++;time++;  //转速测量周期if(Bit>8) Bit=0;//数码管总共只有8位,超过8位则在程序上进行清零//数码管显示部分P0=0xff;P2=Duan[Data_Buffer[Bit]];switch(Bit){case 0:P0=0X7F;break;case 1:P0=0XBF;break;case 2:P0=0XDF;break;case 3:P0=0XEF;break;case 4:P0=0XF7;break;case 5:P0=0XFB;break;case 6:P0=0XFD;break;case 7:P0=0XFE;break;}//数码管显示部分if(time>500)//每1s处理一次脉冲{time=0;num=Inpluse*15;//实际转速,*15是由电机决定的,电机的一个脉冲对应着电机转过了15转Inpluse=0;     //清零,为下一次计数做准备PIDControl();  //调用PID控制程序}
}//串口中断,用于对串口的数据进行处理
void u_int(void) interrupt 4
{ES=0;//关串口中断,避免在数据处理的过程中造成影响if(RI)//若有RI==1,由RI产生中断{RI=0;//RI标志位必须通过软件进行清零arry[i]=SBUF;//将字符赋到arry中i++;        //下一个数if(i>3)        //接收完了指令,进行数据处理,一共有arry[0],arry[1],arry[2],arry[3]四个数据{flag1=1;//将标志置1i=0; //i清零,重新计数}if(flag1) //若flag1==1{flag1=0;//flag1清零SpeedSet=(arry[0]-'0')+(arry[1]-'0')*10+(arry[2]-'0')*100+(arry[3]-'0')*1000;//获得的速度值//由于串口发送的是字符,所以要减去'0'}}else//对应的由TI产生中断TI=0;//TI由软件进行清零  ES=1;//处理完后再开中断
}

C语言实现PID之应用相关推荐

  1. C语言实现pid算法(附完整源码)

    实现pid算法 pid结构体定义 C语言实现pid算法完整源码(定义,实现,main函数测试) pid结构体定义 struct pid {// Controller gainsfloat kP;flo ...

  2. pid控制温度c语言,C语言编写PID温度控制程序

    <C语言编写PID温度控制程序>由会员分享,可在线阅读,更多相关<C语言编写PID温度控制程序(5页珍藏版)>请在人人文库网上搜索. 1.* init program *)PI ...

  3. C语言实现PID算法:位置式PID和增量式PID

    原创者微信公众号 PID算法可以说是在自动控制原理中比较经典的一套算法,在现实生活中应用的比较广泛. 大学参加过电子竞赛的朋友都应该玩过电机(或者说循迹小车),我们要控制电机按照设定的速度运转,PID ...

  4. 小型温控系统c语言程序,pid算法温度控制c语言程序 - 全文

    温度控制PID自整定原理介绍 整定PID(三模式)控制器 整定温度控制器涉及设置比例.积分和微分值,以得到对特定过 程的可能的最佳控制.如果控制器不包含自动整定算法,或者自 动整定算法未提供适合特定应 ...

  5. C语言实现PID算法

    #include <stdio.h> struct _pid { int pv; /*integer that contains the process value*/ int sp; / ...

  6. c语言写pid算法,用c语言实现的pid算法

    pid算法应该算是所以算法中最稳定最可靠最简单的算法,在库函数中添加这种算法对实际控制的时延有非常大的帮助. 全部资料51hei下载地址:   C语言PID算法.doc PID算法(c语言)(来自老外 ...

  7. C语言编写PID基础算法

    PID的作用为将系统输出快速稳定于某一个值 #include <stdio.h> #include <stdlib.h> #include <math.h>/*pi ...

  8. 20190109基于贝加莱PLC 用C语言构建PID控制器 与应用一

    void _CYCLIC PIDRegulation(void) { // // typedef struct // // { // // float setpoint; //设定值 // // fl ...

  9. aix c语言根据pid获取内存信息,如何通过C语言编程获取AIX的CPU,内存使用率

    回复 1# sigou     如果你AIX上安装了bos.perf.libperfstat这个包的话,会有示例程序.root@testhost:/proc/sys/fs/jfs2 #lslpp -f ...

最新文章

  1. GitHub推出云端IDE,几秒完成开发环境配置,今后可以在浏览器里使用VS Code了
  2. ICPC China Nanchang National Invitational - I. Max answer(线段树+ST)
  3. LeetCode 897. 递增顺序查找树(中序遍历)
  4. java 数据库 事务 只读_java – odd SQLException – 无法检索转换只读状态服务器
  5. linux php 如何上传webshell,linux+apache+php的一次拿webshell的心得
  6. oracle导入字符集,Oracle导入字符集问题
  7. python英文词频统计去除定冠词_使用Python进行英文词频统计
  8. 快速开平方取倒数的算法
  9. hdu 1002 A+B problem II
  10. boost context上下文切换
  11. PostSQL编写经验(利用坐标值,创建空间要素字段)
  12. 怎样才算是优质的Scratch作品?
  13. 关于STC8H8K64U单片机IAP升级过程
  14. 计算机报考电子邮箱格式,电子邮箱格式怎么写
  15. cad画固定长度的弧线_CAD中如何绘制指定弧长的圆弧
  16. [日推荐]『Brick4积木』乐高迷不可错过的小工具
  17. 算法注册机编写扫盲之续篇---第三课
  18. item_search_img - 按图搜索淘宝商品(拍立淘)
  19. 罗曼 matlab,成年人简易钢琴教程100首
  20. Resin 与 Tomcat 服务器对比

热门文章

  1. 网页安全证书错误但无法安装证书的解决办法
  2. 编写html获取天气(数据来源theamp;nbs…
  3. 求求你了,不要再浪费抗原了!!!
  4. php失物招领回复源码,失物招领系统 (1) - WEB源码|源代码 - 源码中国
  5. OKR:打破组织中的沟通壁垒
  6. 九个值得一试的跨平台移动应用开发工具
  7. mcnpf5输出结果_MCNP使用说明解读.ppt
  8. Napster 成立 | 历史上的今天
  9. linux下打开chm格式文件
  10. 森林防火无线监控系统解决方案