ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于积分分离PI的Arduino智能刹车系统设计与实现

2026/9/20 19:24:59 拓冰建站 浏览量
基于积分分离PI的Arduino智能刹车系统设计与实现 简介一份围绕智能车制动控制改造的学术论文PDF内容以基于PI算法的智能刹车系统设计为主线适合汽车电子、嵌入式控制、智能车辆方向的研究生、工程师与竞赛团队参考。资源包含硬件执行机构设计、嵌入式单片机软件结构、积分分离PI算法原理、PI参数整定实验及Matlab结果分析等完整内容能够帮助读者理解从制动踏板开孔改造到控制算法落地的全流程。包内为1个PDF文件大小约5.81MB便携易用可直接用于参考文献阅读与技术方案借鉴。目前已有211人学习浏览具备一定专业参考价值。1. 从踏板开孔说起拉线式刹车改造为什么先动机械行程基于 PI 算法的智能刹车系统解决的是拉线式刹车最烦人的两个问题控制精度和响应速度。拉线式刹车的控制难题往往不是电机拉不动而是拉线太长。制动踏板到制动器之间隔着一条软轴踏板踩下去力要经过弯弯曲曲的拉线才能传到执行端在智能车改造里这条长回路直接表现为控制滞后和位置不准。这个方案给出的思路非常直接不换原车制动系统而是在制动踏板上方某处开孔让电机、减速器、飞轮在更短的距离上拉动拉线把机械行程缩短再配合积分分离 PI 算法做位置闭环。对做 Arduino 电机控制、无人车线控底盘改造的人来说这是一个成本低、又能完整训练 PI 参数整定流程的样例。2. 从连续 PI 到积分分离为什么普通 PI 会让刹车抖动2.1 位置式 PI 的离散化写法PI 控制规律写出来并不复杂连续系统形式是u(t) Kp*e(t) Ki*∫e(t)dt。这里给定值是系统预先设定的电机位置被控变量是编码器读到的实际电机位置偏差e(t) 目标位置 - 实际位置。比例项负责对当前偏差立刻作出反应偏差一出现控制量就跟着变动积分项则把历史误差累积起来主要用来消除静态误差。单片机上不能直接做连续积分只能按固定采样周期 T 离散化。假设第 k 个采样时刻位置式 PI 可以写成static float sum 0.0f; float piStep(float target, float current, float kp, float ki) { float err target - current; // 位置偏差单位用编码器 LSB sum err; // 积分项累加 return kp * err ki * sum; // 位置式 PI 输出 }这段代码对应的是最基础的位置式 PIsum相当于离散化的积分项。注意ki的量纲和采样周期 T 有关因为累加的是“误差个数”不是真实的积分时间。如果你把控制周期从 10ms 改成 20ms同样的系数表现会完全不同这是后面调参最容易踩的坑。还有一个隐患是sum没有任何限幅一旦系统启动或突然刹车偏差长时间很大积分项会不断堆高最后控制量远超执行器能输出的范围电机就会带着一个很大的“惯性”冲向目标。2.2 积分饱和是怎么把刹车拉到抖动的普通 PI 在恒速工况下问题不大但刹车系统恰好不是恒速工况。电机启动、刹到定位、急刹、松开刹车这几个瞬态都会在短时间内产生大偏差。偏差大时积分项快速积累等实际位置接近目标位置时积分项还留着一大截旧账输出控制量仍然很大结果就是冲过目标然后反向修正再冲过形成肉眼可见的抖动。对刹车系统来说这个抖动比响应慢更危险。拉线被电机反复拉紧、松开制动力的变化就不是平滑的车上的人会明显感觉到顿挫。论文中专门提出积分分离 PI 算法就是为了处理这个问题当系统偏差较大时取消积分环节避免积分积累造成超调当被控制量和设定值接近时再引入积分用来消除静态误差保证最终停得准。2.3 积分分离的切换条件与阈值理解积分分离的核心是一个判断阈值一般记作 beta。控制程序每个周期先算偏差err再根据偏差大小决定积分项是否参与err 的范围积分项处理控制效果小于等于 beta正常累加比例加积分消除静态误差大于 beta清零或停止累加只剩比例控制快速逼近目标beta 的取值不能拍脑袋。太小时积分几乎永远不接入系统始终有静态误差太大时分离形同虚设大偏差下积分照样累积超调问题还是存在。我一般会先记录系统稳定后的误差波动范围再取这个范围的 2 倍左右作为 beta 初始值然后根据超调量微调。这里还要说清一个概念积分分离不等于抗积分饱和。抗积分饱和是把积分项限制在一个固定范围积分分离则是大偏差时干脆不用积分。实际工程里两者经常叠加使用积分分离解决动态超调积分限幅解决持续大偏差下积分累积过快的问题。这套刹车系统选用位置式 PI 而不是增量式 PI是因为绝对式编码器可以直接给出绝对位置位置式输出也更直观代价就是必须处理积分饱和这正是论文引入积分分离算法的直接原因。3. Arduino Syren50 RS485 编码器硬件链路与关键器件接法3.1 为什么不直接用 DSP 或 STM32这套系统创新点不在主控芯片而在“机械短行程 电控执行机构 位置闭环”的组合。论文选用 Arduino 作为核心处理器我觉得很符合实验阶段的需求Arduino IDE 编程环境简单串口监视器可以直接看编码器反馈USB 转串口连接 PC 也方便对于需要频繁改 PI 参数、观察曲线、验证模式的改造项目这个开发效率比 DSP 高很多。当然量产时肯定会换成 STM32 或专用车身控制器。但在课程设计、智能车竞赛、样机验证阶段Arduino 够用省下的时间全部可以用来整定参数。Syren50 是串口控制的电机驱动器Arduino 不需要自己写复杂 PWM 调速逻辑只要通过串口发控制指令就行这让硬件层简单了不少。3.2 主要模块连接关系制动系统硬件结构大致是Arduino 作为核心PC 通过 USB 转串口连接开发板用来监测传感器反馈信号Arduino 的串口 1 向 Syren50 驱动器发送驱动信号驱动器驱动直流电机旋转电机输出轴带动减速器和飞轮飞轮拉动制动拉线绝对式光电编码器和电机输出轴同轴编码器通过 RS485 模块与单片机相连把电机旋转位置实时反馈回来。模块与 Arduino 的连接在系统中的作用PC / 上位机USB 转串口设定模式、监测实时位置数据Syren50 电机驱动器串口 1TX/RX接收速度/方向指令驱动直流电机直流电机 减速器 飞轮Syren50 动力输出端拉动制动拉线缩短踏板行程绝对式光电编码器RS485 转串口反馈电机轴绝对位置形成闭环这个链路里最容易出问题的是 RS485 半双工通信。编码器回传数据时单片机的收发方向切换如果没留足时间第一个字节大概率是坏的。另外Syren50 这类串口驱动器一般有自己固定的命令帧格式Arduino 端必须按帧发送不能像普通 PWM 一样直接给占空比。3.3 编码器读取的实操细节系统采用 10 位编码器分辨率大约 0.35 度也就是 360/1024 度每个 LSB。对于刹到死这种点位控制这个分辨率完全够。绝对式编码器的好处是上电就能得到绝对位置不需要像增量式编码器那样先找零点这一点对刹车系统非常重要因为系统不可能每次上电都执行一次“回零动作”。我在类似项目里读 RS485 编码器时一般会留一个方向控制引脚放在遍问函数里做收发切换const int rs485DirPin 7; long readEncoderAbs() { digitalWrite(rs485DirPin, HIGH); // 主机切到发送状态 Serial2.write(0x01); // 设备地址这里只是占位 Serial2.write(0x03); // 功能码实际以供应商协议为准 Serial2.write(0x00); // 寄存器地址高字节 Serial2.write(0x00); // 寄存器地址低字节 Serial2.write(0x00); // 读取长度高字节 Serial2.write(0x01); // 读取长度低字节 // 这里应该按 Modbus CRC 规则计算校验位不能直接省略 digitalWrite(rs485DirPin, LOW); // 切回接收状态 delayMicroseconds(100); // 半双工方向切换稳定时间 long pos 0; while (Serial2.available() 2) { pos (pos 8) | Serial2.read(); // 高字节在前拼接成位置 } return pos; }这段代码最关键的是方向引脚时序先切发送发完命令再切回接收并且留出至少 100 微秒的稳定时间。编码器地址、功能码、寄存器长度和校验位必须完全按实际硬件协议来上面只是结构示例不能直接抄进工程。还有一点建议控制程序里所有位置都用编码器 LSB 作为单位不要每次都转成角度。kp、ki、beta都按 LSB 标定单片机里可以少做浮点角度换算调参也更稳定。4. 主程序状态机与积分分离 PI 的 Arduino 实现4.1 三种自动模式怎么组织这套系统软件部分主要分为主程序和 PI 控制调节程序。主程序里有人工模式和自主刹车模式人工模式下先把电机停机由人直接操作刹车踏板自主刹车模式下才进入自动位置闭环。自主刹车模式又分成三种工作状态这是我最欣赏这个设计的地方正常刹车、紧急刹车、缓慢松刹车被拆成不同的目标位置和控制方式。正常刹车模式根据设定位置通过 PI 调节让电机拉到特定位置紧急刹车模式用 PI 调节让电机迅速拉到刹车刹死位置缓慢松刹车模式则让电机以一定转速转到规定宽度范围内用于半坡起步防止溜车。enum BrakeMode { BRAKE_MANUAL, BRAKE_NORMAL, BRAKE_EMERGENCY, BRAKE_SLOW_RELEASE }; BrakeMode mode BRAKE_MANUAL; float integrator 0.0f; const long normalTarget 400; // 正常刹车目标位置LSB const long emergencyTarget 900; // 刹死位置LSB const int releaseWindow 30; // 缓慢松刹车允许的窗口宽度 const float kp 35.2; // 比例系数来自实验整定 const float ki 0.06; // 积分系数来自实验整定 const float beta 30.0f; // 积分分离阈值按编码器噪声区间调整 void loop() { long currentPos readEncoderAbs(); switch (mode) { case BRAKE_MANUAL: setMotorSpeed(0); // 人工接管电机先停 return; case BRAKE_NORMAL: runPositionPI(normalTarget, currentPos); break; case BRAKE_EMERGENCY: runPositionPI(emergencyTarget, currentPos); break; case BRAKE_SLOW_RELEASE: slowRelease(300); // 固定速度松开刹车 return; } delayMicroseconds(10000); // 控制周期约 10ms时间要固定 }模式切换逻辑里有一个容易忽略的点从人工模式切到自动模式之前必须先确认电机处于停机状态、踏板没有被踩下否则编码器当前位置可能不是安全位置。正常刹车和紧急刹车共用一个位置 PI 函数差的只是目标位置这样代码不用复制两份参数也只维护一份。4.2 积分分离 PI 的具体实现积分分离 PI 调节程序是在位置式 PI 基础上改的。核心思想是当被控制量与给定值偏差较大时系统取消积分环节当偏差接近给定值时引入积分环节用来消除静态误差。float runIntegralSepPI(float target, float current, float *integral, float kp, float ki, float beta) { float err target - current; // 计算位置偏差 if (fabs(err) beta) { // 小偏差积分介入 *integral err; *integral constrain(*integral, -300, 300); // 积分限幅 } else { *integral 0; // 大偏差清积分防超调 } float u kp * err ki * (*integral); // PI 输出 return u; }这个函数里最关键的是“大偏差清积分”而不是“大偏差停止积分”。两者差别在于历史遗留如果只是停止累加旧的积分值仍然留在那里等误差变小后系统还要先消化掉这笔旧账依然可能过冲直接清零则等于重新开始比例项单独控制逼近速度和超调都更容易控制。积分限幅的 300 只是示例值。限幅上限可以按执行器饱和输出反推先测出 Syren50 在多大输入下电机开始满速再把积分项限在对应范围附近避免积分单独把控制量推到饱和区。如果刹车系统出现高速小幅度抖动多半是kp太大或者编码器噪声被放大了如果出现缓慢来回晃则很可能积分系数加太多或者控制周期不固定导致积分累加不均匀。4.3 串口数据采集与上位机监测调试 PI 参数时不能只看电机动不动还要把位置时间数据记录下来。论文中的做法是打开串口助手把串口波特率设定为 57600用 PC 机监测系统执行数据在不同工况下采集电机的位置时间信息再用 Matlab 拟合控制曲线。static unsigned long lastLog 0; const unsigned long logInterval 2; // 2ms 打印一次根据波特率调整 void logPosition() { if (millis() - lastLog logInterval) { lastLog millis(); Serial.print(millis() / 1000.0, 3); // 时间秒 Serial.print( ); Serial.println(readEncoderAbs()); // 位置LSB } }这段代码要在 PI 控制函数之后调用确保每个打印点对应的都是真实执行位置。串口打印本身耗时如果控制周期很短不要在 loop 里每个周期都打印否则一个周期可能被拉长到几毫秒采用定时打印可以让数据曲线基本保持均匀。PC 端接收时把串口输出保存成文本文件后续 Matlab 直接 load 进来画图。5. 参数整定、Matlab 拟合与「快速且不抖动」的验证方法5.1 试凑法从哪里下手论文采用工程整定法中的试凑法通过大量测试得到一组能让系统快速响应且不振荡的参数原文表 1 给出的整定结果为kp 35.2、ki 0.06。这个数值不是通用的换了车、换了减速比、换了拉线长度都得重调。我一般按这个顺序调参数现象调整方向响应太慢到不了目标位置加大kp位置到目标附近后一直有静态误差小幅加大ki接近目标时冲过头减小kp同时检查beta是否过大启动和急刹时抖动、振荡减小beta让积分更晚接入高速小幅度抖动检查编码器噪声适当降低kp先只保留比例控制把ki设成 0从比较小的kp开始增大观察实际位置曲线是否快速接近目标且没有明显超调再加积分消除静态误差。最后调beta原则是让积分刚好在系统接近稳态时接入而不是提前制造超调。5.2 用 Matlab 拟合位置时间曲线把 Arduino 串口保存的数据放进 Matlab用下面脚本基本够用data load(brake_log.txt); t data(:, 1); pos data(:, 2); plot(t, pos, -o, MarkerSize, 3); xlabel(Time / s); ylabel(Encoder Position / LSB); title(Integral Separation PI Response); grid on;画出来之后重点看三点正常刹车和紧急刹车模式下电机到达预期目标的响应时间是不是小于 1 秒曲线是否平滑有没有反复穿越目标线的振荡缓慢松刹车模式下曲线是不是接近一条平缓上升或下降的直线。能同时满足这三个状态才说明这套积分分离 PI 算法确实达到了论文说的控制精度和响应速度要求。如果第一次跑还不稳先把控制周期固定成 10ms只用kp把曲线拉到没有大幅超调再加ki、调beta这个顺序能省掉一大半试错时间。本文还有配套的精品资源点击获取