STM32_PID通用算法增量式和位置式
前言:
此算法为入门级PID算法,调试好参数后可应用于温度控制、舵机控制、直流电机的转速控制和直流电机的角度控制等等,下面就以温度控制举例
pid.c
c
#include "pid.h"
#include "sensor.h"
#include "dev_control.h"
#include "usbd_cdc_if.h"
pidTypeDef_t heatTemp_pid = {0};
pidPID_t tempPID = {0};
void pidInit(void)
{
tempPID.KP = 15; //比例常数
tempPID.KI = 0; //积分常数
tempPID.KD = 0.1; //微分常数
heatTemp_pid.PidMode = 0; //使用增量式PID
heatTemp_pid.SetPoint = 0; //设定目标值
heatTemp_pid.ActualValue = 0.0; //期望值输出
heatTemp_pid.SumError = 0.0; //积分值
heatTemp_pid.Error = 0.0; //当前偏差值
heatTemp_pid.LastError = 0.0; //上次偏差值
heatTemp_pid.PrevError = 0.0; //上上次偏差值
heatTemp_pid.Proportion = tempPID.KP; //比例常数
heatTemp_pid.Integral = tempPID.KI; //积分常数
heatTemp_pid.Derivative = tempPID.KD; //微分常数
}
void pidTask(void)//根据系统来计算调用该函数的周期
{
if(devTypedef.devHeatAir.devHeatAirEnable == STATE_ENABLE)
{
heatTemp_pid.SetPoint = (float)sensorData.ptcSensorData.ptcSensorData_target;
heatTemp_pid.ActualValue = pidComputeCtrl(&heatTemp_pid, (float)sensorData.ptcSensorData.ptcSensorData_float);//¼ÆËã³öPIDÊä³öÖµ
if(heatTemp_pid.ActualValue < 0) heatTemp_pid.ActualValue = 0;
if(heatTemp_pid.ActualValue > 100) heatTemp_pid.ActualValue = 100;
devTypedef.devHeatAir.devHeatAirDuty = heatTemp_pid.ActualValue;//作用到控制设备上
//调试信息
usb_printf("%0.2f,%0.2f,%0.2f\r\n",heatTemp_pid.SetPoint,(float)sensorData.ptcSensorData.ptcSensorData_float,heatTemp_pid.ActualValue);
}
}
float pidComputeCtrl(pidTypeDef_t *PID, float feedbackValue)
{
PID->Error = (float)(PID->SetPoint - feedbackValue); //计算偏差
if(PID->PidMode == 1) //增量式PID
{
PID->ActualValue += (PID->Proportion * (PID->Error - PID->LastError)) //比例环节
+ (PID->Integral * PID->Error) //积分环节
+ (PID->Derivative * (PID->Error - 2 * PID->LastError + PID->PrevError)); //微分环节
PID->PrevError = PID->LastError; //更新历史偏差
PID->LastError = PID->Error;
}
else //位置式PID
{
PID->SumError += PID->Error;
float pid_integral = 0;
pid_integral = PID->Integral * PID->SumError; //限积分算法
if(pid_integral > 5) pid_integral = 5;
PID->ActualValue = (PID->Proportion * PID->Error) //比例环节
+ pid_integral //积分环节
+ (PID->Derivative * (PID->Error - PID->LastError)); //微分环节
PID->LastError = PID->Error;
}
return (PID->ActualValue); //返回计算后的结果
}
pid.h
c
#ifndef __PID_H
#define __PID_H
#include "main.h"
#include "log.h"
#define PID_TASK_PERIOD 1 //
#define PID_LOG_EN 1
#if PID_LOG_EN
#define PID_printf(format, ...) printf(RTT_CTRL_TEXT_WHITE format , ##__VA_ARGS__)//"\r\n"
#define PID_info(format, ...) printf(RTT_CTRL_TEXT_GREEN"[pid]info:" format , ##__VA_ARGS__)
#define PID_debug(format, ...) printf(RTT_CTRL_TEXT_WHITE"[pid]debug:" format , ##__VA_ARGS__)
#define PID_warning(format, ...) printf(RTT_CTRL_TEXT_YELLOW"[pid]warning:" format , ##__VA_ARGS__)
#define PID_error(format, ...) printf(RTT_CTRL_TEXT_RED"[pid]error:" format ,##__VA_ARGS__)
#else
#define PID_printf(format, ...)
#define PID_info(format, ...)
#define PID_debug(format, ...)
#define PID_warning(format, ...)
#define PID_error(format, ...)
#endif
typedef struct
{
float KP;
float KI;
float KD;
} pidPID_t;
extern pidPID_t pressurePID;
extern pidPID_t tempPID;
//PID参数结构体
typedef struct
{
float SetPoint; //设定目标值
float ActualValue; //期望值输出
float SumError; //积分值
float Proportion; //比例常数
float Integral; //积分常数
float Derivative; //微分常数
float Error; //当前偏差值
float LastError; //上次偏差值
float PrevError; //上上次偏差值
unsigned int PidMode; //使用PID模式
} pidTypeDef_t;
extern pidTypeDef_t heatTemp_pid; //加热系统PID参数结构体
extern unsigned char pid_flag;
void pidInit(void);
void pidTask(void);
float pidComputeCtrl(pidTypeDef_t *PID, float feedbackValue);
#endif