可以三个挡位,输出不同的转速,同时采集转速,进行PID运算
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
代码:
- #include <reg52.h>
- #include <stdio.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define THC0 0xf9
- #define TLC0 0x0f //2ms
- //#define THC0 0xec
- //#define TLC0 0x78 //5ms
- #define SEG_DATA_PORT P0
- unsigned char code Duan[]={0x3F, 0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x40};//共阴极数码管,0-9段码表
- unsigned char Data_Buffer[8]={1,0,0,0,0,0,0,0}; // 显示缓冲
- unsigned int displaytime=0,timing=90;
-
- uchar i=0;
- sbit LS138_A=P2^2;
- sbit LS138_B=P2^3;
- sbit LS138_C=P2^4;
- sbit AddSpeed=P3^1; //一档按键端口
- sbit SubSpeed=P3^0; //二挡按键端口
- sbit TurnForward=P3^3; //三挡按键端口
- sbit TurnBackward=P3^4; //启动或关闭按键端口
- //sbit Stop=P1^5;
- sbit buzzer = P1^3;
- sbit IN1=P1^1;
- sbit IN2=P1^2;
- sbit PWM_FC=P1^0;
- int e ,e1 ,e2 ;
- float uk ,uk1 ,duk ;//pid输出值
- float Kp=15,Ki=12,Kd=1.6;
- int out=0;
- uint SpeedSet=100;
- uint cnt=0;
- uint Inpluse=0,num=0;//脉冲计数
- uint PWMTime=100;//脉冲宽度
- unsigned char arry[];
- void SendString(uint ch);
- void PIDControl();
- void SystemInit();
- void delay(uchar x);
- void PWMOUT();
- void SetSpeed();
- void SegRefre();
- /**************主函数************/
- void main()
- {
- SystemInit();
- while(1)
- {
- SetSpeed(); //按键设定速度
- SegRefre(); //数码管显示刷新
- PWMOUT(); //输出PWM
-
- }
- }
- void PIDControl() //pid偏差计算
- {
- e=SpeedSet-num;
- duk=(Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2))/50;
- uk=uk1+duk;
- out=(int)uk; //输出为占空比
- if(out>1000)
- {
- out=1000;
- }
- else if(out<0)
- {
- out=0;
- }
- uk1=uk; //变量值移位
- e2=e1;
- e1=e;
- PWMTime=out;
- }
- void delay(uchar x)
- {
- uint i,j;
- for(i=x;i>0;i--)
- for(j=50;j>0;j--);
- }
- void PWMOUT()
- {
- if(cnt<PWMTime)
- {
- PWM_FC=1;
- }
- else
- {
- PWM_FC=0;
- }
- if(cnt>1000) cnt=0;
- }
- void SystemInit()
- {
- TMOD=0X21;
- TH0=THC0;
- TL0=TLC0;
- TH1=0xC0;
- TL1=0XC0;
- ET1=1;
- ET0=1;
- TR0=1;
- TR1=1;
- EX0=1;
- IT0=1;
- EA=1;
- e =0;
- e1=0;
- e2=0;
- IN1 = 0;
- IN2 = 0;
- }
- void SetSpeed()
- {
- if(AddSpeed==0&&IN2==1)
- {
- delay(200); //消抖处理
- if(AddSpeed==0)
- {
- Data_Buffer[0]=1;//一档
- SpeedSet=100;
- timing = 90;
- if(SpeedSet>1500)
- {
- SpeedSet=1500;
- }
- }
- }
- if(SubSpeed==0&&IN2==1)
- {
- delay(200);
- if(SubSpeed==0)
- {
- Data_Buffer[0]=2;//二档
- SpeedSet=230;
- timing = 70;
- if(SpeedSet<0) SpeedSet=0;
- }
- }
- if(TurnForward==0&&IN2==1)
- {
- delay(200);
- if(TurnForward==0)
- {
- Data_Buffer[0]=3;//三档
- SpeedSet=380;
- timing = 50;
- if(SpeedSet<0) SpeedSet=0;
- }
- }
- if(TurnBackward==0)
- {
- delay(200);
- if(TurnBackward==0)
- {
- IN1 = 0;
- IN2 = ~IN2;
- Data_Buffer[0]=1;//一档
- SpeedSet=100;
- timing = 90;
- while(TurnBackward==0);
- }
- }
- /*
- if(Stop==0)
- {
- delay(200);
- if(Stop==0)
- {
- IN1 = 1;
- IN2 = 1;
- while(Stop==0);
- }
- }
- */
- }
- void SegRefre() //显示刷新
- {
- //Data_Buffer[0]=timing/1000; //分离设定值各位
- if(IN2==1){
- Data_Buffer[1]=10;
- Data_Buffer[2]=timing/10;
- Data_Buffer[3]=timing%10;
- }
- else{
- Data_Buffer[0]=0;
- Data_Buffer[1]=10;
- Data_Buffer[2]=0;
- Data_Buffer[3]=0;
- }
- Data_Buffer[4]=num/1000;
- Data_Buffer[5]=num%1000/100;
- Data_Buffer[6]=num%100/10;
- Data_Buffer[7]=num%10;
- }
- void int0() interrupt 0
- {
- Inpluse++; //采集外部脉冲
- }
- void t0() interrupt 1
- {
- static unsigned char Bit=0;
- static unsigned int time=0;
- TH0=THC0;
- TL0=TLC0;
-
- Bit++;
- time++; //转速测量周期
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
仿真代码51hei附件下载:
直流电机PID控制.rar
(102.48 KB)
(下载次数: 117, 2021-11-17 20:34 上传)
下载积分: 黑币 -5