找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

帖子
查看: 3035|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)PID控制的制動(dòng)能量回收系統(tǒng)程序與仿真設(shè)計(jì)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
內(nèi)含PID控制、AD轉(zhuǎn)換、12864顯示、電機(jī)測(cè)速、控制邏輯程序
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機(jī)源程序如下:
  1. #include <MOTOR.h>
  2. #include <ADC.h>
  3. unsigned int PWM=0;  //pwm占空比為50%,可調(diào)占空比
  4. unsigned int   D;        
  5. unsigned char time = 0;
  6. uchar targetM=0,factM=0;


  7. //PID定義
  8. int out = 0;
  9. int e, e1, e2;//pid 偏差
  10. float uk=0, uk1=0, duk=0;//pid輸出值
  11. float Kp = 0.1, Ki = 0.05, Kd = 0.016;//pid控制系數(shù)        10,12,1.5
  12. uint Inpluse = 0, num1 = 0;
  13. unsigned int time1 = 0;


  14. //-------------------------------
  15. //外部中斷0程序-測(cè)速用的
  16. //-------------------------------
  17. void int0() interrupt 0
  18. {
  19.         Inpluse++;

  20. }


  21. //-------------------------------
  22. // PID
  23. //-------------------------------
  24. void PIDControl()        //pid偏差計(jì)算
  25. {
  26.         e = targetM - factM;
  27.         duk = (Kp*(e - e1) + Ki * e + Kd * (e - 2 * e1 + e2));
  28.         uk = uk1 + duk;
  29.         out = (int)uk;
  30.         if (out > 100)
  31.         {
  32.                 out = 100;
  33.         }
  34.         else if (out < 0)
  35.         {
  36.                 out = 0;
  37.         }
  38.         uk1 = uk;
  39.         e2 = e1;
  40.         e1 = e;
  41.         D = out;
  42. }


  43. //-------------------------------
  44. // 定時(shí)器、中斷初始化
  45. //-------------------------------
  46. void TimeInit()
  47. {
  48.         TMOD = 0X01;        //定時(shí)器工作在方式1(16位定時(shí)器)
  49.         TH0 = 0XFF;                //12M晶振下定時(shí)0.1ms   65536-65436
  50. //        TL0 = 0X9c;
  51.     TL0 = 0Xc6;                //實(shí)驗(yàn)


  52.         ET0 = 1;

  53.         TR0 = 1;                        //開(kāi)啟定時(shí)器

  54.         EX0 = 1;  //中斷0允許         
  55.         IT0 = 1;  //邊沿觸發(fā)
  56.          EA = 1;
  57.         INT = 1;
  58.         e = 0;
  59.         e1 = 0;
  60.         e2 = 0;
  61.         IN01=0;
  62. }
復(fù)制代碼

  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include <LCD12864.h>
  4. #include <ADC.h>
  5. #include <WORDMODEL.h>
  6. #include <MOTOR.h>
  7. #define uint unsigned int
  8. #define uchar unsigned char
  9. #include <string.h>

  10. uchar SOC = 0, V = 0, VOLT = 0;





  11. //SOC
  12. void display0()
  13. {

  14.         SOC = vol*100/255;
  15.         temp0 = SOC / 100;
  16.         temp1 = (SOC % 100) / 10;
  17.         temp2 = SOC % 10;
  18.         show_ch1(1, 0, 4 * 6, ch1 + (12 * (temp0 + 4)));
  19.         show_ch1(1, 0, 5 * 6, ch1 + (12 * (temp1 + 4)));
  20.         show_ch1(1, 0, 6 * 6, ch1 + (12 * (temp2 + 4)));
  21. }

  22. //車速
  23. void display1()
  24. {

  25.         V = vol * 192 / 255;
  26.         temp0 = V / 100;
  27.         temp1 = (V % 100) / 10;
  28.         temp2 = V % 10;
  29.         show_ch1(2, 0, 3 * 6, ch1 + (12 * (temp0 + 4)));
  30.         show_ch1(2, 0, 4 * 6, ch1 + (12 * (temp1 + 4)));
  31.         show_ch1(2, 0, 5 * 6, ch1 + (12 * (temp2 + 4)));
  32. }

  33. //電池電壓
  34. void display2()
  35. {

  36.         VOLT = vol * 400 / 255;
  37.         temp0 = VOLT / 100;
  38.         temp1 = (VOLT % 100) / 10;
  39.         temp2 = VOLT % 10;
  40.         show_ch1(2, 2, 0 * 6, ch1 + (12 * (temp0 + 4)));
  41.         show_ch1(2, 2, 1 * 6, ch1 + (12 * (temp1 + 4)));
  42.         show_ch1(2, 2, 2 * 6, ch1 + (12 * (temp2 + 4)));
  43. }

  44. //目標(biāo)制動(dòng)力矩
  45. void display3()
  46. {
  47.         targetM = vol * 200 / 255;
  48.         D= vol * 100 / 255;
  49.         temp0 = targetM / 100;
  50.         temp1 = (targetM % 100) / 10;
  51.         temp2 = targetM % 10;
  52.         show_ch1(2, 4, 3 * 6, ch1 + (12 * (temp0 + 4)));
  53.         show_ch1(2, 4, 4 * 6, ch1 + (12 * (temp1 + 4)));
  54.         show_ch1(2, 4, 5 * 6, ch1 + (12 * (temp2 + 4)));

  55. }

  56. //實(shí)際制動(dòng)力矩
  57. void display4()
  58. {
  59. //        val=100;
  60.     factM=num1/5        ;
  61. //        val = vol * 192 / 255;
  62.         temp0 = factM / 100;
  63.         temp1 = (factM % 100) / 10;
  64.         temp2 = factM % 10;
  65.         show_ch1(2, 6, 3 * 6, ch1 + (12 * (temp0 + 4)));
  66.         show_ch1(2, 6, 4 * 6, ch1 + (12 * (temp1 + 4)));
  67.         show_ch1(2, 6, 5 * 6, ch1 + (12 * (temp2 + 4)));
  68. }



  69. void main()
  70. {

  71.         InitLCD();
  72.         TimeInit();
  73.         ClearScreen(0);
  74.         Set_line(0);
  75. //SOC顯示        
  76.         show_ch1(1,0,0*6,ch1+12*1);
  77.         show_ch1(1,0,1*6,ch1+12*2);
  78.         show_ch1(1,0,2*6,ch1+12*3);
  79.         show_ch1(1, 0, 3 * 6, ch1 + 12 * 0);
  80.         show_ch1(1, 0, 7 * 6, ch1 + 12 * 14);
  81. //車速顯示
  82.         show_ch2(1, 0, 52, ch2 + 24 * 6);
  83.         show_ch2(2, 0, 0 * 12, ch2 + 24 * 7);
  84.         show_ch1(2, 0, 1 * 12, ch1 + 12 * 0);
  85.         show_ch1(2, 0, 6*6, ch1 + 12 * 15);
  86.         show_ch1(2, 0, 6 * 7, ch1 + 12 * 16);
  87.         show_ch1(2, 0, 6 * 8, ch1 + 12 * 17);
  88.         show_ch1(2, 0, 6 * 9, ch1 + 12 * 18);

  89. //電池電壓顯示
  90.         show_ch2(1, 2, 0 * 14, ch2 + 24 * 12);
  91.         show_ch2(1, 2, 1 * 14, ch2 + 24 * 13);
  92.         show_ch2(1, 2, 2 * 14, ch2 + 24 * 14);
  93.         show_ch2(1, 2, 3 * 14, ch2 + 24 * 15);
  94.         show_ch1(1, 2, 4 * 14, ch1 + 12 * 0);
  95.         show_ch1(2, 2, 6 * 3, ch1 + 12 * 21);

  96. //目標(biāo)制動(dòng)力矩顯示        

  97.         show_ch2(1, 4, 0, ch2 + 24 * 0);
  98.         show_ch2(1, 4, 13, ch2 + 24 * 1);
  99.         show_ch2(1, 4, 26, ch2 + 24 * 2);
  100.         show_ch2(1, 4, 39, ch2 + 24 * 3);
  101.         show_ch2(1, 4, 52, ch2 + 24 * 4);
  102.         show_ch2(2, 4, 0 * 12, ch2 + 24 * 5);
  103.         show_ch1(2, 4, 1 * 12, ch1 + 12 * 0);
  104.         show_ch1(2, 4, 6 * 6, ch1 + 12 * 19);
  105.         show_ch1(2, 4, 7 * 6, ch1 + 12 * 20);
  106. //實(shí)際制動(dòng)力矩顯示        

  107.         show_ch2(1, 6, 0 , ch2 + 24 * 16);
  108.         show_ch2(1, 6, 13, ch2 + 24 * 17);
  109.         show_ch2(1, 6, 26, ch2 + 24 * 2);
  110.         show_ch2(1, 6, 39, ch2 + 24 * 3);
  111.         show_ch2(1, 6, 52, ch2 + 24 * 4);
  112.         show_ch2(2, 6, 0 * 12, ch2 + 24 * 5);
  113.         show_ch1(2, 6, 1 * 12, ch1 + 12 * 0);
  114.         show_ch1(2, 6, 6 * 6, ch1 + 12 * 19);
  115.         show_ch1(2, 6, 7 * 6, ch1 + 12 * 20);
  116.         

  117.         while(1)
  118.         {
  119.         ADDA=0;
  120.         ADDB=0;
  121.         ADDC=0;
  122.         adc();
  123.         display0();
  124.         
  125.         ADDA=1;
  126.         adc();
  127.         display1();
  128.         
  129.         ADDA=0;
  130.         ADDB=1;
  131.         adc();
  132.         display2();
  133.                
  134.         ADDA=1;
  135.         adc();
  136.         display3();

  137.         if (SOC>95)
  138.         {
  139.         targetM = 0;
  140.         }

  141.         if (V <20)
  142.         {
  143.                 targetM = 0;
  144.         }

  145.         if (VOLT > 390)
  146.         {
  147.                 targetM = 0;
  148.         }
  149.         if (targetM > 150)
  150.         {
  151.                 targetM = 0;
  152.         }
  153.         else if(targetM > 100)
  154.         {
  155.                 targetM = targetM*0.5;
  156.         }
  157.          
  158.     if (time1 > 100)
  159.           {
  160.                   time1 = 0;
  161.                   num1 = Inpluse*103/27 ;
  162.                   Inpluse = 0;
  163.                   PIDControl();
  164.                   PWM =D;
  165.           }
  166.      display4();
  167.          

  168.         }
  169. }

  170. //-------------------------------
  171. //定時(shí)器0
  172. //-------------------------------
  173. void Timer0(void) interrupt 1
  174. {
  175.         
  176. //        TH0 = 0XFF;                //重裝初值
  177. //        TL0 = 0X9c;                //標(biāo)準(zhǔn)值
  178. //        TL0 = 0Xb8;                //包含誤差
  179.     TH0=0XFF;
  180.         TL0=0X37;
  181.         time++;
  182.         if (time >= 100)        //PWM周期為100*0.1ms
  183.                 time = 0;
  184.         if (time < PWM)
  185.                 IN01 = 1;
  186.         else
  187.                 IN01 = 0;
  188.         time1++;  //轉(zhuǎn)速測(cè)量周期
  189. }
復(fù)制代碼

所有資料51hei提供下載(Proteus請(qǐng)使用7.5版本):
仿真、主程序.zip (115.49 KB, 下載次數(shù): 26)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏5 分享淘帖 頂1 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:542563 發(fā)表于 2021-4-21 09:14 | 只看該作者
SOC居然是個(gè)模擬量?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表