#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// 单级PID结构体
typedef struct
{
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float setpoint; // 目标值
float output; // 输出值
float maxOut; // 最大输出
float minOut; // 最小输出
float error; // 当前误差
float prevError;// 上一次误差
float integral; // 积分项
float derivative; // 微分项
} PID;
// 单级PID初始化函数
void PID_Init(PID *pid, float kp, float ki, float kd, float min, float max)
{
pid->Kp = kp;
pid->Ki = ki;
pid->Kd = kd;
pid->setpoint = 0;
pid->output = 0;
pid->maxOut = max;
pid->minOut = min;
pid->error = 0;
pid->prevError = 0;
pid->integral = 0;
pid->derivative = 0;
}
// 单级PID计算函数
void PID_Calc(PID *pid, float ref, float fdb)
{
pid->setpoint = ref;
pid->error = ref - fdb;
pid->integral += pid->error;
pid->derivative = pid->error - pid->prevError;
// 积分限幅
if(pid->integral * pid->Ki > pid->maxOut)
pid->integral = pid->maxOut / pid->Ki;
if(pid->integral * pid->Ki < pid->minOut)
pid->integral = pid->minOut / pid->Ki;
// PID计算
pid->output = pid->Kp * pid->error +
pid->Ki * pid->integral +
pid->Kd * pid->derivative;
// 输出限幅
if(pid->output > pid->maxOut)
pid->output = pid->maxOut;
if(pid->output < pid->minOut)
pid->output = pid->minOut;
pid->prevError = pid->error;
}
//串级PID的结构体,包含两个单级PID
typedef struct
{
PID inner; //内环
PID outer; //外环
float output; //串级输出,等于inner.output
} CascadePID;
//串级PID的计算函数
//参数(PID结构体,外环目标值,外环反馈值,内环反馈值)
void PID_CascadeCalc(CascadePID *pid, float outerRef, float outerFdb, float innerFdb)
{
PID_Calc(&pid->outer, outerRef, outerFdb); //计算外环
PID_Calc(&pid->inner, pid->outer.output, innerFdb); //计算内环
pid->output = pid->inner.output; //内环输出就是串级PID的输出
}
// 模拟获取当前PH值
float getCurrentPH()
{
// 这里应该是实际读取PH传感器的代码
// 此处用随机数模拟PH值波动,范围在6.0-8.0之间
static float basePH = 7.0;
float noise = ((float)rand() / RAND_MAX) * 0.2 - 0.1; // -0.1到0.1的随机噪声
return basePH + noise;
}
// 模拟设置阀门流速
void setValveFlowRate(float flowRate)
{
// 这里应该是实际控制阀门的代码
printf("设置阀门流速: %.2f L/min\n", flowRate);
}
int main()
{
CascadePID phPID = {0}; // 创建串级PID结构体变量
float targetPH = 7.0; // 目标PH值
// 初始化PID参数
// 内环控制流速,响应要快
PID_Init(&phPID.inner, 10.0, 0.5, 1.0, 0.0, 100.0);
// 外环控制PH值,响应可以慢一些
PID_Init(&phPID.outer, 5.0, 0.2, 0.5, 0.0, 100.0);
printf("PH值PID控制系统启动,目标PH值: %.1f\n", targetPH);
// 模拟运行30个周期
for (int i = 0; i < 30; i++) {
float currentPH = getCurrentPH();
float currentFlowRate = i * 2.0; // 模拟当前流速
printf("周期 %d: 当前PH=%.2f, 目标PH=%.2f\n", i+1, currentPH, targetPH);
// 执行PID计算
PID_CascadeCalc(&phPID, targetPH, currentPH, currentFlowRate);
// 设置阀门流速
setValveFlowRate(phPID.output);
// 延时模拟控制周期
usleep(500000); // 500ms
}
return 0;
} 解释这个代码
最新发布