1、介绍
在直流电机的PID转速控制中,Simulink可以提供一种直观且高效的方法来设计和调试控制器。PID控制器是一种经典的控制算法,它通过不断调整输出信号来使系统的实际输出与期望输出尽可能接近。在直流电机的转速控制中,PID控制器可以根据电机的实际转速和期望转速之间的差异来调整电机的输入电压,以实现转速的精确控制。使用Simulink搭建直流电机的PID转速控制系统可以分为几个步骤。
首先,需要建立一个电机模型,包括电机的转动方程、电机的参数等。然后,将PID控制器模块添加到系统中,设置PID控制器的参数,包括比例系数、积分系数和微分系数。接下来,将电机模型和PID控制器模块连接起来,形成一个闭环控制系统。最后,通过Simulink中的仿真功能,可以对控制系统进行测试和调,观察电机的实际转速与期望转速之间的差异,并对PID控制器的参数进行优化。此外,Simulink还支持代码生成和硬件连接,可以将设计好的控制器直接部署到实际的硬件系统中,实现对直流电机的实时控制。
本文通过Simulink搭建直流电机模型,采用PID控制其运动转速。并将搭建完成的PID控制转换为C代码,通过Keil编译成.Hex文件,载入Proteus半实物仿真平台软件,通过观察代码转换的PID算法是否可以对转速进行控制。主要内容包括:(一)直流电机模型搭建。(二)PID控制器搭建及控制器调参。(三)代码转换介绍。(四)Proteus直流电机驱动控制。
2、直流电机模型搭建
直流电机模型可以通过Simulink的数学模型搭建,也可以使用Simscape的DC Motor模块,如图1所示,关于如何通过数学模型来搭建模型,可以参考数学直流电机模型。
图1
如果大家不想看觉得有点复杂,我给大家总结以下:
将上式进行拉普拉斯变换即可得到下式:
对于delta(θ)为电机转速,V为电机输入电压,几个关键参数如下:
J为直流电机转子惯量,单位Kgm^2; 取J = 0.01Kg*m^2
b为转子阻尼系数,单位Nm/(rad/s); 取b = 0.1Nm/(rad/s)
Kt为直流电机扭矩常数,单位Nm/A; 取Kt = 0.01Nm/A
Ke为直流电机反电动势常数,单位V/(rad/s), 取Ke = 0.01 V/(rad/s)
R为直流电机转子线圈电阻,单位Ω, 取R = 1.0Ω
L为直流电机转子线圈电感,单位H, 取L = 0.5H.
将所有参数带入公式即可得到图1所示的数学模型。另外,如果不想推导数学模型还可以使用Simscape来搭建,如图2所示:
图2
3、PID控制器搭建及参数辨识
如图3所示为直流电机的闭环控制结构图,输入给定一个阶跃信号,本文要求控制的转速为50rpm,但公式中的单位为rad/s,需要转换,阶跃信号的输入为50*0.1047rad/s。
图3
4、仿真结果及代码转换
PID控制器的参数调节,我们采用的是Simulink自带的调节器,操作步骤,可以参考PID参数调节,将所有参数辨识好后,可以得到如图4所示的仿真结果:
图4
得到整定好的PID参数后,我们需要将PID通过代码转换,并在Keil中使用,先将模型整理成如图5所示,控制器采用离散型PID
图5
关于如何进行代码转换,我们要将所有的输入和输出定义为single类型,如图6所示,记住是所有的参数和输入、输出接口
图6
随后在配置参数的地方更改以下几个设置:
图7
然后Ctrl+B生成代码,生成的代码如下:
图8
随后打开Keil,其中Main函数实现电机的控制,DMPC文件实现算法函数。
图9
具体代码如下,生成的代码是更改过的,因为直接调用PID的算法函数不方便。另外PID控制的是PWM波,需要定义PWM的占空比,PID对PWM进行控制即可。
#include <reg52.h>
#include "DMPC.h"
#include "rtwtypes.h"
#define uint unsigned int
#define uchar unsigned char
sbit IN1=P1^0;
sbit IN2=P1^1;
sbit ENA=P1^2;
sbit motor_pin = P3^7; // 直流电机引脚
sbit k0=P2^0;//正转
sbit k1=P2^1;//反转
sbit k2=P2^2;//加速
sbit k3=P2^3;//减速
sbit k4=P2^4;//停止
uchar Counter=0,Compare=0;
uint count = 0; // 用于计数电机转数
uint time = 0; // 用于计时
float speed;
float OutputPID;
float DMPC_step(float Feedbac);
// PID变量
float Targ_Speed = 50;
float rtb_Err1=0;
float rtb_FilterCoefficient=0;
float Filter_DSTATE=0;
float Integrator_DSTATE=0;
float OutPID=0;
float kp = 5.5; // 比例常数
float ki =0.2; // 积分常数
float kd = 0.1; // 微分常数
float DMPC_step(float Feedbac)
{
rtb_Err1 = Targ_Speed - Feedbac;
rtb_FilterCoefficient = kd * rtb_Err1 - Filter_DSTATE;
OutPID = kp * rtb_Err1 +Integrator_DSTATE +rtb_FilterCoefficient;
Integrator_DSTATE += ki * rtb_Err1;
Filter_DSTATE += rtb_FilterCoefficient;
return OutPID;
}
void delay(uint n)
{
uint i=0,j=0;
for(i=0;i<n;i++)
{
for(j=0;j<120;j++);
}
}
void Timer0_init()//100us
{
TMOD |= 0x01; // 设置定时器0为工作模式1
TH0 = 0xFC; // 设置定时器初值,定时50us
TL0 = 0x18;
ET0 = 1; // 开启定时器0中断
EA = 1; // 开启总中断
TR0 = 1; // 启动定时器0
}
void main()
{
motor_pin = 1; // 设置P3.7为输入模式
ENA=0;
IN1=0;
IN2=0;//一开始让电机停止
Timer0_init();
Compare=50;
while(1)
{
if(k0==0)//正转
{
delay(100);
while(!k0);
ENA=1;
IN1=1;
IN2=0;
// 计算转速
speed = (count * 600) / time; // 计算电机转速,单位:RPM
// 更新PID变量
OutputPID=DMPC_step(speed);
Compare+=OutputPID;
}
else if(k1==0)//反转
{
delay(100);
while(!k1);
ENA=1;
IN1=0;
IN2=1;
}
else if(k2==0)//加速
{
delay(100);
while(!k2);
Compare=Compare+20;
}
else if(k3==0)//减速
{
delay(100);
while(!k3);
Compare=Compare-20;
}
if(k4==0)//停止
{
delay(100);
while(!k4);
ENA=0;
TR0=0;
IN1=0;
IN2=0;
}
}
}
void Timer0() interrupt 1
{
TH0 = 0xFC; // 重新设置定时器初值
TL0 = 0x18;
time += 50; // 每次定时器中断时间增加50us
Counter++;
Counter%=100;
if(motor_pin == 0) { // 如果电机引脚为低电平,表示电机没转
count = 0;
} else { // 如果电机引脚为高电平,表示电机转了一圈
count++;
}
if(Counter<Compare)//如果小于占空比
{
IN1=1;
}
else
{
IN1=0;
}
}
硬件部分如图11所示,主要由52单片机、L298N电机控制器和直流电机组成,其中直流电机内置了霍尔传感器可以直接进行转速反馈,我们用P3.7引脚进行接收信号。
图11
由于时间关系,我未进行转速曲线的上位机编写,后续有需求可以尝试,我们看到图11所示的电机转速是可以控制到50rpm的。因此,Simulink的算法和控制策略搭建可以通过proteus来验证,可以打打减小工作上的参数辨识。本文的内容还有很多细节未指出来,有不懂的地方可以联系我~~~~~