利用dsp28335写出机械臂三闭环控制,利用结构体和中断
时间: 2023-07-21 07:40:50 浏览: 95
机械臂控制
5星 · 资源好评率100%
以下是一个在DSP28335上利用结构体和中断实现机械臂三闭环控制的示例代码:
```c
#include "DSP2833x_Device.h"
#include "DSP2833x_Examples.h"
// 定义位置环PID参数
#define KP_POS 1.0
#define KI_POS 0.1
#define KD_POS 0.01
// 定义速度环PID参数
#define KP_VEL 10.0
#define KI_VEL 1.0
#define KD_VEL 0.1
// 定义电流环PI参数
#define KP_CUR 2.0
#define KI_CUR 0.2
// 定义位置反馈和速度反馈
float pos_fb, vel_fb;
// 定义位置环控制量和速度环控制量
float pos_ctl, vel_ctl;
// 定义电流环控制量
float cur_ctl;
// 定义位置误差积分和微分
float pos_integ, pos_deriv, pos_prev;
// 定义速度误差积分和微分
float vel_integ, vel_deriv, vel_prev;
// 定义电流误差积分
float cur_integ;
// 定义位置期望值和速度期望值
float pos_ref = 0.0, vel_ref = 0.0;
// 定义编码器计数器
volatile struct {
Uint32 count;
Uint32 overflow;
} enc;
// 定义中断服务函数
interrupt void enc_isr(void)
{
// 读取编码器计数器
Uint16 status = GpioDataRegs.GPADAT.bit.GPIO31;
enc.count += (status ^ enc.overflow) ? 1 : -1;
enc.overflow = status;
}
// 定义初始化函数
void init(void)
{
// 初始化编码器计数器
enc.count = 0;
enc.overflow = GpioDataRegs.GPADAT.bit.GPIO31;
// 配置GPIO31为输入引脚
EALLOW;
GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 0;
GpioCtrlRegs.GPADIR.bit.GPIO31 = 0;
EDIS;
// 配置GPIO31的中断
EALLOW;
PieVectTable.XINT1 = enc_isr;
IER |= M_INT1;
PieCtrlRegs.PIECTRL.bit.ENPIE = 1;
PieCtrlRegs.PIEIER1.bit.INTx4 = 1;
EINT;
EDIS;
}
// 定义位置环控制函数
void pos_control(void)
{
// 计算位置误差
float pos_err = pos_ref - pos_fb;
// 计算位置环控制量
pos_ctl = KP_POS * pos_err + KI_POS * pos_integ + KD_POS * pos_deriv;
pos_integ += pos_err;
pos_deriv = pos_err - pos_prev;
pos_prev = pos_err;
// 将位置环控制量送到速度环控制器中
vel_ref = pos_ctl;
}
// 定义速度环控制函数
void vel_control(void)
{
// 计算速度误差
float vel_err = vel_ref - vel_fb;
// 计算速度环控制量
vel_ctl = KP_VEL * vel_err + KI_VEL * vel_integ + KD_VEL * vel_deriv;
vel_integ += vel_err;
vel_deriv = vel_err - vel_prev;
vel_prev = vel_err;
// 将速度环控制量送到电流环控制器中
cur_ctl = vel_ctl;
}
// 定义电流环控制函数
void cur_control(void)
{
// 计算电流误差
float cur_err = cur_ctl - vel_fb;
// 计算电流环控制量
cur_ctl = KP_CUR * cur_err + KI_CUR * cur_integ;
cur_integ += cur_err;
// 输出电流控制量到电机驱动器
set_motor_current(cur_ctl);
}
// 主函数
void main(void)
{
// 初始化系统
InitSysCtrl();
DINT;
InitPieCtrl();
// 初始化控制器
init();
// 启用全局中断
EINT;
// 进入主循环
while (1) {
// 读取位置反馈和速度反馈
pos_fb = enc.count * 0.1; // 编码器计数器转换为角度值
vel_fb = (pos_fb - pos_prev) * 1000.0 / (float)ISR_FREQ; // 计算角速度
// 进行控制器计算
pos_control();
vel_control();
cur_control();
}
}
```
在这个代码中,我们使用了结构体来保存编码器计数器的值,中断服务函数用于更新计数器的值。控制器的计算函数分别在主循环中调用,中断服务函数和主循环函数都可以访问全局变量,因此可以通过结构体来共享数据。此外,我们还使用了定时器来实现中断的触发,这可以使用DSP28335的定时器模块来实现。
阅读全文