用dsp28335实现电机速度的闭环控制
时间: 2023-09-16 21:16:04 浏览: 499
以下是一份基于DSP28335芯片的电机速度闭环控制代码,可供参考:
```c
#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
// 电机参数
#define POLES 4 // 电机极数
#define ENCODER_RES 2048 // 编码器分辨率
#define GEAR_RATIO 50 // 减速比
#define SAMPLE_TIME_MS 1 // 采样时间
// 控制参数
#define Kp 0.5 // 比例系数
#define Ki 0.01 // 积分系数
#define Kd 0.1 // 微分系数
// 电机控制变量
float speed_ref = 500.0; // 速度设定值,单位为RPM
float speed_act = 0.0; // 速度实际值,单位为RPM
// 电机控制器
typedef struct
{
float Kp;
float Ki;
float Kd;
float Ts;
float saturation;
float error[2];
float integral;
float derivative;
} PID;
PID pid = {
.Kp = Kp,
.Ki = Ki,
.Kd = Kd,
.Ts = SAMPLE_TIME_MS / 1000.0,
.saturation = 1.0,
};
// 速度测量
float encoder_count = 0.0;
float prev_encoder_count = 0.0;
interrupt void xint1_isr(void)
{
encoder_count += 1.0;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}
void InitEncoder(void)
{
EALLOW;
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;
GpioCtrlRegs.GPAQSEL1.bit.GPIO1 = 0;
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;
GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 1;
PieVectTable.XINT1 = &xint1_isr;
IER |= M_INT1;
PieCtrlRegs.PIEIER1.bit.INTx4 = 1;
EINT;
EDIS;
}
void MeasureSpeed(void)
{
float delta_count = encoder_count - prev_encoder_count;
prev_encoder_count = encoder_count;
speed_act = (delta_count / ENCODER_RES) * (1000.0 / SAMPLE_TIME_MS) * 60.0 / POLES / GEAR_RATIO;
}
// 电机控制
float duty_cycle = 0.0;
void InitPwm(void)
{
EALLOW;
GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO16 = 1;
GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0;
GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1;
GpioCtrlRegs.GPADIR.bit.GPIO17 = 1;
GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;
EPwm1Regs.TBPRD = 1500; // PWM周期为20kHz
EPwm1Regs.TBCTL.bit.CTRMODE = 0; // up-down计数模式
EPwm1Regs.AQCTLA.bit.CAU = 2; // 当CMPA <= TBCTR,EPWMxA引脚输出高电平
EPwm1Regs.AQCTLA.bit.CAD = 1; // 当CMPA > TBCTR,EPWMxA引脚输出低电平
EPwm1Regs.CMPA.half.CMPA = 0; // 初始占空比为0
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // 使能PWM触发ADC
EPwm1Regs.ETSEL.bit.SOCASEL = 4; // 当计数器计数到零时触发ADC
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // PWM触发ADC时序为立即触发
EPwm1Regs.TBCTL.bit.PHSEN = 0; // 禁止相位补偿
EPwm1Regs.TBCTL.bit.SYNCOSEL = 0; // 禁止同步输出
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // 不使用高速时钟
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // 时钟分频系数为1
EPwm1Regs.TBCTL.bit.FREE_SOFT = 0b10; // 停止计数器并清空CMPA、CMPB寄存器
EPwm1Regs.TBCTL.bit.PHSDIR = 0; // 相位递增
EPwm1Regs.TBCTL.bit.SWFSYNC = 0; // 禁止软件同步
EPwm1Regs.TBCTL.bit.TRB = 1; // 允许重新加载计数器
EPwm1Regs.TBCTL.bit.CTRMODE = 3; // 停止计数器并清空CMPA、CMPB寄存器
EDIS;
}
void ControlSpeed(void)
{
float error = speed_ref - speed_act;
pid.integral += (error + pid.error[0]) * pid.Ts / 2;
pid.derivative = (error - pid.error[0]) / pid.Ts;
pid.error[0] = error;
duty_cycle = pid.Kp * error + pid.Ki * pid.integral + pid.Kd * pid.derivative;
duty_cycle = duty_cycle > pid.saturation ? pid.saturation : duty_cycle;
duty_cycle = duty_cycle < -pid.saturation ? -pid.saturation : duty_cycle;
EPwm1Regs.CMPA.half.CMPA = EPwm1Regs.TBPRD * (1.0 - duty_cycle) / 2;
}
void main(void)
{
InitSysCtrl();
InitPieCtrl();
InitPwm();
InitEncoder();
EnableInterrupts();
while (1)
{
MeasureSpeed();
ControlSpeed();
DELAY_US(SAMPLE_TIME_MS * 1000);
}
}
```
在代码中,我们首先定义了电机参数和控制参数。然后定义了一个PID控制器结构体,其中包含了比例系数、积分系数、微分系数、采样时间、饱和值、误差、积分和微分等变量。在控制函数中,我们首先测量电机的速度,然后根据速度设定值和实际值计算出误差,并使用PID控制算法计算出输出值。在主函数中,我们使用定时器来定时采样电机速度和控制电机,然后将控制量输出到PWM信号中,驱动电机转动。
需要注意的是,上述代码中使用了编码器来测量电机速度,在初始化函数中需要设置GPIO引脚,并配置中断。同时,PWM信号需要设置占空比和周期,以及触发ADC采样。
阅读全文