📄 pid.c
字号:
#include <ADUC842.H>
#include <math.h>
#include "feedback.h"
#include "PID.h"
#include"lcd.h"
#define VMAX 250 //最大速度
#define BACKWARD_L 1 //定义前进为一
#define FORWARD_L 0
#define BACKWARD_R 0
#define FORWARD_R 1
sbit DIR_R = P0^1;
sbit DIR_L = P0^3;
/*************速度PID相关参数定义*******************/
float xdata V_Kp; //V_PID参数
float xdata V_Ki;
int xdata e_V_L; //速度反馈PID变量ei
int xdata e1_V_L; //e(i-1)
int xdata e_V_R;
int xdata e1_V_R;
float xdata d_u_V_L; //速度PID u的增量
float xdata d_u_V_R;
float xdata tem_data; //中间变量,用于解决中断中表达式过长引起的得数错误问题
int xdata beta_V_L;
int xdata beta_V_R;
int interval_V; // 速度间隔
char dis_V; // 允许速度误差
int tem_V_L; //暂时目标速度
int tem_V_R;
int aim_V_R; //最终目标速度,全局变量
int aim_V_L;
/*************速度PID相关参数定义*******************/
float xdata u_L; //占空比
float xdata u_R;
//------------------------------超级PID函数---------------------------------------
//函数名:MOTOR_PID
//参数:(左轮目标速度、右轮目标速度)
//说明:采用遇限削弱积分PID控制算法,目标速度和加速度值是与实际速度和电流成比例的值,各个值的上限要根据不同的电机实验测量
void MOTOR_V_PID(void)
{
//为了减少电机在饱和区停留过久,设置参数beta_lbe,y当进入饱和区,不计算积分值
if(u_L>VMAX||u_L<(0-VMAX))
{
beta_V_L = 0;
}
else
{
beta_V_L = 1;
}
if(u_R>VMAX||u_R<(0-VMAX))
{
beta_V_R = 0;
}
else
{
beta_V_R = 1;
}
//---------------------增量型V-PID计算-----------------------------
e_V_L = (tem_V_L - fb_V_L);
tem_data = V_Ki * beta_V_L;// 由于按二阶工程算法计算, 微分相为零,故略去微分相
tem_data = tem_data * e_V_L;
d_u_V_L = tem_data;
tem_data = V_Kp * (e_V_L - e1_V_L);
d_u_V_L = tem_data+d_u_V_L;
u_L += d_u_V_L;
//---------------------增量型V-PID计算-----------------------------
e_V_R = (tem_V_R - fb_V_R);
tem_data = V_Ki * beta_V_R;
tem_data = tem_data * e_V_R;
d_u_V_R = tem_data;
tem_data = V_Kp * (e_V_R - e1_V_R);
d_u_V_R = tem_data+d_u_V_R;
u_R += d_u_V_R;
//----------左轮输出电压限制--选择VMAX的值时要防止溢出-------------
if(u_L>VMAX)
{
u_L = VMAX;
}
if(u_L<(0-VMAX))
{
u_L = 0 - VMAX;
}
//----------右轮输出电压限制-------------------
if(u_R>VMAX)
{
u_R= VMAX;
}
if(u_R<(0-VMAX))
{
u_R = 0 - VMAX;
}
putstr("u_L",1);
putnum(u_L);
putstr("u_R",2);
putnum(u_R);
//--------配置电机输出方向---------------------
if(u_R<0)
{
DIR_R = BACKWARD_R; //这里还要重新分析 主要是因为不知道车怎样是前走,怎样后走
PWM0L = 0 - u_R;
}
else
{
DIR_R = FORWARD_R;
PWM0L = u_R; //pwm寄存器能是浮点数么?//不能,浮点数会被转换位整型
}
if(u_L<0)
{
DIR_L = BACKWARD_L;
PWM0H = 0 - u_L; //此处其实也是一个将u_L的绝对值传给PWM0L的过程
} //这样处理可以不调用fabs()函数,可能速度更快
else
{
DIR_L = FORWARD_L;
PWM0H = u_L;
}
//----------保存部分信息,以备下次计算使用---------------------------
e1_V_L = e_V_L; //注意传递顺序
e1_V_R = e_V_R;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -