|
头文件:
#ifndef __PID__H
#define __PID__H
#define SCALING_FACTOR 128
typedef struct PID_DATA{
//! Last process value, used to find derivative of process value.
int16_t lastProcessValue;
//! Summation of errors, used for integrate calculations
int32_t sumError;
//! The Proportional tuning constant, multiplied with SCALING_FACTOR
int16_t P_Factor;
//! The Integral tuning constant, multiplied with SCALING_FACTOR
int16_t I_Factor;
//! The Derivative tuning constant, multiplied with SCALING_FACTOR
int16_t D_Factor;
//! Maximum allowed error, avoid overflow
int16_t maxError;
//! Maximum allowed sumerror, avoid overflow
int32_t maxSumError;
} pidData_t;
*
* Needed to avoid sign/overflow problems
*/
// Maximum value of variables
#define MAX_INT 0x011F //INT16_MAX
#define MAX_LONG INT32_MAX
#define MAX_I_TERM (INT32_MAX / 2)
// Boolean values
#define FALSE 0
#define TRUE 1
#endif
源文件:
void pid_Init(signed int p_factor, signed int i_factor, signed int d_factor, struct PID_DATA *pid)
{
// Start values for PID controller
pid->sumError = 0;
pid->lastProcessValue = 0;
// Tuning constants for PID loop
pid->P_Factor = p_factor;
pid->I_Factor = i_factor;
pid->D_Factor = d_factor;
// Limits to avoid overflow
pid->maxError = MAX_INT / (pid->P_Factor + 1);
pid->maxSumError = MAX_I_TERM / (pid->I_Factor + 1.0); //sea
}
/*******************************************************************************************************
** 函数名称: pid_Controller
** 功能描述: Calculates output from setpoint, process value and PID status.
** 输入参数: int16_t setPoint: Desired value.
** int16_t processValue: Measured value.
** struct PID_DATA *pid_st: PID status struct.
** 输出参数: 无
********************************************************************************************************/
int16_t pid_Controller(int16_t setPoint, int16_t processValue, struct PID_DATA *pid_st)
{
int16_t error, p_term, d_term;
int32_t i_term, ret, temp;
error = setPoint - processValue;
if (error > pid_st->maxError) // Calculate Pterm and limit error overflow
{
p_term = MAX_INT;
}
else if (error < -pid_st->maxError)
{
p_term = -MAX_INT;
}
else
{
p_term = pid_st->P_Factor * error;
}
temp = pid_st->sumError + error; // Calculate Iterm and limit integral runaway
if(temp > pid_st->maxSumError)
{
i_term = MAX_I_TERM;
pid_st->sumError = pid_st->maxSumError;
}
else if(temp < -pid_st->maxSumError)
{
i_term = -MAX_I_TERM;
pid_st->sumError = -pid_st->maxSumError;
}
else
{
pid_st->sumError = temp;
i_term = pid_st->I_Factor * pid_st->sumError;
}
d_term = pid_st->D_Factor * (pid_st->lastProcessValue - processValue); // Calculate Dterm
pid_st->lastProcessValue = processValue;
ret = (p_term + i_term + d_term) / SCALING_FACTOR;
if(ret > MAX_INT)
{
ret = MAX_INT;
}
else if(ret < -MAX_INT)
{
ret = -MAX_INT;
}
//lcd_locate(5,1);
//lcd_print_number(ret,4,0);
return((int16_t)ret);
}
1、在这里,MAX_I_TERM定义为INT32_MAX/2,为什么要除以2呢?
2、PID初始化的时候
pid->maxError = MAX_INT / (pid->P_Factor + 1);
pid->maxSumError = MAX_I_TERM / (pid->I_Factor + 1.0); //sea
这里分母加1和1.0是什么意思?
3、如果用这个PID算法控制电压和电流,控制对象不同不会有什么问题吗?比如说对锂电池充电,要求恒压4.2V,会不会控制使得电压为4.2V的同时,电流太大了呢?或者恒流充电的时候,控制在保持恒定电流的同时,电压却会超过4.2V呢?能同时兼顾吗?
4、PID的参数P,I,D该如何确定呢?我看到充电器源码上给出的是P=5.4,I=0.01,D=0。
初次用PID,请大家帮忙,没说清楚的地方,请大家指出。谢谢了 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
如果天空是黑暗的,那就摸黑生存;
如果发出声音是危险的,那就保持沉默;
如果自觉无力发光,那就蜷伏于牆角。
但是,不要习惯了黑暗就为黑暗辩护;
也不要为自己的苟且而得意;
不要嘲讽那些比自己更勇敢的人。
我们可以卑微如尘土,但不可扭曲如蛆虫。
|