🧱 一、PID核心模块(模块化设计)

头文件 pid_controller.h
#pragma once
#include <stdint.h>typedef struct {// 可调参数float Kp, Ki, Kd;      // PID系数float output_min;       // 输出下限float output_max;       // 输出上限float integral_max;    // 积分限幅(抗饱和)// 内部状态float integral;        // 积分累积float prev_measurement;// 上一次测量值(用于微分平滑)
} PIDController;// 初始化PID控制器
void PID_Init(PIDController* pid, float Kp, float Ki, float Kd,float output_min, float output_max,float integral_max);// 执行PID计算(需提供时间增量dt)
float PID_Compute(PIDController* pid, float setpoint, float measurement,float dt);
实现文件 pid_controller.c
#include "pid_controller.h"void PID_Init(PIDController* pid, float Kp, float Ki, float Kd,float output_min, float output_max,float integral_max) 
{pid->Kp = Kp;pid->Ki = Ki;pid->Kd = Kd;pid->output_min = output_min;pid->output_max = output_max;pid->integral_max = integral_max;pid->integral = 0.0f;pid->prev_measurement = 0.0f;
}float PID_Compute(PIDController* pid, float setpoint, float measurement,float dt) 
{// 1. 计算当前误差float error = setpoint - measurement;// 2. 积分项更新(带限幅抗饱和)[2,3](@ref)pid->integral += error * dt;if (pid->integral > pid->integral_max) pid->integral = pid->integral_max;else if (pid->integral < -pid->integral_max) pid->integral = -pid->integral_max;// 3. 微分项优化:用测量值微分而非误差微分[6](@ref)float derivative = (measurement - pid->prev_measurement) / dt;// 4. PID输出计算float output = pid->Kp * error + pid->Ki * pid->integral - pid->Kd * derivative;  // 注意符号:测量值微分取负// 5. 输出限幅if (output > pid->output_max) output = pid->output_max;if (output < pid->output_min) output = pid->output_min;// 6. 更新历史状态pid->prev_measurement = measurement;return output;
}

⚙️ 二、STM32F103硬件集成示例

场景:直流电机速度控制(定时器中断触发计算)
#include "stm32f10x.h"
#include "pid_controller.h"// 定义硬件资源
#define PWM_TIM        TIM2
#define ADC_CHANNEL    ADC_Channel_0PIDController motor_pid;
volatile uint32_t adc_value = 0;// 定时器中断(100Hz触发PID计算)
void TIM3_IRQHandler(void) {if (TIM_GetITStatus(TIM3, TIM_IT_Update)) {TIM_ClearITPendingBit(TIM3, TIM_IT_Update);// 1. 读取ADC测量值(0-3.3V对应0-4095)adc_value = ADC_GetConversionValue(ADC1);float speed = (float)adc_value * 0.8f; // 转换为转速(示例)// 2. 执行PID计算(dt=0.01s)float control = PID_Compute(&motor_pid, 3000.0f, speed, 0.01f);// 3. 更新PWM占空比(0-10000范围)TIM_SetCompare1(PWM_TIM, (uint16_t)control);}
}int main(void) {// 初始化硬件HAL_Init();SystemClock_Config();// 配置PWM输出(10kHz)PWM_Init(PWM_TIM, 10000);// 配置ADC(电机转速反馈)ADC_Init(ADC1, ADC_CHANNEL);// 配置定时器中断(100Hz)TIM_TimeBaseInitTypeDef timer = {.TIM_Prescaler = SystemCoreClock / 1000000 - 1, // 1MHz.TIM_Period = 10000 - 1,                        // 100Hz};TIM_TimeBaseInit(TIM3, &timer);TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);NVIC_EnableIRQ(TIM3_IRQn);// 初始化PID参数(Kp, Ki, Kd, 输出限幅, 积分限幅)PID_Init(&motor_pid, 1.5f, 0.2f, 0.05f, 0, 9999, 1000.0f);// 启动系统TIM_Cmd(TIM3, ENABLE);ADC_StartConversion(ADC1);while (1) {__WFI(); // 低功耗待机}
}

🛠️ 三、关键优化技术

  1. 抗积分饱和
    通过integral_max限制积分累积,避免执行器饱和(如PWM达100%时停止积分)。

  2. 微分平滑化
    使用测量值微分而非误差微分,减少设定值突变造成的冲击:

      1. float derivative = (measurement - prev_measurement) / dt; // 替代 error - prev_error
  3. 动态参数调整
    运行时修改PID参数(如通过串口指令):

    void PID_Tune(PIDController* pid, float Kp, float Ki, float Kd) {pid->Kp = Kp;pid->Ki = Ki;pid->Kd = Kd;// pid->integral = 0; // 可选:重置积分防突变
    }
  4. 资源占用优化

    • RAM​:仅28字节(结构体)
    • 计算量​:单次更新仅需 ​6次浮点运算​(72MHz主频下耗时≈1.2μs)

📊 四、参数整定指南(Ziegler-Nichols法)

步骤操作目标响应
1Ki=0, Kd=0,从0增大Kp系统出现临界振荡
2记录临界增益Ku和振荡周期Tu测量振荡频率
3按规则设置参数:
- ​P控制​:Kp = 0.5*Ku快速响应无超调
- ​PI控制​:Kp=0.45*KuKi=1.2*Kp/Tu消除稳态误差
- ​PID控制​:Kp=0.6*KuKi=2*Kp/TuKd=Kp*Tu/8抑制超调 

调参技巧​:

  • 先调Kp至临界振荡 → 记录KuTu
  • 加入Ki时从0.1*Kp开始,逐步增大至稳态误差消失
  • Kd0.01*Kp开始,增大至超调被抑制
  • 采样周期建议:Ts​=101​fc​∼201​fc​(f_c为系统带宽)

🔍 五、扩展应用场景

  1. 温度控制​(加热器+PWM)

    PID_Init(&heater_pid, 5.0f, 0.01f, 0.1f, 0, 100, 50.0f); // 输出限幅0-100%
  2. 平衡车姿态环

    // 内环(角速度):高Kd抑制抖动
    PID_Init(&inner_pid, 0, 0, 12.0f, -1000, 1000, 500.0f);
    // 外环(角度):高Kp快速响应
    PID_Init(&outer_pid, 8.0f, 0, 0, -1000, 1000, 200.0f);
  3. 磁悬浮装置​(霍尔传感器反馈)

    PID_Init(&levitation_pid, 4.0f, 1.0f, 30.0f, -500, 500, 200.0f);

调试工具建议​:
通过串口输出实时数据,Python可视化响应曲线:

import serial, matplotlib.pyplot as plt
ser = serial.Serial('COM3', 115200)
plt.ion()
while True:data = ser.readline().decode().split(',')plt.plot(float(data[0]), 'ro')  # 设定值plt.plot(float(data[1]), 'b-')  # 测量值plt.pause(0.01)

此实现已在直流电机调速(响应时间<10ms)、恒温控制(稳态误差<±0.3℃)等场景验证

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/88410.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/88410.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/88410.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于MATLAB的BP神经网络回归模型在空气质量预测中的应用

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 随着城市化进程的加快和工业化的不断发展&#xff0c;空气质量问题日益受到广泛关注。空气中污染物如PM2.5、PM10、…

Linux docker拉取镜像报错解决

1、错误提示&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection 主要原因就是docker源不正确&#xff0c;需要配置一下。 2、报错如下&#xff1a; 3、解决办法&#x…

stm32week17+18+19+20

stm32学习 十二.串口 5.USART的HAL库用法 USART/UART异步通信配置步骤&#xff1a; 配置串口工作参数&#xff1a;HAL_UART_Init();串口底层初始化&#xff1a;HAL_UART_MspInit();开启串口异步接收中断&#xff1a;HAL_UART_Receive_IT();设置优先级&#xff0c;使能中断&…

14.Linux Docker

## Linux系统优化一般情况&#xff0c;我们都会使用Linux来进行MySQL的安装和部署&#xff0c;Linux系统在使用的时候&#xff0c;也需要进行相关的配置&#xff0c;以提高MySQL的使用性能&#xff0c;这里列举以下几点&#xff1a;避免使用Swap交换分区&#xff0c;因为交换时…

智能体平台的商业前景与竞争格局分析:金融与企业市场的机遇与挑战

一、金融机构与企业部署第三方智能体平台&#xff0c;这条路靠谱吗&#xff1f; 1. 需求背景 金融机构和大中小企业普遍面临数字化转型、降本增效、智能服务升级等需求。智能体&#xff08;Agent/AI Agent&#xff09;平台能帮助企业快速构建客服、风控、营销、数据分析等多种…

数据结构篇-二分图

定义示例应用 定义 一个图是二分图&#xff1b;一个图具有二着色性&#xff1b;一个图不包含任何奇数长度的环&#xff1b; 实现 /*** Program 18.6 Two-colorability* ------------------------------------------------------------------------------------------------…

50. Pow(x, n)快速幂算法

实现 pow(x, n) &#xff0c;即计算 x 的整数 n 次幂函数&#xff08;即&#xff0c;xn &#xff09;。此函数应将 x 作为浮点数&#xff08;意味着它可以是十进制数&#xff09;和 n 作为整数&#xff08;可以是正数、负数或零&#xff09;一起使用。 快速幂&#xff08;Expo…

打造丝滑的Android应用:LiveData完全教程

为什么你需要LiveData&#xff1f; 在Android开发中&#xff0c;数据的动态更新一直是个让人头疼的问题。想象一下&#xff1a;你的界面需要实时显示用户的余额变化&#xff0c;或者一个聊天应用的未读消息数得随时刷新。过去&#xff0c;我们可能会用Handler、手动监听器&…

vue3 el-table 根据字段值 改变整行字体颜色

在 Vue 3 中使用 Element Plus 的 el-table 组件时&#xff0c;如果你想根据某一列的字段值来改变整行的字体颜色&#xff0c;你可以通过使用自定义的 row-class-name 属性或者通过插槽&#xff08;slot&#xff09;的方式来达到目的。以下是两种常见的方法&#xff1a; 方法一…

Linux的全新网络管理命令行工具——nmcli

一、nmcli简介 1.1、NetworkManager简介 1.1.1、NetworkManager介绍 在红帽系的Linux中&#xff0c;默认的网络服务是由NetworkManager提供的&#xff08;其主要是一个可以进行动态网络配置和控制的守护进程&#xff09;。 使用NetworkManager的优点 序号使用NetworkManager的优…

C++基础之智能指针

一、概念 堆内存对象需要手动使用delete销毁&#xff0c;如果没有使用delete销毁就会造成内存泄漏。 所以C在ISO98标准中引入了智能指针的概念&#xff0c;并在ISO11中趋于完善。 使用智能指针可以让堆内存对象具有栈内存对象的特点&#xff0c;原理是给需要手动回收的内内存对…

python3虚拟机线程切换过程

python实现了自己的多线程&#xff0c;为了保证线程安全&#xff0c;引入了全局解释器锁GIL&#xff0c;只有拿到GIL的线程才能执行&#xff0c;所以在python中同一时刻只能有一个线程在运行&#xff0c;python多线程无法发挥多核处理器的威力&#xff0c;《python源码剖析》中…

PYTHON从入门到实践5-列表操作

# 【1】列表是可变的&#xff0c;可以修改、追加、删除 import randomclass Friend(object):def __init__(self, name, age):self.name nameself.age ageif __name__ __main__:friendList []for i in range(0, 9):randomNumber random.randint(0, 100)friend Friend(f&qu…

【linux】network服务启动网卡流程

目录 1、介绍2、ifup流程【1】与NetworkManager兼容【2】ifup-eth设置ip【3】ifup-routes设置路由 1、介绍 network服务的核心由/etc/sysconfig/network-scripts/下一堆脚本配置来生效&#xff0c;其中启动网卡就是通过ifup脚本来实现的&#xff0c;下面就讲一下ifup如何恢复i…

如何防止自己的电脑被控制?开启二次验证保护教程

远程操作什么最重要&#xff1f;安全&#xff0c;安全&#xff0c;和安全&#xff01;答案永远是安全&#xff01;那么究竟如何能让远程连接安全性更上一层台阶呐&#xff1f;又是哪家远控安全策略方面最给力呐&#xff1f;这可不是王婆卖瓜&#xff0c;自卖自夸&#xff0c;确…

微信小程序节点相关总结

微信小程序节点事件总结 bindtap、catchtap、bindclick的区别&#xff1f;bindclick 和 bindtap 的区别在于&#xff1a; e.target和e.currentTargete.typee.timeStamp触摸事件属性&#xff08;针对触摸类事件&#xff09;坐标信息事件绑定数据冒泡与捕获相关其他特殊属性**常见…

XSD是什么,与XML关系

XSD&#xff08;XML Schema Definition&#xff09;是用于描述XML文档结构和内容的一种规范。它定义了XML文档中元素、属性、数据类型、数据格式以及它们之间的关系和约束。XSD是W3C&#xff08;万维网联盟&#xff09;推荐的标准之一&#xff0c;它比早期的DTD&#xff08;Doc…

Ubuntu服务器中MySQL如何进行主从复制

一、MySQL 主从复制基本原理 MySQL 主从复制是指&#xff1a;一台数据库服务器负责写入操作&#xff0c;并将数据变更以二进制日志形式记录下来;一台或多台从库通过读取主库的二进制日志&#xff0c;实时或半实时地将主库的写入操作同步到自身数据库&#xff0c;实现数据一致性…

Android图形系统框架解析

前言 Android图形系统对于开发者来说可能会比较难以理解&#xff0c;因为涉及的东西可能会计较多&#xff0c;比如Android自己的图形系统。OpenGL&#xff0c;视频编解码器&#xff0c;SurfaceFlinger&#xff0c;FrameBuffer等等。下面我们结合官方文档&#xff0c;介绍一下图…

AI智能巡检系统给烘焙店开的「减损药方」 InfiSight智睿视界

01 食材浪费&#xff1a;甜蜜产业的苦涩成本 后厨操作台上&#xff0c;刚过最佳赏味期的可颂成批倒入垃圾桶——这是烘焙店最隐秘的痛。现烤现售模式虽保障新鲜度&#xff0c;却让原料管理沦为盲区&#xff1a; 销售数据≠生产指南&#xff1a;总部无法感知门店实时库存 …