久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1417|回復: 0
打印 上一主題 下一主題
收起左側

基于51單片機PID算法控制電機轉速程序Proteus仿真圖

[復制鏈接]
跳轉到指定樓層
樓主
一個用51單片機實現2個電機pid調速的源程序,Proteus仿真的版本是8.17,只能用新版打開,電路原理圖在帖子最后
單片機源程序如下:
  1. #include<reg52.h>
  2. #include"lcd1602.h"
  3. #include"delay.h"
  4. sfr T2MOD = 0x0c9;
  5. #define uchar unsigned char
  6. #define uint unsigned int

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

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

  17. uint tuint = 65535;
  18. uint tpwm = 1;    //pwm周期為10000us tpwm變量表示pwm高電平時間,也相當于占空比 (仿真時,頻率高時,電機反應慢。在實物上要加大頻率)
  19. uchar t1_flag = 0;

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


  25. #define     ZZ         { Q0 = 0;Q1 = 0;Q2 = 1;Q3 = 1;}    //正轉
  26. #define     FZ         { Q0 = 1;Q1 = 1;Q2 = 0;Q3 = 0;}    //反轉
  27. #define     STOP    { Q0 = 1;Q1 = 0;Q2 = 1;Q3 = 0;}    //停止
  28. //禁止出現 Q0 = 0;Q1 = 1;Q2 = 0;Q3 = 1; 不然會燒掉mos管

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

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

  37. //*****************************************************************

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

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

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

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

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

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

  162. int PID2()        //位置式PID
  163. {
  164.    
  165.     int num = 0;
  166.     static num_bef = 0;
  167.    
  168.     err_now = set - now;
  169.     err_bef = set - bef;
  170.    
  171.     error_add = error_add + err_now;  //誤差累加。一旦誤差為0則error_add的值不變,PID輸出值不變

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

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

  288.     }
  289.    
  290. }
復制代碼

屏幕截圖 2024-06-07 124527.png (122.89 KB, 下載次數: 30)

上下電機pid調節

上下電機pid調節

屏幕截圖 2024-06-07 124546.png (123.02 KB, 下載次數: 26)

左右電機pid調節

左右電機pid調節

Proteus8.17版本的仿真程序.7z

212.97 KB, 下載次數: 23, 下載積分: 黑幣 -5

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久毛片网站 | 国产精品影视在线观看 | 日韩精品一区二区三区高清免费 | 久久久久久成人 | 看av片网站 | 成人免费视频播放 | 精品久久久一区二区 | 国产区在线观看 | 久久99一区二区 | 男人天堂手机在线视频 | 精品久久久一区二区 | 国产视频一区二区 | 成人精品久久 | 亚洲美女一区二区三区 | 天天久 | aaaaaa大片免费看最大的 | 欧美精品成人一区二区三区四区 | 国产一区二区在线免费观看 | 亚洲视频一区二区三区 | aⅴ色国产 欧美 | 成人1区2区 | 91视频在线看 | 国产一区二区精品在线观看 | 一级片片 | 国产情侣久久 | 国产成人综合av | 一级片在线视频 | 国产成人一区 | h视频免费在线观看 | 日韩精品一区二区三区第95 | 国产精品乱码一区二三区小蝌蚪 | 久久久欧洲| 亚洲国产黄 | 免费观看一级毛片 | 毛片入口| 国产视频91在线 | 欧美综合国产精品久久丁香 | 一级欧美黄色片 | 国产大片黄色 | 毛片免费视频 | 成人免费网站www网站高清 |