STM32_PID通用算法增量式和位置式

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
相关推荐
季明洵2 小时前
C语言实现单链表
c语言·开发语言·数据结构·算法·链表
shandianchengzi3 小时前
【小白向】错位排列|图文解释公考常见题目错位排列的递推式Dn=(n-1)(Dn-2+Dn-1)推导方式
笔记·算法·公考·递推·排列·考公
I_LPL3 小时前
day26 代码随想录算法训练营 回溯专题5
算法·回溯·hot100·求职面试·n皇后·解数独
Yeats_Liao3 小时前
评估体系构建:基于自动化指标与人工打分的双重验证
运维·人工智能·深度学习·算法·机器学习·自动化
怒放吧德德3 小时前
后端 Mock 实战:Spring Boot 3 实现入站 & 出站接口模拟
java·后端·设计
cpp_25013 小时前
P9586 「MXOI Round 2」游戏
数据结构·c++·算法·题解·洛谷
浅念-3 小时前
C语言编译与链接全流程:从源码到可执行程序的幕后之旅
c语言·开发语言·数据结构·经验分享·笔记·学习·算法
biyezuopinvip3 小时前
基于Spring Boot的企业网盘的设计与实现(任务书)
java·spring boot·后端·vue·ssm·任务书·企业网盘的设计与实现
脸大是真的好~3 小时前
EasyExcel的使用
java·excel
小宋10213 小时前
Java 项目结构 vs Python 项目结构:如何快速搭一个可跑项目
java·开发语言·python