模糊pid控制单片机程序
时间: 2024-01-08 19:02:15 浏览: 29
以下是一个简单的模糊PID控制的单片机程序:
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define Kp 1.0 // 比例增益
#define Ki 0.5 // 积分增益
#define Kd 0.2 // 微分增益
#define ERROR_THRESHOLD 0.001 // 误差阈值
#define INPUT_MAX 1023 // 输入最大值
#define OUTPUT_MAX 255 // 输出最大值
// 模糊控制器参数
#define NB 3 // 模糊集合个数
#define NM 3
#define NS 3
#define ZE 3
#define PS 3
#define PM 3
#define PB 3
#define SIGMA 0.1
// 模糊集合
float NB_set[NB] = {-1.0, -0.5, 0.0};
float NM_set[NM] = {-0.5, 0.0, 0.5};
float NS_set[NS] = {0.0, 0.5, 1.0};
float ZE_set[ZE] = {-0.1, 0.0, 0.1};
float PS_set[PS] = {-1.0, -0.5, 0.0};
float PM_set[PM] = {-0.5, 0.0, 0.5};
float PB_set[PB] = {0.0, 0.5, 1.0};
// 模糊规则库
float rule[NB][NM][NS] = {
{{PB_set[0], PB_set[0], PM_set[0]},
{PB_set[0], PM_set[0], ZE_set[0]},
{PM_set[0], ZE_set[0], NS_set[0]}},
{{PB_set[0], PM_set[0], ZE_set[0]},
{PM_set[0], ZE_set[0], NS_set[0]},
{ZE_set[0], NS_set[0], PS_set[0]}},
{{PM_set[0], ZE_set[0], NS_set[0]},
{ZE_set[0], NS_set[0], PS_set[0]},
{NS_set[0], PS_set[0], PM_set[0]}}
};
float fuzzy_output[NB][NM][NS];
// 模糊化函数
float fuzzy(float error, float delta_error) {
float NB_membership, NM_membership, NS_membership, ZE_membership, PS_membership, PM_membership, PB_membership;
// 计算误差和误差变化量的隶属度
for (int i = 0; i < NB; i++) {
for (int j = 0; j < NM; j++) {
for (int k = 0; k < NS; k++) {
NB_membership = exp(-pow(error - NB_set[i], 2) / (2 * pow(SIGMA, 2)));
NM_membership = exp(-pow(error - NM_set[j], 2) / (2 * pow(SIGMA, 2)));
NS_membership = exp(-pow(error - NS_set[k], 2) / (2 * pow(SIGMA, 2)));
ZE_membership = exp(-pow(delta_error - ZE_set[1], 2) / (2 * pow(SIGMA, 2)));
PS_membership = exp(-pow(delta_error - PS_set[1], 2) / (2 * pow(SIGMA, 2)));
PM_membership = exp(-pow(delta_error - PM_set[1], 2) / (2 * pow(SIGMA, 2)));
PB_membership = exp(-pow(delta_error - PB_set[1], 2) / (2 * pow(SIGMA, 2)));
fuzzy_output[i][j][k] = rule[i][j][k] * NB_membership * NM_membership * NS_membership * ZE_membership * PS_membership * PM_membership * PB_membership;
}
}
}
// 求和
float numerator = 0.0;
float denominator = 0.0;
for (int i = 0; i < NB; i++) {
for (int j = 0; j < NM; j++) {
for (int k = 0; k < NS; k++) {
numerator += fuzzy_output[i][j][k] * (NB_set[i] + NM_set[j] + NS_set[k]);
denominator += fuzzy_output[i][j][k];
}
}
}
// 计算模糊输出
return numerator / denominator;
}
int main() {
float setpoint = 512.0; // 目标值
float input, output, error, last_error, delta_error, integral, derivative;
while (1) {
// 获取输入
// 这里用 ADC 获取输入,假设输入值的范围为 0 ~ 1023
input = ADC_Read();
// 计算误差和误差变化量
error = setpoint - input;
delta_error = error - last_error;
// 计算模糊输出
output = fuzzy(error, delta_error);
// 计算 PID 输出
integral += error;
derivative = error - last_error;
float pid_output = Kp * error + Ki * integral + Kd * derivative;
// 模糊输出和 PID 输出相加得到最终输出
output += pid_output;
// 输出限制
if (output > OUTPUT_MAX) {
output = OUTPUT_MAX;
} else if (output < 0) {
output = 0;
}
// 输出
PWM_Set(output);
// 判断是否达到目标
if (fabs(error) < ERROR_THRESHOLD) {
break;
}
// 更新误差和误差变化量
last_error = error;
}
return 0;
}
```
上面的程序实现了一个简单的模糊PID控制器。其中,`fuzzy()` 函数用于计算模糊输出,`main()` 函数中的其它部分用于计算PID控制器输出和最终输出,并将最终输出发送到PWM输出引脚。
需要注意的是,以上程序仅供参考,需要根据具体情况进行修改。特别是模糊规则库和模糊集合的选择需要根据实际应用进行调整。