STM32_PID通用算法增量式和位置式
前言:
此算法为入门级PID算法,调试好参数后可应用于温度控制、舵机控制、直流电机的转速控制和直流电机的角度控制等等,下面就以温度控制举例
pid.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; //使用增量式PIDheatTemp_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
#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, ...)
#endiftypedef 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