自整定模糊pid程序stm32
时间: 2023-08-04 07:05:07 浏览: 57
对于自整定模糊PID程序,可以使用STM32的定时器和中断来实现。下面是一个示例程序:
```c
#include "stm32f10x.h"
// 定义PID参数
float kp = 0.0, ki = 0.0, kd = 0.0;
// 定义模糊PID变量
float error = 0.0, last_error = 0.0, sum_error = 0.0;
float delta_error = 0.0, output = 0.0;
// 定义PID输出限制
float output_min = 0.0, output_max = 0.0;
// 定义定时器计数变量
volatile uint32_t timer_tick = 0;
// 定义定时器中断处理函数
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
timer_tick++;
}
}
// 定义PID计算函数
void pid_compute(float setpoint, float input)
{
// 计算误差
error = setpoint - input;
// 计算误差积分
sum_error += error;
// 计算误差微分
delta_error = error - last_error;
last_error = error;
// 计算模糊PID输出
output = kp * error + ki * sum_error + kd * delta_error;
// 输出限制
if (output < output_min)
output = output_min;
else if (output > output_max)
output = output_max;
}
// 定义自整定模糊PID函数
void auto_tune_fuzzy_pid(float setpoint, float input)
{
// 设置PID参数初值
kp = 1.0;
ki = 0.0;
kd = 0.0;
// 设置PID输出限制
output_min = 0.0;
output_max = 100.0;
// 设置定时器
TIM_TimeBaseInitTypeDef tim_init;
tim_init.TIM_Period = 1000;
tim_init.TIM_Prescaler = 72 - 1;
tim_init.TIM_ClockDivision = TIM_CKD_DIV1;
tim_init.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &tim_init);
// 启动定时器
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
// 等待稳定状态
while (timer_tick < 5000) {
pid_compute(setpoint, input);
output = 0.0; // 不输出控制信号
}
// 计算kp
float delta_output = 0.0;
float delta_kp = 0.0;
float max_delta_kp = 0.01;
float min_delta_output = (output_max - output_min) / 50.0;
float target_output = output_max - (output_max - output_min) / 3.0;
while (delta_output < target_output && delta_kp < max_delta_kp) {
pid_compute(setpoint, input);
delta_output += output;
delta_kp += 0.001;
kp += delta_kp;
if (output < min_delta_output)
break;
}
// 计算ki
float sum_output = 0.0;
float sum_ki = 0.0;
float max_sum_output = (output_max - output_min) * 10.0;
float target_sum_output = (output_max - output_min) / 2.0;
float target_ki = 0.0;
while (sum_output < target_sum_output && sum_ki < 10.0) {
pid_compute(setpoint, input);
sum_output += output;
sum_ki += ki;
ki += 0.001;
if (sum_output > max_sum_output)
break;
}
target_ki = ki;
// 计算kd
float delta_input = 0.0;
float delta_kd = 0.0;
float max_delta_input = (setpoint - input) * 10.0;
float target_delta_input = (setpoint - input) / 2.0;
float target_kd = 0.0;
while (delta_input < target_delta_input && delta_kd < 10.0) {
pid_compute(setpoint, input);
delta_input += input - last_error;
delta_kd += kd;
kd += 0.001;
if (delta_input > max_delta_input)
break;
}
target_kd = kd;
// 设置PID参数
kp -= delta_kp;
ki = target_ki;
kd = target_kd;
// 停止定时器
TIM_Cmd(TIM2, DISABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
timer_tick = 0;
}
int main(void)
{
// 初始化定时器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
NVIC_InitTypeDef nvic_init;
nvic_init.NVIC_IRQChannel = TIM2_IRQn;
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
nvic_init.NVIC_IRQChannelSubPriority = 0;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
// 初始化模糊PID变量
error = 0.0;
last_error = 0.0;
sum_error = 0.0;
delta_error = 0.0;
output = 0.0;
// 设置目标值和输入值
float setpoint = 50.0;
float input = 0.0;
// 进行自整定模糊PID
auto_tune_fuzzy_pid(setpoint, input);
while (1) {
// 进行PID计算
pid_compute(setpoint, input);
// 输出控制信号
// ...
}
}
```
注意,这只是一个基本的示例程序,实际应用需要根据具体的需求进行调整和优化。