单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
上一页
1/3
下一页
查看:33959|回复:91

单片机用PID算法控制直流电机转速 源代码+仿真 成功版

 [复制链接]
ID:207635发表于 2017-6-4 12:35|显示全部楼层
使用51单片机用PID算法来控制直流电机的转速.带有3个按钮 切换电机转动方向,调节p,调节转速.测试已经成功

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载):
0.png
0.png
0.png

单片机源程序如下:
  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 PWM           = P1^7;
  11. sbit UP               = P1^0;
  12. sbit DOWM           = P1^1;
  13. sbit GORB         = P2^3; //换相
  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. ……………………

  247. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
PID算法控制电机转速.rar(100.25 KB, 下载次数: 1192)

评分

黑币 +13
收起理由
+ 2
赞一个!
stu
+ 1
很给力!
+ 5
学习到知识
+ 5
很给力!

查看全部评分

ID:1发表于 2017-6-4 16:33|显示全部楼层
好资料,51黑有你更精彩!!!
ID:177855发表于 2017-6-4 17:39|显示全部楼层
不懂,下来慢慢学
ID:226086发表于 2017-8-9 14:09|显示全部楼层
很好,学习一下!
ID:122686发表于 2017-9-3 14:24|显示全部楼层
不错加油
ID:239382发表于 2017-10-15 00:21|显示全部楼层
棒棒哒
ID:210141发表于 2017-10-15 11:27来自手机|显示全部楼层
慢慢学习一下
ID:239623发表于 2017-10-15 14:21|显示全部楼层
nice   好大拇指
ID:239382发表于 2017-10-15 22:22|显示全部楼层
请问lcd显示屏上的p值是什么用途呢?
ID:125901发表于 2017-10-17 01:00来自手机|显示全部楼层
努力学习学习
ID:243861发表于 2017-10-29 15:49|显示全部楼层
P值是什么
ID:252056发表于 2017-11-21 20:55|显示全部楼层
谢谢分享   好
ID:262605发表于 2017-12-17 11:50|显示全部楼层
谢谢分享谢谢分享谢谢分享
ID:262605发表于 2017-12-17 11:53|显示全部楼层
谢谢分享
ID:262605发表于 2017-12-17 14:23|显示全部楼层
看看
谢谢分享  
ID:262988发表于 2017-12-18 10:11|显示全部楼层
正在做直流电机控制,学习下
ID:262988发表于 2017-12-18 10:12|显示全部楼层
额,没币,下起不了
ID:44165发表于 2018-3-13 23:22|显示全部楼层

好资料,51黑有你更精彩!!!
ID:302760发表于 2018-4-6 18:13|显示全部楼层
学习一下
ID:250045发表于 2018-4-12 11:54|显示全部楼层
很好的资料,刚好最近在做这个。
ID:311523发表于 2018-4-19 11:04|显示全部楼层
谢谢分享
ID:324603发表于 2018-5-7 22:01|显示全部楼层
谢谢分享
ID:326595发表于 2018-5-10 10:35|显示全部楼层
非常感谢,新手入门,很有用
ID:336452发表于 2018-5-23 14:24|显示全部楼层
谢谢楼主
ID:197331发表于 2018-6-6 18:47|显示全部楼层
不错,值得学习
ID:344257发表于 2018-6-6 21:09|显示全部楼层
这个源代码直接放到keil里面编译,是有警告的啊?
ID:356219发表于 2018-6-21 17:04|显示全部楼层
谢谢哈哈
ID:358826发表于 2018-6-25 21:12|显示全部楼层
下来慢慢学
ID:293560发表于 2018-7-13 10:53|显示全部楼层
pid入坑中
ID:370696发表于 2018-7-13 11:55|显示全部楼层
谢谢分享
ID:371038发表于 2018-7-13 17:06|显示全部楼层
非常好
ID:371504发表于 2018-7-14 15:09|显示全部楼层
值得学习
ID:339697发表于 2018-8-19 07:49|显示全部楼层
很想试试看
ID:398044发表于 2018-9-14 17:14|显示全部楼层
很想试试看
ID:402275发表于 2018-10-10 17:43|显示全部楼层
感谢大佬
ID:405059发表于 2018-10-13 09:46|显示全部楼层
第一次用PID算法来控制,文件里位置式和增量式都涉及到了,很详细
ID:432291发表于 2018-11-24 11:50|显示全部楼层
正好,试着做做
ID:452353发表于 2018-12-22 21:47|显示全部楼层
谢谢楼主分享
ID:452376发表于 2018-12-22 22:24|显示全部楼层
努力学习亚
ID:450877发表于 2018-12-22 22:28|显示全部楼层
好帖子,试试做

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

Powered by 单片机教程网