位制式PID算法
PID计算公式:
K:比例系数
E:为当前的偏差
T :PID的计算周期
T:积分周期
T:微分周期
E:前一次的偏差
OUT:常数
#ifndef _PID_#define _PID_#include "stm32f10x_conf.h"void PID_Calc(void);// 使用结构体定义PID所需的类型typedef struct{float Sv; // 用户设定值float Pv; // 当前的值float Kp; // 比例系数float T; // 计算周期or采样周期float Ti; // 积分时间常数float Td; // 微分系数float Ek; // 本次的偏差float Ek_1; // 上次的偏差float SEk; // 前面n次历史偏差之和float OUT0; // 当计算值为0时,维持一个稳定的输出float OUT; // 输出的值unsigned int C10ms;unsigned int pwmcycle; // pwm周期}PID;
// pid.c#include "pid.h"PID pid; // 存放PID算法所需的数据void PID_Calc(void) // pid计算{float DelEk;float ti, ki, td, kd;float Pout,Iout,Dout, temp;if(/*判断计算周期是否到了*/)return;pid.Ek = pid.Sv-pid.Pv; // 得到当前的偏差值pid.SEK += pid.Ek; // 历史偏差总和DelEk = pid.Ek - pid.Ek_1; // 最近两次偏差之差ti = pid.T/pid.Ti; // 积分项ki = ti*pid.Kp;td = pid.Td/pid.T; // 微分项kd = td*pid.Kp;Pout = pid.Kp*pid.Ek; // 比例输出Iout = ki*pid.SEK; // 积分输出Dout = kd*(pid.Ek - pid.Ek_1); // 微分输出temp = Pout + Iout + Dout + pid.OUT0; // 本次计算结果// pid归并到有效值内if(out>pid.pwmcycle){pid.OUT = pid.pwmcycle;}else if{pid.OUT = 0;}else{pid.OUT = temp;}pid.Ek_1 = pid.Ek; // 本次输出后,将本次的值赋值到上一次的pid.C10ms = 0;}
// main.c// 初始化PID所需的参数值(一般这些参数都是存储在可记忆存储位置)void PID_Init(){pid.Sv = 100; // 用户设定温度 从存储器获取的值pid.Kp = 20; // 从传感器获取的值pid.T = 1000; // PID计算周期 1000mspid.Ti = 5000; // 积分时间5000mspid.Td = 1200; // 微分时间1200mspid.pwmcycle = 1000; // pwm周期1000;}int main(){//....PID_Init();while(1){}}
增量式PID算法
公式:
参数介绍:
Ek:本次的偏差
Ek_1:上次的偏差
Ek_2:上上次的偏差
Kp:算法增益调节
Ti:积分时间
Td:微分时间常数
结论:
增量式PID的计算只需要最近3次的偏差(本次偏差,上次偏差,上上次偏差),不需要处理器存储大量的历史偏差值,计算量也相对较少,容易实现。
