基于51单片机的PID算法控制电机仿真

该系统采用AT89C52单片机,使用4位数码管显示,通过四个功能键进行速度控制。L298作为电机驱动芯片,具备高驱动电流能力、双全桥结构、灵活的输入控制和保护功能。程序中实现了PWM速度控制及PID控制算法,用于精确调节电机速度。同时,系统具备显示电机速度和设置速度的功能。
摘要由CSDN通过智能技术生成

仿真图:

功能简介:

单片机采用AT89C52,显示部分采用4位数码管
四个功能按键,分别是一档二档三挡选择以及启动和停止开关
采用L298作为电机驱动芯片

芯片/模块的特点:

L298特点:

高驱动能力:L298具有高驱动电流能力,能够提供最高4安培的峰值输出电流。这使得它可以驱动较大功率的直流电机,适用于许多高性能应用。

双全桥结构:L298具有双全桥结构,即两个独立的H桥电路,可以分别控制两个直流电机的运行方向和速度。这种结构使得同时控制多个电机变得更加方便。

输入控制灵活:L298的输入控制接口可以使用标准的逻辑电平(TTL或CMOS)来控制电机的运行。它可以接受脉冲宽度调制(PWM)信号来实现速度控制,并且支持正向、反向和制动模式的控制。

内置保护功能:L298具有内置的过流保护和过温保护功能,可以保护芯片和外部电路免受损坏。当输出电流超过设定值或芯片温度过高时,保护功能会自动触发。

低功耗待机模式:L298具有低功耗待机模式,可以通过控制输入信号将芯片置于低功耗状态。这有助于节省电能和延长电池寿命。

多种封装形式:L298可提供不同的封装形式,如多引脚直插式封装(DIP)和表面贴装技术(SMT)封装。这使得L298适应不同应用的安装需求。

主程序:

#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++;  //转速测量周期
	if(Bit>8) Bit=0;		  
	LS138_A=0;LS138_B=0;LS138_C=0;
	SEG_DATA_PORT=Duan[Data_Buffer[Bit]];	//显示段码
	switch(Bit)					//数码管位选
	{
		case 0:LS138_A=1;LS138_B=1;LS138_C=1;break;
		case 1:LS138_A=0;LS138_B=1;LS138_C=1;break;
		case 2:LS138_A=1;LS138_B=0;LS138_C=1;break;
		case 3:LS138_A=0;LS138_B=0;LS138_C=1;break;
		case 4:LS138_A=1;LS138_B=1;LS138_C=0;break;
		case 5:LS138_A=0;LS138_B=1;LS138_C=0;break;
		case 6:LS138_A=1;LS138_B=0;LS138_C=0;break;
		case 7:LS138_A=0;LS138_B=0;LS138_C=0;break;
	}
	if(time>100)
	{
		time=0;
		num=Inpluse*5;		   
		Inpluse=0;			   
		PIDControl();		   
	}
	displaytime++;
	if(displaytime==500){
		
		if(timing <= 0){
			buzzer=0;
			timing = 0;
		}
		else timing--;
		if(timing<=20&&timing>=0){
			buzzer=~buzzer;
		}
		displaytime = 0;
	}
		
}



设计文件:
链接:https://pan.baidu.com/s/1ZPxipfRUj2T0Mvst1q9hSw?pwd=yyxp

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值