
简介本资源是面向嵌入式初学者与机器人爱好者的一站式平衡车开发套件基于STM32F103 Cortex-M3主控聚焦自平衡控制原理与工程实现解决从硬件搭建、传感器融合到闭环算法调试的核心学习难点。压缩包共50.91MB涵盖原理图PDF、多版本源码库函数版/DMP版/卡尔曼滤波版/精简入门版、算法说明文档、CCD/超声波/NRF24L01外设解析资料、开发笔记及芯片Datasheet等关键内容类型包括电路设计文件、C语言工程代码、技术说明PDF与系统级文档。已有4032人学习下载资源结构清晰突出“理论—算法—硬件—调试”全链路闭环既提供大功率版MiniBalanceV3.5完整硬件设计参考又通过不同滤波策略源码对比展现姿态解算演进逻辑辅以开发视频与问题记录笔记显著降低平衡控制类项目的复现门槛与试错成本。1. 项目概述从“资料包”到一辆能站立的平衡车如果你手头正好有一个名为“平衡小车之家平衡车全套资料STM32F103.rar”的压缩包或者正想从零开始制作一辆属于自己的两轮自平衡小车那么这篇内容就是为你准备的。这不仅仅是一个资料包的简单解压说明而是一个完整的、从硬件到软件、从理论到实践的自平衡车项目深度解析。我们将以这个资料包中常见的STM32F103C8T6俗称“蓝桥杯”或“最小系统板”为核心控制器拆解让两个轮子的小车像“不倒翁”一样站立起来的全部秘密。自平衡车是嵌入式开发、自动控制理论尤其是PID算法和传感器融合的经典入门项目。它麻雀虽小五脏俱全涉及电机驱动、姿态感知、闭环控制、电源管理等多个关键模块。通过这个项目你能实战掌握STM32的PWM输出、定时器编码器模式、中断、串口通信等核心外设更关键的是能深刻理解PID控制器“比例-积分-微分”三个参数是如何相互协作将一个剧烈晃动的系统变得稳定如山的。接下来我们将抛开空洞的理论直接进入如何利用手头的资料和一块STM32让小车真正“站”起来。2. 核心硬件架构与元器件选型解析一套完整的平衡车硬件系统可以看作一个微型的机器人。我们需要感知自身的倾斜角度姿态需要驱动轮子产生运动来对抗倾斜还需要一个“大脑”快速计算并下达指令。下面我们逐一拆解。2.1 主控芯片为什么是STM32F103C8T6资料包通常围绕STM32F103系列尤其是C8T6这款型号。这不是偶然而是由其极高的性价比和足够的性能决定的。STM32F103C8T6基于ARM Cortex-M3内核主频72MHz拥有64KB Flash和20KB RAM。对于平衡车项目它的优势非常明显性能足够平衡车的控制周期即计算一次PID并更新电机输出通常要求在5ms甚至更短比如2ms。72MHz的主频足以在短时间内完成姿态解算涉及浮点或整数运算、PID计算以及外设控制。外设齐全定时器需要至少2个高级定时器如TIM1, TIM8或通用定时器来生成驱动电机的PWM波并且需要配置为互补输出带死区控制以驱动常见的H桥电路保护MOS管。同时还需要定时器工作在编码器模式来读取电机转速用于速度环PID。ADC用于读取电池电压实现低压报警或保护。USART用于调试输出数据角度、角速度、PID输出等或者连接蓝牙模块如HC-05进行无线遥控和参数调试。I2C或SPI用于连接最重要的传感器——陀螺仪和加速度计通常集成在一个芯片里如MPU6050通过I2C通信。生态与成本STM32的HAL库或标准库资料丰富“平衡小车之家”等社区有大量成熟代码参考。C8T6核心板价格低廉降低了项目门槛。注意虽然STM32F103没有硬件浮点单元FPU所有浮点运算都由软件模拟但在优化得当的情况下比如使用arm_math库的定点数版本或将浮点运算转化为整数运算依然能满足实时性要求。这是初期调参时需要注意的。2.2 姿态传感器MPU6050的核心作用与数据融合平衡车能站立的“眼睛”就是姿态传感器。MPU6050或性能更好的MPU9250几乎是标配它集成了三轴加速度计和三轴陀螺仪。加速度计测量的是包括重力加速度在内的所有加速度。在静止或匀速运动时可以通过计算各轴重力加速度的分量来估算车身相对于水平面的倾角。但它对运动加速度比如小车突然启动非常敏感这会导致倾角估算产生巨大误差。陀螺仪测量的是绕各轴旋转的角速度。对角速度进行积分就可以得到角度变化。但它存在“零漂”静止时输出不为零积分误差会随着时间累积导致角度估算越来越偏离真实值。因此单一传感器无法获得稳定、准确的角度。必须采用传感器融合算法最经典且高效的就是互补滤波或卡尔曼滤波。资料包里的代码大概率包含了这两种算法之一。互补滤波原理非常直观。利用加速度计估算出的角度长期稳定但短期噪声大和陀螺仪积分出的角度短期精确但长期会漂移进行加权融合。通常用一句核心代码实现angle 0.98 * (angle gyro * dt) 0.02 * accAngle。其中0.98和0.02是滤波系数dt是采样周期。它的计算量小在STM32F103上运行绰绰有余是入门首选。卡尔曼滤波一种最优估计算法性能通常优于互补滤波但数学模型和参数调整更复杂。资料包若提供通常是已经调好的理解其输入加速度、角速度和输出融合后的角度、角速度即可。2.3 电机与驱动动力系统的关键搭配平衡车的“腿”是电机而“肌肉”是电机驱动模块。电机选型通常使用直流减速电机。减速箱可以降低转速、增大扭矩让小车更有力地抵抗倾斜。编码器是必选项分为光电编码器和霍尔编码器。它安装在电机尾部输出脉冲信号用于测量电机实际转速构成速度闭环。常见的是每圈输出13线即13脉冲的霍尔编码器经过减速箱减速比换算后得到轮子的转速。驱动电路最常用的是TB6612FNG或DRV8833这类双H桥驱动芯片。它们比传统的L298N效率高、发热小。STM32的PWM信号输入到驱动芯片的控制引脚控制电机的转速和方向。这里就涉及到STM32的PWM输出配置特别是如何产生频率可调、占空比可变的PWM。频率选择电机驱动PWM频率通常在5kHz到20kHz之间。频率太低电机会有啸叫声频率太高开关损耗会增加。一般选择10kHz-15kHz是一个平衡点。占空比控制占空比直接对应电机两端的平均电压从而控制转速。PID控制器的最终输出量通常会映射到PWM的占空比值。死区时间当使用高级定时器的互补输出控制H桥的上下管时必须设置死区时间。这是为了防止上下两个MOS管在切换瞬间同时导通造成电源短路而烧毁芯片。死区时间通常设置在几百纳秒到几微秒。2.4 电源管理稳定是一切的前提整个系统通常由一块7.4V或12V的锂电池供电。电源管理模块需要提供电机驱动电压直接或经过稳压后供给电机驱动模块。控制系统电压需要通过降压模块如LM2596、MP1584稳定到5V给STM32核心板、传感器、编码器等供电。STM32F103的工作电压是3.3V通常由核心板上的AMS1117-3.3稳压芯片从5V转换而来。电压监测通过STM32的ADC通道分压后采集电池电压。当电压低于设定阈值如7.4V电池降到6.5V时应让小车缓慢停止或报警防止电池过放。3. 软件控制框架与PID算法深度剖析硬件是躯体软件是灵魂。平衡车的控制软件是一个典型的多环、嵌套的闭环反馈控制系统。3.1 控制回路结构环环相扣平衡车的控制通常包含两个主要的PID环它们以级联的方式工作内环速度环这个环的设定值是期望速度通常由遥控器给定直立时一般为0反馈值是通过电机编码器计算出的实际速度。速度环PID的输出是外环角度环的设定值增量。也就是说速度环的作用是如果你想让它加速前进它就命令车身向前倾斜一点想减速就命令车身向后倾斜一点。外环角度环/直立环这是最核心、最敏感的环。它的设定值是期望角度平衡时就是0度即竖直向上反馈值是MPU6050融合后得到的车身当前倾角。角度环PID的输出直接对应了需要给电机施加的扭矩大小最终体现为PWM占空比。它的作用是发现车身前倾了就命令电机向前转动把车身“拉”回来后倾则向后转动。两个环的输出叠加在一起共同决定了最终的PWM输出。代码结构上在一个定时中断服务函数里例如2ms中断一次按顺序执行以下操作读取MPU6050原始数据进行滤波融合得到当前角度angle和角速度gyro。读取编码器值计算当前速度velocity。执行速度环PID计算speed_out PID_velocity(0, velocity)期望速度0。将speed_out叠加到角度环的期望值上angle_setpoint speed_out这里angle_setpoint通常就是0的偏移量。执行角度环PID计算pwm_out PID_angle(angle_setpoint, angle)。将pwm_out值加载到定时器的比较寄存器更新PWM输出。3.2 PID参数整定手动“调参”的艺术PID控制器的性能完全取决于三个参数比例系数Kp、积分系数Ki、微分系数Kd。调参是平衡车制作中最具“玄学”色彩但也最有规律可循的一步。必须遵循先内环后外环先比例后微分再积分的原则且每次只调一个参数。角度环直立环调参只加Kp将Ki和Kd设为0。用手扶住小车给定一个较小的Kp值比如20下载程序。你会发现松手后小车会向一个方向加速跑出去根本站不住。这是因为Kp的作用是“纠正偏差”倾角越大电机输出越大。但只有Kp小车就像一个反应迟钝的倒立摆总是“过冲”无法稳定。加入Kd微分微分项关注的是角度变化的趋势即角速度。它的作用是抑制振荡相当于给系统增加了“阻尼”。逐渐增大Kd你会发现小车的振荡幅度变小反应变“稳”了。当Kp和Kd配合适当时小车应该能在你手扶的范围内快速摆动并试图保持直立但可能无法长期静止会缓慢地朝一个方向移动。这是因为还存在静态误差。谨慎加入Ki积分积分项是为了消除静态误差。但在直立环中积分项要非常小甚至为0。因为车身角度传感器本身非常敏感微小的积分累积就可能导致输出突变引起系统振荡。通常直立环只用PD控制器就够了。速度环速度环调参首先确保直立环已经能基本稳住小车你可以一直用手轻微扶着。只加速度环的Kp让期望速度为0。增大Kp你会发现小车开始抵抗你的推动。你推它它会朝反方向“顶”你你拉它它会朝反方向“退”。这说明速度环开始工作了它试图将速度维持在0。加入速度环的Ki这是速度环的关键。积分项能累积速度的误差。如果小车在平地上因为微小的倾斜而缓慢移动积分项会逐渐增加输出改变直立环的设定点让车身产生一个反方向的倾斜从而产生一个力来抵消这个移动最终让小车稳定在一点。调大Ki小车“定住”的能力越强但太大也会引起振荡。速度环的Kd通常不需要或者加一个很小的值来抑制高频噪声即可。实操心得调参时务必通过蓝牙模块和上位机如匿名科创地面站、SerialPlot等实时查看角度、角速度、PID输出等波形。观察阶跃响应比如突然用手推一下小车看它是否快速恢复且超调小、振荡少。“看波形调参”比“凭感觉调参”效率高十倍。3.3 代码中的关键实现细节定时器配置系统时钟节拍使用SysTick定时器或一个基本定时器产生一个精确的时基如1ms用于控制整个程序的运行周期和提供dt时间微分值。PWM定时器配置一个高级定时器如TIM1的通道1和通道2为PWM输出模式并启用互补输出和死区插入。关键代码是设置TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1;和TIM_BDTRInitStructure.TIM_DeadTime 72;死区时间数值根据系统时钟计算。编码器定时器配置两个通用定时器如TIM2, TIM3为编码器模式。TIM_EncoderInterfaceConfig(TIMx, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);这样就能自动根据AB相脉冲计数。MPU6050数据读取与融合// 示例读取MPU6050原始数据I2C通信 MPU_Get_Accelerometer(acc_x, acc_y, acc_z); // 读取加速度 MPU_Get_Gyroscope(gyro_x, gyro_y, gyro_z); // 读取陀螺仪 // 互补滤波融合简化版 float acc_angle atan2(acc_y, acc_z) * 57.29578f; // 加速度计计算的角度转换为度 gyro_angle gyro_x * dt; // 陀螺仪积分角度gyro_x需转换为度/秒 // 互补滤波核心公式 float fusion_angle 0.98f * (gyro_angle) 0.02f * acc_angle; gyro_angle fusion_angle; // 更新积分角度用于下一次计算PID算法实现建议将PID写成独立的结构体和函数方便管理多个环。typedef struct { float target; // 设定值 float actual; // 实际值 float err; // 当前误差 float err_last; // 上次误差 float integral; // 积分项 float Kp, Ki, Kd; // PID参数 float output; // 输出值 float integral_limit; // 积分限幅 float output_limit; // 输出限幅 } PID_TypeDef; float PID_Calc(PID_TypeDef *pid) { pid-err pid-target - pid-actual; pid-integral pid-err; // 积分限幅防止积分饱和 if (pid-integral pid-integral_limit) pid-integral pid-integral_limit; if (pid-integral -pid-integral_limit) pid-integral -pid-integral_limit; pid-output pid-Kp * pid-err pid-Ki * pid-integral pid-Kd * (pid-err - pid-err_last); pid-err_last pid-err; // 输出限幅 if (pid-output pid-output_limit) pid-output pid-output_limit; if (pid-output -pid-output_limit) pid-output -pid-output_limit; return pid-output; }4. 常见问题排查与实战调试技巧即使有了完整的资料和代码第一次组装调试也难免遇到各种问题。以下是一些典型的“坑”及其排查思路。4.1 小车根本站不起来直接倒向一边可能原因1电机输出方向错误。这是最常见的问题。角度环计算出的PWM输出符号必须与电机实际转动方向匹配。例如当小车前倾角度为正计算出的PWM输出应为正这个“正”应该对应电机向前转动将小车拉回。如果接线相反小车就会加速倒下。排查用手扶住小车轻微前倾观察轮子是否向前转动。如果不是交换电机驱动芯片上控制该电机的两个PWM输入线如AIN1和AIN2或者直接在代码里对输出值取反。可能原因2MPU6050安装方向或数据符号错误。代码中定义的“前倾角度为正”必须与MPU6050物理安装的坐标系一致。如果传感器装反了或者坐标轴定义错了反馈的角度符号就错了。排查通过串口打印出融合后的角度值fusion_angle。用手将小车明确地向前倾斜观察打印值是否增加变正。如果不是检查MPU6050的安装或者修改代码中加速度计和陀螺仪数据的符号。可能原因3PID参数极不合理。Kp太小无力纠正Kd为负值反而加剧振荡。排查回归最基础的参数。将速度环PID参数全部设为0。角度环只给一个较小的Kp如20和Kd如0.5Ki0。然后用手扶住测试根据小车反应慢慢调整。4.2 小车能站但剧烈振荡“跳舞”可能原因1微分项Kd不足或比例项Kp过大。Kp过大会导致系统反应过激Kd不足则无法抑制这种过激带来的振荡。排查逐步减小Kp同时适当增大Kd。观察振荡频率和幅度是否降低。使用上位机观察角度波形目标是让小车受到扰动后角度波形能快速、平滑地回归零点超调小。可能原因2控制周期不稳定或过长。PID计算和传感器读取必须在严格固定的时间间隔内完成。如果因为中断嵌套、程序阻塞导致周期时快时慢系统必然不稳定。排查在定时中断服务函数入口点翻转一个GPIO引脚用示波器测量其波形看中断周期是否稳定为设定的值如2ms。确保中断函数内代码执行时间远小于中断周期。可能原因3机械结构松动。轮子、电机安装不牢固存在间隙会导致控制指令和实际响应之间存在延迟和不确定性。排查用手晃动轮子和车身检查是否有明显的旷量。紧固所有螺丝确保电机轴与轮子连接紧密。4.3 小车能站立但会缓慢漂移可能原因1速度环的积分项Ki太小或为零。这是最主要的原因。直立环只能让小车不倒但无法保证它的位置。速度环的积分作用才是抑制漂移的关键。排查适当增大速度环的Ki值。注意要非常缓慢地增加因为Ki过大会引起低频振荡。观察小车在平地上从静止到开始缓慢移动的时间这个时间越长说明Ki的“定住”效果越好但反应也会变慢需要权衡。可能原因2MPU6050零点漂移。虽然融合算法能抑制大部分漂移但如果陀螺仪零漂太大融合后的角度仍会有一个缓慢的偏差这个偏差会被速度环积分导致小车朝一个方向走。排查小车静止放在水平面上上电后不移动通过串口观察融合角度值是否长期稳定在0附近。如果有缓慢的线性变化可以在程序初始化时进行简单的校准上电后静止2秒计算这段时间内陀螺仪输出的平均值作为零偏并在后续读数中减去它。4.4 电机启动时抖动或异响可能原因1PWM频率不在电机合适的范围内。频率太低会听到明显的“滋滋”声音频范围内的振动频率太高可能导致驱动芯片发热严重或电机响应异常。排查尝试调整定时器ARR和PSC寄存器将PWM频率调整到10kHz-15kHz范围内再测试。可能原因2死区时间设置不当。死区时间过长会减少有效电压输出导致电机无力死区时间过短则可能无法完全避免上下管直通的风险。排查使用示波器观察驱动芯片输入端的PWM波形看互补的两路信号之间是否有明显的死区间隔。根据驱动芯片数据手册的推荐值进行设置TB6612通常需要几百纳秒。5. 项目进阶与功能扩展思路当你的平衡车能够稳稳站立并抵抗轻微干扰后就可以考虑为其增加更多功能这会让项目更有挑战性和趣味性。5.1 无线遥控与姿态指令通过蓝牙HC-05/06或2.4G无线模块NRF24L01接收遥控指令。可以将指令转化为速度环的目标速度。例如手机APP或遥控器发送前进指令就将目标速度设置为一个正值小车便会自动向前倾斜并前进。关键在于建立一个平滑的目标速度斜坡函数避免目标速度突变导致小车剧烈晃动甚至摔倒。// 示例速度目标斜坡处理 float target_velocity 0; float remote_command 0; // 从串口或无线接收的指令 float ramp_step 0.5f; // 每控制周期增加的速度值 if (remote_command target_velocity) { target_velocity ramp_step; if (target_velocity remote_command) target_velocity remote_command; } else if (remote_command target_velocity) { target_velocity - ramp_step; if (target_velocity remote_command) target_velocity remote_command; } // 将平滑后的 target_velocity 赋给速度环PID的设定值5.2 使用HAL库进行重构与优化很多资料包基于标准外设库SPL编写。你可以尝试用STM32CubeMX初始化项目使用HAL库重新实现。这有助于你理解CubeMX的图形化配置工具并熟悉HAL库的编程模式。虽然HAL库效率稍低但可移植性更好。关键点在于用CubeMX正确配置定时器PWM、编码器模式、I2CMPU6050、USART等并生成代码框架。5.3 探索更高级的控制算法PID虽然经典但并非万能。当小车需要承载变化的负载、在复杂路面行驶时单纯的PID可能表现不佳。可以研究模糊PID将PID参数Kp,Ki,Kd根据误差e和误差变化率ec的模糊规则进行在线调整适应不同工况。串级PID的改进在速度环和角度环之间加入一个“转向环”实现差速控制让小车不仅能走直线还能灵活转弯。基于模型的控制建立小车的动力学数学模型倒立摆模型设计状态观测器和LQR线性二次型调节器控制器理论上能获得比PID更优的性能。5.4 增加视觉或循迹功能为小车加上摄像头如OpenMV、ESP32-CAM或红外/灰度传感器就可以实现颜色追踪、物体跟随或循迹行驶。这需要引入另一个控制维度——转向控制。核心思路是根据图像或传感器信息计算出偏离路径的误差将这个误差通过一个单独的转向PID环输出为左右轮的速度差。同时整体的前进速度仍由遥控或定速控制。这就构成了一个双输入速度、转向偏差、双输出左轮PWM、右轮PWM的混合控制系统。从解压一个“平衡小车之家”的资料包到亲手调校出一辆反应灵敏、运行稳健的自平衡车这个过程是对嵌入式系统开发能力的一次全面锻炼。它强迫你去理解硬件时序、传感器特性、控制理论以及软件架构的协同。最宝贵的经验往往来自于调试当你看着波形图一点点调整参数最终看到小车从东倒西歪到稳稳立住的那一刻那种对“反馈”、“闭环”、“稳定性”的理解是任何教科书都无法给予的。建议你在基本功能实现后不要止步尝试去改动算法、增加功能甚至重新设计机械结构每一次挑战都会让你对这套系统的认识更深一层。本文还有配套的精品资源点击获取