標(biāo)題: 單片機(jī)用PID算法控制直流電機(jī)轉(zhuǎn)速 源代碼+仿真 成功版 [打印本頁(yè)]

作者: kk民    時(shí)間: 2017-6-4 12:35
標(biāo)題: 單片機(jī)用PID算法控制直流電機(jī)轉(zhuǎn)速 源代碼+仿真 成功版
使用51單片機(jī)用PID算法來控制直流電機(jī)的轉(zhuǎn)速.帶有3個(gè)按鈕 切換電機(jī)轉(zhuǎn)動(dòng)方向,調(diào)節(jié)p,調(diào)節(jié)轉(zhuǎn)速.測(cè)試已經(jīng)成功

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載):


單片機(jī)源程序如下:
  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高電平時(shí)間,也相當(dāng)于占空比 (仿真時(shí),頻率高時(shí),電機(jī)反應(yīng)慢。在實(shí)物上要加大頻率)
  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;}        //正轉(zhuǎn)
  25. #define         FZ                 { Q0 = 1;Q1 = 1;Q2 = 0;Q3 = 0;}        //反轉(zhuǎn)
  26. #define         STOP        { Q0 = 1;Q1 = 0;Q2 = 1;Q3 = 0;}        //停止
  27. //禁止出現(xiàn) Q0 = 0;Q1 = 1;Q2 = 0;Q3 = 1; 不然會(huì)燒掉mos管

  28. //************************ PID *************************************
  29. float now = 0,bef = 0,bbef = 0;         //本次采樣值,上次采樣值,上上次采樣值
  30. float err_now,err_bef,err_bbef;                //當(dāng)前偏差,上次偏差,上上次偏差
  31. float error_add = 0;                                //所有偏差之和
  32. float set = 25;                                                //設(shè)定值

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

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

  37. void delayms(uint ms)//延時(shí)?個(gè) 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; //定時(shí)器0 計(jì)數(shù)模式 定時(shí)器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時(shí)間到
  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:");                //比例系數(shù)
  219.         printword(0,5,"S:");                //設(shè)定值
  220.         printword(1,0,"TPWM:");                //當(dāng)前占空比
  221.         printword(0,10,"PS:");                //當(dāng)前電機(jī)反饋的每秒脈沖數(shù)
  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. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
PID算法控制電機(jī)轉(zhuǎn)速.rar (100.25 KB, 下載次數(shù): 1239)



作者: admin    時(shí)間: 2017-6-4 16:33
好資料,51黑有你更精彩!!!
作者: qjyjack612510    時(shí)間: 2017-6-4 17:39
不懂,下來慢慢學(xué)
作者: kevin110125    時(shí)間: 2017-8-9 14:09
很好,學(xué)習(xí)一下!
作者: a77303383    時(shí)間: 2017-9-3 14:24
不錯(cuò)加油
作者: 別人沒有的名字    時(shí)間: 2017-10-15 00:21
棒棒噠

作者: 陸地巡洋艦    時(shí)間: 2017-10-15 11:27
慢慢學(xué)習(xí)一下
作者: 1633278314wl    時(shí)間: 2017-10-15 14:21
nice   好大拇指
作者: 別人沒有的名字    時(shí)間: 2017-10-15 22:22
請(qǐng)問lcd顯示屏上的p值是什么用途呢?
作者: lhf211185    時(shí)間: 2017-10-17 01:00
努力學(xué)習(xí)學(xué)習(xí)
作者: 夏天xx    時(shí)間: 2017-10-29 15:49
P值是什么

作者: wuyanzuzzz    時(shí)間: 2017-11-21 20:55
謝謝分享    好
作者: peigang123    時(shí)間: 2017-12-17 11:50
謝謝分享謝謝分享謝謝分享
作者: peigang123    時(shí)間: 2017-12-17 11:53
謝謝分享

作者: peigang123    時(shí)間: 2017-12-17 14:23
看看
謝謝分享  
作者: sinolover    時(shí)間: 2017-12-18 10:11
正在做直流電機(jī)控制,學(xué)習(xí)下
作者: sinolover    時(shí)間: 2017-12-18 10:12
額,沒幣,下起不了
作者: aaaa_7777    時(shí)間: 2018-3-13 23:22

好資料,51黑有你更精彩!!!
作者: goldbr    時(shí)間: 2018-4-6 18:13
學(xué)習(xí)一下
作者: hllt    時(shí)間: 2018-4-12 11:54
很好的資料,剛好最近在做這個(gè)。
作者: coldwindhot    時(shí)間: 2018-4-19 11:04
謝謝分享

作者: 2333admin    時(shí)間: 2018-5-7 22:01
謝謝分享
作者: zh_silence    時(shí)間: 2018-5-10 10:35
非常感謝,新手入門,很有用
作者: HEARD    時(shí)間: 2018-5-23 14:24
謝謝樓主
作者: zhanggaochina    時(shí)間: 2018-6-6 18:47
不錯(cuò),值得學(xué)習(xí)
作者: combathyl    時(shí)間: 2018-6-6 21:09
這個(gè)源代碼直接放到keil里面編譯,是有警告的啊?
作者: q86346643    時(shí)間: 2018-6-21 17:04
謝謝哈哈
作者: 電子菜鳥啊    時(shí)間: 2018-6-25 21:12
下來慢慢學(xué)

作者: 小阿哈    時(shí)間: 2018-7-13 10:53
pid入坑中
作者: 123feng    時(shí)間: 2018-7-13 11:55
謝謝分享
作者: lm1720755472    時(shí)間: 2018-7-13 17:06
非常好
作者: 只為學(xué)習(xí)到一點(diǎn)    時(shí)間: 2018-7-14 15:09
值得學(xué)習(xí)
作者: 23932209    時(shí)間: 2018-8-19 07:49
很想試試看
作者: cjztiger    時(shí)間: 2018-9-14 17:14
很想試試看
作者: kikko    時(shí)間: 2018-10-10 17:43
感謝大佬
作者: xxz1061018609    時(shí)間: 2018-10-13 09:46
第一次用PID算法來控制,文件里位置式和增量式都涉及到了,很詳細(xì)
作者: linyou    時(shí)間: 2018-11-24 11:50
正好,試著做做

作者: brycew    時(shí)間: 2018-12-22 21:47
謝謝樓主分享
作者: wlee    時(shí)間: 2018-12-22 22:24
努力學(xué)習(xí)亞
作者: jmy11    時(shí)間: 2018-12-22 22:28
好帖子,試試做
作者: 楊柳青    時(shí)間: 2019-1-4 21:51
厲害!
作者: xode    時(shí)間: 2019-1-4 23:51
謝謝分享
作者: 伯爵默默    時(shí)間: 2019-1-12 14:55
東西很不錯(cuò)
作者: nipingbo    時(shí)間: 2019-2-11 13:28
東西很不錯(cuò)

作者: nipingbo    時(shí)間: 2019-2-11 13:28
東西很不錯(cuò)

作者: 1172047001    時(shí)間: 2019-2-12 13:06
很給力!
作者: 648025666    時(shí)間: 2019-3-19 18:08
非常感謝,新手入門
作者: lyy001    時(shí)間: 2019-3-29 15:34
好資料,51黑有你更精彩!!!
作者: lyy001    時(shí)間: 2019-3-29 16:51
第一次用PID算法來控制,文件里位置式和增量式都涉及到了,很詳細(xì)
作者: yll1995    時(shí)間: 2019-3-29 18:11
很好,謝謝樓主
作者: 923975623    時(shí)間: 2019-4-22 19:36
贊 很有用
作者: 蝶舞狂雷    時(shí)間: 2019-5-5 09:34
謝謝分享
作者: qxl1997119    時(shí)間: 2019-5-5 12:30
棒棒噠
作者: 13327291097    時(shí)間: 2019-5-5 14:42
好資料,51黑有你更精彩!!!
作者: machenshuo    時(shí)間: 2019-5-6 17:48
從圖上看,電機(jī)和單片機(jī)的輸入電壓一樣,可以不一樣嗎?
作者: machenshuo    時(shí)間: 2019-5-6 20:30
附件在哪??
作者: 胡旭飛飛飛飛    時(shí)間: 2019-5-9 16:31
這個(gè)讓我學(xué)到了很多!
作者: timelesszn    時(shí)間: 2019-5-24 14:13
很好,很牛逼啊
作者: 2632960016    時(shí)間: 2019-5-31 11:14
新手入門先保存下來

作者: Jazz-HipHop    時(shí)間: 2019-6-24 13:10
正在做這個(gè),感謝
作者: 825673316    時(shí)間: 2019-6-27 22:45
非常期待,希望是好的
作者: 陳小曉    時(shí)間: 2019-7-29 20:54
注釋也太少了點(diǎn)吧,理解起來有點(diǎn)困難
作者: hht805656153    時(shí)間: 2019-7-30 17:49
好資料,51黑有你更精彩!!!
作者: sym111    時(shí)間: 2019-7-31 08:00

謝謝分享
作者: 花名張清    時(shí)間: 2019-7-31 09:16
好資料,51黑有你更精彩!!!
作者: meng666meng    時(shí)間: 2019-8-2 11:08
很不錯(cuò)的貼,可是想下載積分不夠
作者: 小蘿卜頭    時(shí)間: 2019-8-2 16:26
給力啊,今天剛學(xué)到PID
作者: china043    時(shí)間: 2019-8-5 10:23
不錯(cuò)加油
作者: zhangsl168    時(shí)間: 2019-8-5 16:56
真是高人很多啊,原來這個(gè)也可做��!
作者: JTR2017    時(shí)間: 2019-9-18 16:11
灰常感謝
作者: 劉繼智    時(shí)間: 2019-10-3 15:58
想要學(xué)知識(shí),麻煩給一個(gè)吧
作者: mmmaaaxxx    時(shí)間: 2019-11-12 18:15
謝謝分享    好
作者: 阿斯頓發(fā)生    時(shí)間: 2019-11-14 19:04
贊一個(gè)!
作者: hj08102    時(shí)間: 2020-2-28 12:11
很詳細(xì)的代碼,下載實(shí)驗(yàn)下,謝謝樓主分享
作者: yoghourt    時(shí)間: 2020-2-28 14:38
非常實(shí)用,謝謝
作者: sinolover    時(shí)間: 2020-3-17 17:03
我自己弄的,一直不理想
作者: 15649862501    時(shí)間: 2020-3-22 17:05
謝謝分享
作者: 2794446011    時(shí)間: 2020-4-2 14:47
先Mark
作者: sance    時(shí)間: 2020-4-25 09:16
感謝分享 感謝
作者: 15245340616    時(shí)間: 2020-6-26 17:57
謝謝分享
作者: Jeff_BlindCat    時(shí)間: 2020-6-26 23:20
好資料,謝謝樓主分享。
作者: ygw911651    時(shí)間: 2020-7-27 19:33
proteus的文件沒有啊
作者: 周11    時(shí)間: 2020-8-11 23:37
這個(gè)是用52的板子嗎
作者: fcc521    時(shí)間: 2020-8-12 14:30
pid里的printchar是自定義的嗎
作者: adsdasfewfwe    時(shí)間: 2020-8-16 17:27
感謝分享,太給力了,這個(gè)好難,還好有你
作者: asuka鳥    時(shí)間: 2020-12-1 15:15

感謝分享,太給力了,這個(gè)好難,還好有你
作者: asuka鳥    時(shí)間: 2020-12-2 08:58
講的很棒
作者: 小啊嘉    時(shí)間: 2024-4-26 01:20

nice   好大拇指
作者: 徐久博    時(shí)間: 2024-4-26 19:50
我下載了·準(zhǔn)備安裝·謝謝分享
作者: ffqx@!68    時(shí)間: 2024-4-28 08:56
看了,真的實(shí)用!
作者: haide1998    時(shí)間: 2024-5-2 20:37
謝謝分享,學(xué)習(xí)了!
作者: 隨風(fēng)飄遠(yuǎn)    時(shí)間: 2024-5-11 10:02
電機(jī)驅(qū)動(dòng)是不是需要濾波電路? 有誰(shuí)了解嗎?
作者: 51heiartist    時(shí)間: 2024-7-20 15:10
是有刷的嗎
作者: sdfbhbk111    時(shí)間: 2024-10-24 08:58
學(xué)到了很多知識(shí)
作者: cuijb    時(shí)間: 2024-10-27 11:00
下管驅(qū)動(dòng)應(yīng)該沒問題,上管驅(qū)動(dòng)能用嗎
作者: jovew    時(shí)間: 2024-10-28 13:46
這個(gè)程序驅(qū)動(dòng)的電機(jī)是步進(jìn)電機(jī)嗎?




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1