登录|立即注册|使用QQ帐号登录
论坛 > 51单片机
发帖|
看3681|回2|收藏
楼主 ID:528775 只看他
2021-11-17 20:34
可以三个挡位,输出不同的转速,同时采集转速,进行PID运算
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.gif 51hei图片20211117203331.png

单片机源程序如下:

代码:

  1. #include <reg52.h>
  2. #include <stdio.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. #define THC0 0xf9
  6. #define TLC0 0x0f   //2ms
  7. //#define THC0 0xec
  8. //#define TLC0 0x78   //5ms
  9. #define SEG_DATA_PORT P0
  10. unsigned char  code Duan[]={0x3F, 0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};//共阴极数码管,0-9段码表
  11. unsigned char  Data_Buffer[8]={1,0,0,0,0,0,0,0};                         //        显示缓冲
  12. unsigned int displaytime=0,timing=90;

  13. uchar i=0;
  14. sbit LS138_A=P2^2;
  15. sbit LS138_B=P2^3;
  16. sbit LS138_C=P2^4;

  17. sbit AddSpeed=P3^1;  //一档按键端口
  18. sbit SubSpeed=P3^0;  //二挡按键端口
  19. sbit TurnForward=P3^3; //三挡按键端口
  20. sbit TurnBackward=P3^4; //启动或关闭按键端口
  21. //sbit Stop=P1^5;
  22. sbit buzzer = P1^3;

  23. sbit IN1=P1^1;
  24. sbit IN2=P1^2;
  25. sbit PWM_FC=P1^0;
  26. int e ,e1 ,e2 ;
  27. float uk ,uk1 ,duk ;//pid输出值
  28. float Kp=15,Ki=12,Kd=1.6;
  29. int out=0;
  30. uint SpeedSet=100;
  31. uint cnt=0;
  32. uint Inpluse=0,num=0;//脉冲计数
  33. uint PWMTime=100;//脉冲宽度
  34. unsigned char  arry[];
  35. void SendString(uint ch);
  36. void PIDControl();
  37. void SystemInit();
  38. void delay(uchar x);
  39. void PWMOUT();
  40. void SetSpeed();
  41. void SegRefre();
  42. /**************主函数************/
  43. void main()
  44. {
  45.         SystemInit();
  46.         while(1)
  47.         {
  48.                 SetSpeed();                //按键设定速度
  49.                 SegRefre();                //数码管显示刷新
  50.                 PWMOUT();                //输出PWM

  51.         }
  52. }

  53. void PIDControl()        //pid偏差计算
  54. {
  55.         e=SpeedSet-num;                 
  56.         duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2))/50;      
  57.         uk=uk1+duk;            
  58.         out=(int)uk;   //输出为占空比
  59.         if(out>1000)
  60.         {
  61.                 out=1000;
  62.         }
  63.         else if(out<0)
  64.         {
  65.                 out=0;
  66.         }
  67.         uk1=uk;                                  //变量值移位
  68.         e2=e1;
  69.         e1=e;                                  
  70.         PWMTime=out;
  71. }

  72. void delay(uchar x)
  73. {
  74.         uint i,j;
  75.         for(i=x;i>0;i--)
  76.                 for(j=50;j>0;j--);
  77. }

  78. void PWMOUT()                  
  79. {
  80.         if(cnt<PWMTime)               
  81.         {
  82.                 PWM_FC=1;
  83.         }
  84.         else
  85.         {
  86.                 PWM_FC=0;
  87.         }
  88.         if(cnt>1000) cnt=0;         
  89. }
  90. void SystemInit()
  91. {
  92.         TMOD=0X21;     
  93.         TH0=THC0;
  94.         TL0=TLC0;
  95.         TH1=0xC0;
  96.         TL1=0XC0;
  97.         ET1=1;
  98.         ET0=1;
  99.         TR0=1;
  100.         TR1=1;
  101.         EX0=1;     
  102.         IT0=1;
  103.         EA=1;
  104.         e =0;               
  105.         e1=0;
  106.         e2=0;
  107.         IN1 = 0;
  108.         IN2 = 0;
  109. }
  110. void SetSpeed()
  111. {
  112.         if(AddSpeed==0&&IN2==1)
  113.         {
  114.                 delay(200);                          //消抖处理
  115.                 if(AddSpeed==0)
  116.                 {
  117.                         Data_Buffer[0]=1;//一档
  118.                         SpeedSet=100;
  119.                         timing = 90;
  120.                         if(SpeedSet>1500)
  121.                         {
  122.                                 SpeedSet=1500;
  123.                         }
  124.                 }
  125.         }
  126.         if(SubSpeed==0&&IN2==1)
  127.         {
  128.                 delay(200);
  129.                 if(SubSpeed==0)
  130.                 {
  131.                         Data_Buffer[0]=2;//二档
  132.                         SpeedSet=230;
  133.                         timing = 70;
  134.                         if(SpeedSet<0) SpeedSet=0;
  135.                 }
  136.         }
  137.         if(TurnForward==0&&IN2==1)
  138.         {
  139.                 delay(200);
  140.                 if(TurnForward==0)
  141.                 {
  142.                         Data_Buffer[0]=3;//三档
  143.                         SpeedSet=380;
  144.                         timing = 50;
  145.                         if(SpeedSet<0) SpeedSet=0;
  146.                 }
  147.         }
  148.         if(TurnBackward==0)
  149.         {
  150.                 delay(200);
  151.                 if(TurnBackward==0)
  152.                 {
  153.                    IN1 = 0;
  154.                    IN2 = ~IN2;
  155.                          Data_Buffer[0]=1;//一档
  156.                          SpeedSet=100;
  157.                          timing = 90;
  158.                    while(TurnBackward==0);
  159.                 }
  160.         }
  161. /*
  162.         if(Stop==0)
  163.         {
  164.                 delay(200);
  165.                 if(Stop==0)
  166.                 {
  167.                    IN1 = 1;
  168.                    IN2 = 1;
  169.                    while(Stop==0);
  170.                 }
  171.         }
  172. */
  173. }
  174. void SegRefre()                  //显示刷新
  175. {
  176.          //Data_Buffer[0]=timing/1000;                  //分离设定值各位
  177.          if(IN2==1){
  178.                  Data_Buffer[1]=10;
  179.                  Data_Buffer[2]=timing/10;
  180.                  Data_Buffer[3]=timing%10;
  181.          }
  182.          else{
  183.                  Data_Buffer[0]=0;
  184.                  Data_Buffer[1]=10;
  185.                  Data_Buffer[2]=0;
  186.                  Data_Buffer[3]=0;
  187.          }
  188.          Data_Buffer[4]=num/1000;                         
  189.          Data_Buffer[5]=num%1000/100;
  190.          Data_Buffer[6]=num%100/10;
  191.          Data_Buffer[7]=num%10;
  192. }

  193. void int0() interrupt 0
  194. {
  195.         Inpluse++;                    //采集外部脉冲
  196. }
  197. void t0() interrupt 1
  198. {
  199.         static unsigned char Bit=0;
  200.         static unsigned int time=0;
  201.         TH0=THC0;
  202.         TL0=TLC0;


  203.         Bit++;
  204.         time++;  //转速测量周期
  205. ……………………

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

仿真代码51hei附件下载:
直流电机PID控制.rar (102.48 KB)
(下载次数: 117, 2021-11-17 20:34 上传)

下载积分: 黑币 -5



沙发 ID:342822 只看他
2021-11-19 00:16
开机电源短路,是不是电机上编码器接地错误
板凳 ID:102963 只看他
2021-11-19 09:39
倒计时时间,是什么用途呢?没看懂!

51黑电子论坛

Powered by Discuz! X3.1

首页|标准版|触屏版|电脑版