找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2435|回复: 1
打印 上一主题 下一主题
收起左侧

单片机PID控制的制动能量回收系统程序与仿真设计

[复制链接]
跳转到指定楼层
楼主
内含PID控制、AD转换、12864显示、电机测速、控制逻辑程序
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include <MOTOR.h>
  2. #include <ADC.h>
  3. unsigned int PWM=0;  //pwm占空比为50%,可调占空比
  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控制系数        10,12,1.5
  12. uint Inpluse = 0, num1 = 0;
  13. unsigned int time1 = 0;


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

  20. }


  21. //-------------------------------
  22. // PID
  23. //-------------------------------
  24. void PIDControl()        //pid偏差计算
  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. // 定时器、中断初始化
  45. //-------------------------------
  46. void TimeInit()
  47. {
  48.         TMOD = 0X01;        //定时器工作在方式1(16位定时器)
  49.         TH0 = 0XFF;                //12M晶振下定时0.1ms   65536-65436
  50. //        TL0 = 0X9c;
  51.     TL0 = 0Xc6;                //实验


  52.         ET0 = 1;

  53.         TR0 = 1;                        //开启定时器

  54.         EX0 = 1;  //中断0允许         
  55.         IT0 = 1;  //边沿触发
  56.          EA = 1;
  57.         INT = 1;
  58.         e = 0;
  59.         e1 = 0;
  60.         e2 = 0;
  61.         IN01=0;
  62. }
复制代码

  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. //目标制动力矩
  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. //实际制动力矩
  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. //目标制动力矩显示        

  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. //实际制动力矩显示        

  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. //定时器0
  172. //-------------------------------
  173. void Timer0(void) interrupt 1
  174. {
  175.         
  176. //        TH0 = 0XFF;                //重装初值
  177. //        TL0 = 0X9c;                //标准值
  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++;  //转速测量周期
  189. }
复制代码

所有资料51hei提供下载(Proteus请使用7.5版本):
仿真、主程序.zip (115.49 KB, 下载次数: 26)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:542563 发表于 2021-4-21 09:14 | 只看该作者
SOC居然是个模拟量?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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