直流电机PID调速

文章写的是基于数字PID控制器的闭环电机速度控制系统,系统以STC89C51单片机为控制核心,通过电机驱动L298N(这里因为所用电机是个小马达,额定电流和堵转电流不算大,所以用的是TC1508S做驱动)控制电机转速,电机转速控制采用PWM控制。在对电机转速进行调速的过程同时,单片机对电机的转速进行实时采集,并在LCD1602显示屏上实时显示电机实际转速。由于PID参数整定的需要,在设计中利用按键实现PID参数显示和修改;同时使用按键控制电机的目标转速。
以下是主要硬件部分:在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
霍尔传感器测速的使用非常简单,在电机同轴上安装几个小磁铁,当磁铁靠近霍尔传感器的时候,输出端输出低电平。
下面部分代码,后面会附上代码ZIP,仅供参考。
主程序:

#include "include.h"
void main()
{
	System_Init();
	while(1)
	{
		_5_KEY_scan();
		LCD_Display();
	}
} 

初始化程序:

#include <reg52.h>
#include "INIT.h"
#include "LCD_Drive.h"
#include "key.h"
#include "TIM.h"
#include "int0.h"
#include "PID.h"
#include<intrins.h>		
#define kp 7.03
#define ki 2.39
#define kd 0
void Motor_Init(void);
void System_Init(void)
{
	Motor_Init();
	Int0Init();
	LCD_init();
	LCD_Motor_velocity_Interface();
	Set_PID_Parameter(kp,ki,kd);
	Timer0Init();
	Timer1Init();
}
void Motor_Init(void)
{
	Motor_IN0 =0; Motor_IN1 = 0;
}

PID的C文件:

#include "PID.h"
#include "int0.h"
#include "string.h"

PID Velocity_PID;
int OUT=0;
//------------------------------------------
//		设置PID参数
//------------------------------------------
void Set_PID_Parameter(float KP,float KI,float KD)
{
	Velocity_PID.Kd = KD;
	Velocity_PID.Ki = KI;
	Velocity_PID.Kp = KP;
	Velocity_PID.SumError = 0;
	Velocity_PID.LastError=0;
	Velocity_PID.PrevError=0;
	Velocity_PID.SetPoint=0;
}
//增量式PID
float incPIDcalc(PID *PIDx,int nextpoint)
{
	int iError, iincpid;
	iError=PIDx->SetPoint-nextpoint;  
	iincpid= PIDx->Kp*( iError-PIDx->LastError) +PIDx->Ki*iError +PIDx->Kd*(iError-2*PIDx->LastError+PIDx->PrevError);
	if(iincpid>100) iincpid = 100;
	else if(iincpid<-100)iincpid = -100;
	PIDx->PrevError=PIDx->LastError; //存储保存上次数据
	PIDx->LastError=iError;//存储保存数据
	PIDx->SumError += iincpid;
	if(PIDx->SumError<0)PIDx->SumError=0;
	return PIDx->SumError;
}

定时器C文件:

#include "TIM.h"
#include "delay.h"
#include "int0.h"
#include "key.h"
#include "PID.h"
bit Bling_bling=0;//闪烁标志位,选中的参数会闪烁,用于屏幕
void Timer0Init(void)		//50毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		
	TL0 = 0xB0;		//
	TH0 = 0x3C;		//
	TF0 = 0;		//清楚TF0标志
	TR0 = 1;		//开启定时器
	ET0 = 1;
}

void Timer1Init(void)		//100UÃë@12.000MHz
{
	TMOD &= 0x0F;		//ÉèÖö¨Ê±Æ÷ģʽ
	TMOD |= 0x10;		//ÉèÖö¨Ê±Æ÷ģʽ
	TL1 = 0x9C;		//ÉèÖö¨Ê±³õÖµ
	TH1 = 0xFF;		//ÉèÖö¨Ê±³õÖµ
	TF1 = 0;		//Çå³ýTF1±êÖ¾
	TR1 = 1;		//¶¨Ê±Æ÷1¿ªÊ¼¼Æʱ
	ET1 = 1;
	EA = 1;    //Open master interrupt switch
}
void TIM0_isr() interrupt 1
{
	static uint8 Time_count=0,_50ms_Dida;
	uint8 i;
	TL0 = 0xB0;		//
	TH0 = 0x3C;		//
	_50ms_Dida++;
	if(Interface_flag)
	{
		Time_count++;
		if(Time_count==10){
			Bling_bling = !Bling_bling;
			Time_count = 0;
		}
	}
	if(_50ms_Dida==2)//100msµÃµ½Âö³å¸öÊý
	{
		/*********Âö³åдÔÚÕâÀï**********/
		Pulse_sum[9]=Pulse/2;
		SUM = 0;
		//¶ÔPulseת»»Îª1sÏÔʾÔÚÆÁÄ»
		for(i = 0;i<10;i++)
		{
			SUM+= Pulse_sum[i];
		}
		for(i=0;i<9;i++)
		{
			Pulse_sum[i]=Pulse_sum[i+1];
		}
		OUT= (int)incPIDcalc(&Velocity_PID,Pulse_sum[9]);
		if(Velocity_PID.SetPoint==0)OUT = 0;
		Pulse = 0;	
		/******************************/
		_50ms_Dida=0;
	}
}
void TIM1_isr() interrupt 3
{
	static uint16 PWM=0;
	TL1 = 0x9C;		//ÉèÖö¨Ê±³õÖµ
	TH1 = 0xFF;		//ÉèÖö¨Ê±³õÖµ
	PWM++;
	if(PWM==100)	PWM=0;
	if(OFF_AND_ON)
	{
		if(dirct_flag)//Motor_IN0 = 1;Motor_IN1 = 0;//Õýת
		{
			if(PWM==0) Motor_IN0 = 1;//Motor_pwm=1;
		  if(PWM==OUT)	Motor_IN0 = 0;//Motor_pwm=0;
		}
		else if(dirct_flag==0)//Motor_IN0 = 0;Motor_IN1 = 1;//·´×ª
		{
			if(PWM==0)Motor_IN1 = 1;//Motor_pwm=1;
			if(PWM==OUT)Motor_IN1 = 0;//	Motor_pwm=0;
		}
	}
}

按键C文件:

#include "key.h"
#include "LCD_Drive.h"
#include "PID.h"
int aim_velocity=0;
uint8 Parameter=0;
bit key_aux=0,Interface_flag=0;
bit dirct_flag=0,OFF_AND_ON=0;
void _5_KEY_scan(void)
{
	if(Clockwise_Key==0 && key_aux==1)
	{
		key_aux = 0;
		dirct_flag=!dirct_flag;
		if(OFF_AND_ON==1)
		{
			if(dirct_flag == 1)
			{
				Motor_IN0 = 1;Motor_IN1 = 0;//Õýת
				Write_Cmd(0x40+0x86);	
				Write_Data('+');
			}
			else if(dirct_flag==0)
			{
				Motor_IN0 = 0;Motor_IN1 = 1;//·´×ª
				Write_Cmd(0x40+0x86);	
				Write_Data('-');
			}
		}
	}
	else if(Switch==0 && key_aux==1)//¿ª¹Ø¼üºÍÑ¡ÔñPID²ÎÊý¼ü
	{
		key_aux = 0;
		if(!Interface_flag)
		{
			OFF_AND_ON=!OFF_AND_ON;
			if(OFF_AND_ON==0)
			{
				Motor_IN0 = 0;Motor_IN1 = 0;
				Write_Cmd(0x40+0x86);	
				Write_Data(' ');
				Velocity_PID.SumError = 0;
				Velocity_PID.LastError = 0;
			}
			if(OFF_AND_ON == 1)
			{
				if(dirct_flag == 1){
					Write_Cmd(0x40+0x86);	
					Write_Data('+');
				}else if(dirct_flag ==0)
				{
					Write_Cmd(0x40+0x86);	
					Write_Data('-');
				}
			}
		}
		else 
		{
			Parameter++;
			if(Parameter==4)Parameter=0;
		}
	}
	if(Up_speed==0 && key_aux==1)
	{
		key_aux = 0;
		if(!Interface_flag)		Velocity_PID.SetPoint+=1;//¼ÓËÙ
		else if(Interface_flag)
		{
			switch(Parameter)
			{
				case 1:Velocity_PID.Kp +=0.1;break;
				case 2:Velocity_PID.Ki +=0.1;break;
				case 3:Velocity_PID.Kd +=0.1;break;
			}
		}
	}
	if(Down_speed==0 && key_aux==1)
	{
		key_aux = 0;
		if(!Interface_flag)
		{
			Velocity_PID.SetPoint-=1;//¼õËÙ
			if(Velocity_PID.SetPoint<0)Velocity_PID.SetPoint = 0;
		}
		else if(Interface_flag)
		{
			switch(Parameter)
			{
				case 1:Velocity_PID.Kp -=0.1;if(Velocity_PID.Kp<0)Velocity_PID.Kp=0;break;
				case 2:Velocity_PID.Ki -=0.1;if(Velocity_PID.Ki<0)Velocity_PID.Ki=0;break;
				case 3:Velocity_PID.Kd -=0.1;if(Velocity_PID.Kd<0)Velocity_PID.Kd=0;break;
			}
		}
	}
	if(Interface_f == 0 && key_aux==1)//½çÃæÇл»°´¼ü
	{
		key_aux = 0;
		Parameter = 0;//Çл»½çÃæ˳±ã°ÑËüÖÃ0£¬Ï´βŲ»»áÊÇÑ¡Ôñ״̬
		Interface_flag = !Interface_flag;
		if(!Interface_flag){Write_Cmd(0x38);	Write_Cmd(0x0c);	Write_Cmd(0x01);LCD_Motor_velocity_Interface();}
		else {Write_Cmd(0x38);	Write_Cmd(0x0c);	Write_Cmd(0x01);LCD_PIDparameter_Interface();}
	}
	if(Clockwise_Key && Switch && Up_speed && Down_speed && Interface_f)//松开
		key_aux = 1;
}

显示屏的程序就不贴了,每个人使用的显示屏都可以不一样。只要信息能显示出来都可以了。
下面附上程序压缩包。Motor_incPID.zip

  • 30
    点赞
  • 238
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值