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
相关推荐
Funny_AI_LAB3 分钟前
Naval最新播客谈“氛围编码”:Vibe Coding 开启“一人独角兽”时代
人工智能·算法·语言模型·agi
如何原谅奋力过但无声3 分钟前
【灵神高频面试题合集04-05】二分查找
数据结构·python·算法·leetcode
salipopl5 分钟前
Spring Boot 整合 Druid 并开启监控
java·spring boot·后端
我不是懒洋洋7 分钟前
【数据结构】排序算法(直接插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序、计数排序)
c语言·数据结构·c++·经验分享·算法·排序算法
MediaTea7 分钟前
ML:逻辑回归的基本原理与实现
人工智能·算法·机器学习·数据挖掘·逻辑回归
ShiJiuD66688899912 分钟前
JSP Cookie和Session
java·开发语言
写点什么呢12 分钟前
PID平衡车_电路板绘制
stm32·单片机·嵌入式硬件
geNE GENT16 分钟前
Spring Boot 实战篇(四):实现用户登录与注册功能
java·spring boot·后端
FQNmxDG4S9 小时前
Java多线程编程:Thread与Runnable的并发控制
java·开发语言
超级码力6669 小时前
【Latex文件架构】Latex文件架构模板
算法·数学建模·信息可视化