找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 27678|回复: 51
收起左侧

PID算法控制电机转速 仿真及程序

  [复制链接]
ID:121330 发表于 2016-5-19 23:11 | 显示全部楼层 |阅读模式
有需要的朋友可以看看额,51单片机PID算法的控制电机转速而且有仿真和源程序哦

0.png

pid算法来控制电机转速的源程序(全部代码请下载附件):
  1. #include <reg52.h>
  2. #include "lcd1602.h"

  3. sfr T2MOD = 0x0c9;
  4. #define uchar unsigned char
  5. #define uint unsigned int

  6. sbit Q0 = P2^4;
  7. sbit Q1 = P2^5;
  8. sbit Q2 = P2^6;
  9. sbit Q3 = P2^7;

  10. sbit GORB        = P1^6; //换相
  11. sbit PWM = P1^7;
  12. sbit UP        = P1^0;
  13. sbit DOWM        = P1^1;
  14. sbit ADDSPEED = P1^2;
  15. sbit SUBSPEED        = P1^3;

  16. uint tuint = 65535;
  17. uint tpwm = 1;        //pwm周期为10000us tpwm变量表示pwm高电平时间,也相当于占空比 (仿真时,频率高时,电机反应慢。在实物上要加大频率)
  18. uchar t1_flag = 0;

  19. uint pulse = 0;
  20. uint t0_flag = 0;
  21. uchar t2_flag = 0;
  22. bit t2_over = 0;
  23. bit Just_Get = 1;


  24. #define         ZZ                 { Q0 = 0;Q1 = 0;Q2 = 1;Q3 = 1;}        //正转
  25. #define         FZ                 { Q0 = 1;Q1 = 1;Q2 = 0;Q3 = 0;}        //反转
  26. #define         STOP        { Q0 = 1;Q1 = 0;Q2 = 1;Q3 = 0;}        //停止
  27. //禁止出现 Q0 = 0;Q1 = 1;Q2 = 0;Q3 = 1; 不然会烧掉mos管

  28. //************************ PID *************************************
  29. float now = 0,bef = 0,bbef = 0;         //本次采样值,上次采样值,上上次采样值
  30. float err_now,err_bef,err_bbef;                //当前偏差,上次偏差,上上次偏差
  31. float error_add = 0;                                //所有偏差之和
  32. float set = 25;                                                //设定值

  33. float kp = 25;
  34. float ki = 25;
  35. float kd = 0;

  36. //*****************************************************************

  37. void delayms(uint ms)//延时?个 ms
  38. {
  39.     uchar a,b,c;
  40.         while(ms--)
  41.         {
  42.           for(c=1;c>0;c--)
  43.         for(b=142;b>0;b--)
  44.             for(a=2;a>0;a--);
  45.         }
  46. }

  47. void timer_init()
  48. {
  49.         EA = 1;
  50.         ET0 = 1;
  51.         ET1 = 1;
  52.         ET2 = 1;
  53.        
  54.         TMOD = 0x15; //定时器0 计数模式 定时器1模式1
  55.         T2MOD = 0x01;
  56.        
  57.         TH0 = TL0 = 255;
  58.         TH2 = 0x3C;
  59.         TL2 = 0xB0;                //50MS
  60.        
  61. }
  62. void timer1() interrupt 3
  63. {
  64.         if(t1_flag == 0)
  65.         {
  66.                 t1_flag = 1;
  67.                 PWM = 1;
  68.                 TH1 = (tuint - tpwm + 1)/256;
  69.                 TL1 = (tuint - tpwm + 1)%256;
  70.                
  71.         }
  72.         else
  73.         {
  74.                 t1_flag = 0;
  75.                 PWM = 0;
  76.                 TH1 = (tuint - 10000 + tpwm + 1)/256;
  77.                 TL1 = (tuint - 10000 + tpwm + 1)%256;
  78.         }
  79. }

  80. void timer0() interrupt 1
  81. {
  82.         TH0 = TL0 = 255;
  83.         t0_flag++;
  84. }
  85. void timer2() interrupt 5
  86. {
  87.         TF2 = 0;
  88.         TH2 = 0x3C;
  89.         TL2 = 0xB0;                //50MS
  90.        
  91.         t2_flag++;
  92.        
  93.         if(t2_flag == 2)
  94.         {
  95.                 TR0 = 0;
  96.                 TR2 = 0;
  97.                 t2_flag = 0;
  98.                 t2_over = 1;        //表示100ms时间到
  99.         }
  100. }
  101. void GetPulse()
  102. {
  103.         t0_flag = 0;
  104.         t2_flag = 0;
  105.        
  106.         TH0 = TL0 = 255;
  107.         TH2 = 0x3C;
  108.         TL2 = 0xB0;                //50MS
  109.        
  110.         TR0 = 1;
  111.         TR2 = 1;
  112. }

  113. int PID()        //增量式PID
  114. {
  115.         int change;

  116.         err_now = set - now;
  117.         err_bef = set - bef;
  118.         err_bbef = set - bbef;
  119.        
  120.         change = kp*(err_now - err_bef) + ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
  121.        
  122. /*       
  123.         if(set >= now)
  124.         {       
  125.                 if(set - now > 1)
  126.                         change = kp*(err_now - err_bef) + ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
  127.                 else
  128.                         change = 0.2*kp*(err_now - err_bef) + 0.5*ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
  129.         }
  130.         else if(now > set)
  131.         {
  132.                 if(now - set > 1)
  133.                         change = kp*(err_now - err_bef) + ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
  134.                 else
  135.                         change = 0.2*kp*(err_now - err_bef) + 0.5*ki*err_now + kd*(err_now - 2*err_bef + err_bbef);
  136.                        
  137.         }
  138. */
  139.        
  140.         //change = (kp + ki + kd)*(set - now) + (-kp - 2*kd)*(set - bef) + kd*(set - bbef);
  141.         //change = kp*(set - now) + ki*(set - bef) + kd*(set - bbef);
  142.         if(change > 0)
  143.         {
  144.                 printchar(1,10,'+');       
  145.                 printuint(1,11,4,change);
  146.                
  147.         }
  148.         else if(change < 0)
  149.         {       
  150.                 printchar(1,10,'-');
  151.                 printuint(1,11,4,-change);
  152.         }
  153.         else if(change == 0)
  154.         {       
  155.                 printchar(1,10,' ');
  156.                 printword(1,11," 0  ");

  157.         }
  158.        
  159.         return(change);
  160. }

  161. int PID2()                //位置式PID
  162. {
  163.        
  164.         int num = 0;
  165.         static num_bef = 0;
  166.        
  167.         err_now = set - now;
  168.         err_bef = set - bef;
  169.        
  170.         error_add = error_add + err_now;  //误差累加。一旦误差为0则error_add的值不变,PID输出值不变

  171.         num = kp*err_now + ki*error_add + kd*(err_now - err_bef);
  172.        
  173. /*       
  174.         if(set - now >= 0)
  175.         {       
  176.                 if(set - now > 1)
  177.                         num = kp*err_now + ki*error_add + kd*(err_now - err_bef);
  178.                 else
  179.                         num = 0.1*kp*err_now + ki*error_add + kd*(err_now - err_bef);
  180.         }
  181.         else
  182.         {
  183.                 if(now - set > 1)
  184.                         num = kp*err_now + ki*error_add + kd*(err_now - err_bef);
  185.                 else
  186.                         num = 0.1*kp*err_now + ki*error_add + kd*(err_now - err_bef);
  187.                        
  188.         }
  189.         */
  190.        
  191.         if(num > num_bef)
  192.         {
  193.                 printchar(1,10,'+');       
  194.                 printuint(1,11,4,num - num_bef);
  195.         }
  196.         else if(num < num_bef)
  197.         {
  198.                 printchar(1,10,'-');       
  199.                 printuint(1,11,4,num_bef - num);
  200.         }
  201.         else
  202.         {       
  203.                 printchar(1,10,' ');
  204.                 printuint(1,11,4,0);
  205.         }
  206.        
  207.         num_bef = num;
  208.        
  209.         return((uint)num);
  210. }

  211. void main()
  212. {       
  213.        
  214.         lcd_init();
  215.         timer_init();
  216.         TH1 = TL1 = 255;
  217.        
  218.         printword(0,0,"P:");                //比例系数
  219.         printword(0,5,"S:");                //设定值
  220.         printword(1,0,"TPWM:");                //当前占空比
  221.         printword(0,10,"PS:");                //当前电机反馈的每秒脉冲数
  222.        
  223.         while(1)
  224.         {
  225.                 if(GORB == 1)
  226.                 {        ZZ;                }
  227.                 else
  228.                 {        FZ;                }
  229.                
  230.                 if(ADDSPEED == 0)
  231.                         set++;
  232.                 if(SUBSPEED == 0)
  233.                         set--;
  234.                
  235.                 if(Just_Get == 1)
  236.                 {       
  237.                         Just_Get = 0;
  238.                         GetPulse();
  239.                 }
  240.                 else if(t2_over == 1)
  241.                 {       
  242.                         t2_over = 0;
  243.                         Just_Get = 1;
  244.                         pulse = t0_flag;
  245.                         bbef = bef;
  246.                         bef = now;
  247.                         now = t0_flag;
  248.                        
  249.                         if(set != 0)
  250.                         {
  251.                                 TR1 = 1;
  252.                         }
  253.                         else
  254.                         {
  255.                                 TR1 = 0;
  256.                                 PWM = 0;
  257.                         }
  258.                        
  259.                 //        tpwm = tpwm + PID();                //增量式PID
  260.                         tpwm = PID2();                                //位置式PID
  261.                                        
  262.                 }
  263.                
  264.                 if(UP == 0)
  265.                         kp = kp + 1;
  266.                 if(DOWM == 0)
  267.                         kp = kp - 1;
  268.                
  269.                 printuint(0,2,3,kp);
  270.                 printuint(0,7,3,set);
  271.                 printuint(1,5,4,tpwm);
  272.                 printuint(0,13,5,pulse);

  273.         }
  274.        
  275. }
  276.        
复制代码
电机控制的压缩包
0.png

所有资料下载: PID算法控制电机转速.rar (90.37 KB, 下载次数: 713)

评分

参与人数 10黑币 +83 收起 理由
chb704125391 + 1 很给力!
lttle + 1 很给力!
骁勇阿凯 + 1 很给力!
yufewng + 5 很给力!
你可往后稍稍 + 5
youmu + 5 很给力!
mook陌 + 5 不错
hxj + 5 赞一个!
e心r意 + 5 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:220927 发表于 2018-1-26 17:42 | 显示全部楼层
大神基于的例程对代码进行了改写,删了反馈计数的中断服务,例程的仿真资源占用由原来的60%~80%降到20%~35%,对PID算法入门真是一个相当好的例程
回复

使用道具 举报

ID:220927 发表于 2018-1-26 17:44 | 显示全部楼层
http://www.51hei.com/bbs/dpj-106379-1.html
这是我优化大神例程的连接地址,欢迎访问下载

评分

参与人数 1黑币 +80 收起 理由
admin + 80 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:146550 发表于 2016-11-7 10:14 | 显示全部楼层
好用  帮了我很大的忙
回复

使用道具 举报

ID:158112 发表于 2017-3-9 23:33 | 显示全部楼层
下载看看  应该有用吧    快没有积分下载了 。。。。。。。。
回复

使用道具 举报

ID:186870 发表于 2017-4-19 19:57 | 显示全部楼层
谢谢
回复

使用道具 举报

ID:197528 发表于 2017-5-8 18:20 | 显示全部楼层
楼主好人
回复

使用道具 举报

ID:167458 发表于 2017-5-9 17:23 | 显示全部楼层
谢谢你的分享 真的感谢!
回复

使用道具 举报

ID:167458 发表于 2017-5-9 17:24 | 显示全部楼层
谢谢你的分享  真的感谢!
回复

使用道具 举报

ID:159139 发表于 2017-5-10 16:03 来自手机 | 显示全部楼层
谢谢分享正研究中。
回复

使用道具 举报

ID:204735 发表于 2017-5-26 11:54 来自手机 | 显示全部楼层
程序出错,怎么解决#include "lcd1602.h"出现的问题
回复

使用道具 举报

ID:204735 发表于 2017-5-26 12:25 来自手机 | 显示全部楼层
#include "lcd1602.h"无法打开是什么情况,大神求解
回复

使用道具 举报

ID:205767 发表于 2017-5-29 11:28 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:207095 发表于 2017-6-2 15:37 | 显示全部楼层
程序都运行了 但是里面的各个按键都是干嘛的啊
回复

使用道具 举报

ID:207095 发表于 2017-6-2 15:39 | 显示全部楼层
有没有视频讲解?
回复

使用道具 举报

ID:207095 发表于 2017-6-2 15:40 | 显示全部楼层
楼主  有视频讲解吗?   显示出来的波形图中的按键都不知道什么意思
回复

使用道具 举报

ID:207095 发表于 2017-6-2 15:41 | 显示全部楼层
波形图中的按键都不知道是什么意思
回复

使用道具 举报

ID:94511 发表于 2017-7-3 14:43 | 显示全部楼层
研究中
回复

使用道具 举报

ID:183655 发表于 2017-7-7 11:19 | 显示全部楼层
厉害了我的哥
回复

使用道具 举报

ID:198530 发表于 2017-7-8 14:02 来自手机 | 显示全部楼层
可以可以,很不错
回复

使用道具 举报

ID:183120 发表于 2017-7-13 19:44 | 显示全部楼层
看了挺牛的,可程序通过不了
回复

使用道具 举报

ID:219500 发表于 2017-7-22 21:00 | 显示全部楼层
学习学习
回复

使用道具 举报

ID:221677 发表于 2017-7-22 21:48 | 显示全部楼层
好资料
回复

使用道具 举报

ID:110278 发表于 2017-7-23 16:06 | 显示全部楼层
没有积分下载了。
回复

使用道具 举报

ID:223470 发表于 2017-7-31 08:35 | 显示全部楼层
黑币不够,楼主顶你啊
回复

使用道具 举报

ID:110278 发表于 2017-8-6 11:10 | 显示全部楼层
很不错。。。
回复

使用道具 举报

ID:257829 发表于 2017-12-10 13:54 | 显示全部楼层
满意,非常满意
回复

使用道具 举报

ID:262605 发表于 2017-12-18 16:34 | 显示全部楼层
没有积分下载
回复

使用道具 举报

ID:44165 发表于 2018-3-13 23:46 | 显示全部楼层

学习学习
回复

使用道具 举报

ID:244217 发表于 2018-3-26 21:51 | 显示全部楼层
PID电机控制给力、谢谢分享
回复

使用道具 举报

ID:292673 发表于 2018-4-3 09:36 | 显示全部楼层
好贴,自己看了温控的PID表示数据指针看不懂

回复

使用道具 举报

ID:301413 发表于 2018-4-3 12:40 | 显示全部楼层
学习学习
回复

使用道具 举报

ID:292009 发表于 2018-4-4 00:48 来自手机 | 显示全部楼层
我觉得这个程序没有实现闭关反馈。都没有用到反馈值!!!
回复

使用道具 举报

ID:326997 发表于 2018-5-10 17:17 | 显示全部楼层
大神啊
回复

使用道具 举报

ID:336452 发表于 2018-5-23 21:17 | 显示全部楼层
P调节没什么变化啊  不太懂这个作用
回复

使用道具 举报

ID:340655 发表于 2018-5-29 15:52 | 显示全部楼层
值得学习
回复

使用道具 举报

ID:69057 发表于 2018-5-30 15:17 | 显示全部楼层
为大虾赞一个,最近也在研究PID
回复

使用道具 举报

ID:353241 发表于 2018-6-17 14:01 | 显示全部楼层
不错,好好,学习学习~
回复

使用道具 举报

ID:359327 发表于 2018-6-26 14:58 | 显示全部楼层
正需要,资料很好
回复

使用道具 举报

ID:359327 发表于 2018-6-26 14:59 | 显示全部楼层
正需要这方面的资料
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表