This repository has been archived on 2025-02-28. You can view files and clone it, but cannot push or open issues or pull requests.
controller-hd/User/lib/control/custom/pid_hd.c

174 lines
5.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "pid_hd.h"
#include <math.h>
float32 out_pos; // 位置式pid输出
float32 Kp_watch; // 观测Kp的大小
float32 Ki_watch; // 观测Kp的大小
float32 Kd_watch; // 观测Kp的大小
/// <summary>
/// 杭电设置增量式PID参数
/// </summary>
/// <param name="self"></param>
/// <param name="kp">比例参数
/// <param name="ki">积分参数
/// <param name="kd">微分参数
static void _set_ctrl_prm_position(struct PID_HD *self, float32 kp, float32 ki, float32 kd)
{
pid_hd_position_t *pri = &self->pri_u.position;
osel_memset((uint8_t *)pri, 0, sizeof(pid_hd_position_t));
/*观测传进来的Kp、Ki、Kd*/
Kp_watch = kp;
Ki_watch = ki;
Kd_watch = kd;
pri->kp = kp;
pri->ki = ki;
pri->kd = kd;
pri->ki_limit = 10; // 积分分离界限
pri->kp_limit = 1; // 变比例界限
pri->err_dead = 0.5; // 控制死区范围
pri->alpha = 0.2; // 不完全微分系数
}
/// <summary>
/// 杭电:设置输出限幅参数
/// </summary>
/// <param name="self"></param>
/// <param name="maximum">积分输出上限
/// <param name="minimum">积分输出下限
static void _set_out_prm_position(struct PID_HD *self, float32 maximum, float32 minimum)
{
self->pri_u.position.out_max = maximum;
self->pri_u.position.out_min = minimum;
}
float32 out_pos_watch;
/// <summary>
/// 杭电位置式PID控制算法
/// </summary>
/// <param name="self"></param>
/// <param name="err"></param>
/// <returns></returns>
static float32 _pid_position(struct PID_HD *self, float32 err)
{
float32 x[3];
self->pri_u.position.err = err;
/*抗积分饱和*/
#if INTEGRAL_SEPARATION == 1 // 积分分离
if (self->pri_u.position.out > self->pri_u.position.out_max)
{
if (self->pri_u.position.err > self->pri_u.position.ki_limit) // 积分分离
{
self->pri_u.position.ki_error += 0;
}
else
{
if (self->pri_u.position.err < 0) // 若偏差为负值,执行负偏差的累加
{
self->pri_u.position.ki_error += self->pri_u.position.err;
}
}
}
else if (self->pri_u.position.out < self->pri_u.position.out_min)
{
if (self->pri_u.position.err > self->pri_u.position.ki_limit) // 若偏差为负值,停止积分
{
self->pri_u.position.ki_error += 0;
}
else
{
if (self->pri_u.position.err > 0) // 若偏差为正值,执行正偏差的累加
{
self->pri_u.position.ki_error += self->pri_u.position.err;
}
}
}
else
{
if (fabs(err) > self->pri_u.position.ki_limit || fabs(err) < 0.4)
{
self->pri_u.position.ki_error += 0;
}
else
{
self->pri_u.position.ki_error += self->pri_u.position.err;
}
}
#else /*无积分分离操作*/
if (fabs(err) < 0.4)
{
self->pri_u.position.ki_error += 0;
}
else
{
self->pri_u.position.ki_error += self->pri_u.position.err;
}
#endif
///*变比例操作*/
// if (fabs(err) > self->pri_u.position.kp_limit)
//{
// self->pri_u.position.kp = self->pri_u.position.kp_big;
// }
// else
//{
// self->pri_u.position.kp = self->pri_u.position.kp_small;
// }
// Kp_watch=self->pri_u.position.kp;
/*输出*/
if (fabs(err) < self->pri_u.position.err_dead)
{
self->pri_u.position.out = self->pri_u.position.pre_out;
}
else
{
x[0] = self->pri_u.position.err;
x[1] = self->pri_u.position.ki_error;
#if INCOMPLETE_DIFFEREN == 1
// 不完全微分项为了解决普通PID为微分环节容易振荡的问题
x[2] = self->pri_u.position.kd * (1 - self->pri_u.position.alpha) * (self->pri_u.position.err - self->pri_u.position.pre_error) + self->pri_u.position.alpha * self->pri_u.position.pre_error;
out_pos = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + x[2];
#endif
// 普通的微分环节
x[2] = self->pri_u.position.err - self->pri_u.position.pre_error;
out_pos = self->pri_u.position.kp * x[0] + self->pri_u.position.ki * x[1] + self->pri_u.position.kd * x[2];
out_pos_watch = out_pos;
self->pri_u.position.out = out_pos;
}
/*输出限幅*/
if (self->pri_u.position.out > self->pri_u.position.out_max)
{
self->pri_u.position.out = self->pri_u.position.out_max;
}
if (self->pri_u.position.out < self->pri_u.position.out_min)
{
self->pri_u.position.out = self->pri_u.position.out_min;
}
// 更新误差历史
self->pri_u.position.pre_error = self->pri_u.position.err; /*上一次误差值*/
// 更新输出历史
self->pri_u.position.pre_out = self->pri_u.position.out; /*上一次输出值*/
out_pos = self->pri_u.position.out;
return self->pri_u.position.out;
}
/// <summary>
/// 杭电:参数控制器
/// </summary>
/// <param name="self"></param>
void pid_hd_constructor(struct PID_HD *self)
{
self->set_ctrl_prm_position = _set_ctrl_prm_position;
self->set_out_prm_position = _set_out_prm_position;
self->pid_position = _pid_position;
}