平衡小车开发全套资料:STM32、AD09与蓝牙遥控实战解析

发布时间:2026/9/1 15:35:26
平衡小车开发全套资料:STM32、AD09与蓝牙遥控实战解析 简介本资源是一套完整的STM32平衡小车软硬件开发套件面向嵌入式初学者、电子设计竞赛备赛者及智能车项目实践者覆盖自平衡控制核心原理与工程落地全流程。资源包含AD09设计的10张模块化原理图如AHRS姿态传感、蓝牙通信、电机驱动、主控与电源系统、对应PCB文件及BOM清单两套独立MCU源码——运动控制STM32F103RCT6与姿态解算STM32F103C8T6以及可直接安装调试的安卓蓝牙遥控器APK与完整Java源码。压缩包共351个文件含75个.h头文件、71个.c源文件、37个.o编译中间文件及多个.uvproj工程配置辅以实物图、3D结构图与电路板照片便于理解硬件布局与软件分层架构。目前已有339人学习下载资料结构清晰、模块解耦明确支持从传感器数据融合、PID闭环调参到移动端指令下发的全链路验证是掌握惯性导航、实时控制与跨平台通信的高实用性学习样本。 一提平衡小车很多人第一反应是“这不就是陀螺仪加电机驱动的经典项目嘛”但真上手过的人都知道网上的资料大多数只给了一半要么只有原理图要么只丢一份工程代码或者是手机APP源码压根不完整。而这个项目资料包是少见的“三件套齐全”——AD09设计原理图和PCB、STM32单片机软件源码、安卓蓝牙遥控器APK及源码硬件、固件、手机端一条龙拿来就能照着做也能拆开逐模块学习。这套资料的适用人群很明确正在学STM32的学生、刚入行的嵌入式工程师、以及想在电子制作比赛里快速出作品的爱好者。如果你能把这套资料吃透你等于完整走了一遍“传感器采集→姿态解算→闭环控制→无线通信→手机端交互”的全链路开发过程这比单纯看教程有价值得多。1. 资料全景拆解一个平衡小车项目到底包含哪几块1.1 硬件设计资料AD09原理图PCB这套资料的硬件部分用AD09Altium Designer 2009设计。很多人纠结要不要升级到AD20、AD21其实对于平衡小车这种规模的板子AD09完全够用而且不少学校、公司的旧版本兼容环境还在用09。关键在于AD09能打开工程文件也能直接输出Gerber文件发给工厂打样这点老归老但干活没问题。原理图里大致包含这几块STM32最小系统F103C8T6或者兼容型号、MPU6050六轴传感器、TB6612电机驱动、HC-05蓝牙模块、电机编码器接口、电源管理、按键和指示灯。把这些外设电路吃透后你会发现它其实是一个“最小系统传感器驱动通信”的通用模板以后做智能小车、机械臂、云台都能复用。PCB部分可以拿来做两件事第一是直接打样焊接按BOM清单买物料就能复现整机第二是当作布局布线的学习样本看别人怎么处理电机大电流线路、晶振位置、电源滤波电容的摆放。这一点反而最值钱因为很多新手画板子能亮灯但跑电机之后系统老复位根源就是布局布线经验不足。1.2 STM32软件源码从驱动到控制闭环的关键路径软件源码是这套资料的灵魂。它不止是“点灯”级别的例程而是覆盖了从底层寄存器配置到上层控制算法的完整链路。工程里最核心的模块有MPU6050初始化与角度读取、陀螺仪和加速度计数据处理、编码器测速、PWM输出、PID控制器、蓝牙串口协议解析。我特别看重代码里的“控制节拍”设计。平衡小车是一个典型的实时控制系统姿态环至少要跑到1kHz才能稳速度环和转向环一般100Hz就够。源码里通过定时器中断来区分任务粒度这个架构思路比具体某行代码更重要。你只要看懂了这个架构将来做四轴、平衡机器人、自稳云台思路完全通用。另外源码最好用标准外设库版本因为网上教程多、排查问题时资料好找。如果资料里恰好是HAL库的版本问题也不大重点是看控制逻辑跑通了之后你完全可以用自己习惯的库重写驱动层。1.3 安卓蓝牙遥控APK及源码手机秒变遥控器安卓端这部分资料包里同时给了已签名的APK和完整工程源码。APK可以直接装到手机上试用省去配置环境的时间源码则方便你改遥控界面、加功能、换成自己的按键布局或通信协议。APP实现的功能一般包括前后左右方向控制、速度加减、急停、转向微调。这些功能背后对应一套简单的串口协议比如特定帧头加指令字加校验位单片机能解析、执行、回传状态。手机通过经典蓝牙SPP协议和HC-05模块通信这套方案成熟稳定代码量不大适合入门级蓝牙开发。如果你是做安卓开发的新手这个APP的源码价值也很高。它涵盖蓝牙权限申请、设备扫描、配对连接、Socket读写线程、UI事件处理、数据分包粘包处理这些正好是安卓蓝牙应用开发的全部核心点。2. 硬件核心设计AD09里怎么画好一块平衡车驱动板2.1 主控与外设选型及原理图设计要点先看主控。这类项目最经典的选择是STM32F103C8T648脚、64KB Flash、20KB RAM性能做平衡车绰绰有余价格也便宜。选它还有一个好处——资料极多哪怕你完全没用过STM32网上随便搜都能找到入门教程避免“入门即放弃”。原理图设计时最小系统要做扎实8MHz主晶振加两个20pF负载电容复位电路用10k电阻加100nF电容BOOT0和BOOT1都要通过10k电阻下拉到地。电源引脚旁边放0.1uF去耦电容每个VDD一组芯片底部的VSSA、VDDA这些模拟电源也要接好不能悬空。这些细节看着琐碎但真遇到“程序跑飞、偶尔死机”的毛病大部分问题都出在这些小地方。MPU6050通过I2C接口连接SDA和SCL必须加上拉电阻一般用4.7k一组到3.3V。这里有个关键坑点I2C地址由AD0引脚决定AD0接地时地址是0x68接高电平是0x69读不到数据时先查这个引脚。INT引脚最好接到STM32的一个普通GPIO方便后续用中断方式读取数据比轮询方式省CPU。电机驱动部分TB6612FNG是主流选择。它比L298N体积小、压降小、效率高用在7.4V两节锂电池供电场景下非常合适。控制脚需要6个GPIO两个PWM引脚控制左右电机速度AIN1/AIN2、BIN1/BIN2控制方向逻辑。注意TB6612的逻辑电源VCC接3.3V还是5V要和单片机IO电平匹配避免逻辑电平不兼容导致电机乱转。2.2 电源系统与电机驱动的布局布线经验电源方案我见过最多的是两节18650锂电池串联标称7.4V直接给电机驱动供电。控制板需要5V和3.3V所以板上至少两级降压常用的做法是先用一颗低压差线性稳压器降到5V给逻辑电路和传感器再通过AMS1117-3.3降到3.3V给单片机。如果电机电流大导致电压跌落明显建议用开关降压模块先把电压稳到5V再线性降到3.3V这样系统更稳。这里教大家一个估算方法电机在堵转状态下电流可能到1A到2A如果两路电机同时大电流瞬时电流到3A到4A很正常。所以PCB上电池到电机驱动的电源线、以及电机驱动到电机的输出线线宽至少要100mil以上最好直接铺铜皮或者加开窗覆锡。普通信号线可以走10mil左右但功率线绝不能按信号线的标准来。我在第一版板上就吃过亏电源线走细了电机一加速单片机就复位。布局上电机驱动和电源部分要尽量靠近电池输入接口并远离天线、传感器和晶振。大电流线路的去程和回程要短而粗形成环路面积尽量小这样可以减少对外辐射干扰。电机接线端子边上放一颗100uF电解电容和一颗0.1uF瓷片电容用来吸收电机换向时产生的反电动势尖峰这一步对系统稳定性帮助极大。2.3 PCB抗干扰设计哪些细节直接影响稳定性平衡小车是典型的“功率电路和敏感电路共存”的板子电机产生的电磁干扰很容易通过电源和地线窜进传感器和单片机导致姿态数据跳动甚至程序死机。所以布板时有几条原则必须守。一是电源和地线分开处理。模拟地、数字地、功率地不要直接大面积铺在一起而是在某一点单点连接。一般做法是分别在原理图里用0欧电阻或磁珠把模拟地和数字地隔开PCB上功率地单独走最后在电池负极处汇合。这样电机电流的突变不会直接干扰到MPU6050和单片机的参考地平面。二是去耦电容的位置要正确。每个芯片的电源引脚都要有0.1uF瓷片电容并且要放在芯片电源引脚附近走线要先过电容再到芯片的VDD引脚。大容量的电解电容放在板子电源入口处起到储能和滤波作用。电容放得不对等效于没放高频噪声照样进芯片。三是晶振和I2C线的处理。8MHz晶振要尽量靠近STM32的OSC_IN和OSC_OUT引脚晶振下方不要走其它信号线最好在晶振区域铺地。I2C总线的SDA和SCL线尽量短如果板子空间大、走线长可以在靠近MPU6050那一端再加一组4.7k上拉以增强驱动能力。最后蓝牙模块的天线区域下不能铺铜不然天线被地平面屏蔽蓝牙连接距离会明显缩短。3. STM32软件源码三环控制闭环实现细节3.1 初始化与主循环任务架构这套源码的整体架构是“主循环定时器中断”的模式。上电后先把时钟配置到72MHz然后依次初始化GPIO、I2C、串口用于蓝牙和调试、定时器用于PWM输出和编码器计数、外部中断接收遥控数据。主循环里跑的通常是一个状态机比如待机、自检、平衡、遥控、急停。状态之间通过按键或者蓝牙指令切换。这种状态机的好处是后续扩展功能非常方便想加一个“充电状态”或者“学习模式”只需要加一个枚举值再补一个分支。关键的实时控制逻辑放在定时器中断里。常用的分配方式是这样的1ms中断里做直立环控制读MPU6050姿态数据、算出倾角和角速度、执行PID计算、输出PWM占空比到电机驱动10ms中断里做速度环和转向环读取编码器累计值、计算当前车速、累加速度误差、更新直立环的目标角度。把实时性要求高的任务放进高频中断把低频任务放在低频中断或主循环CPU占用率低控制响应又及时。这里有一个很多人忽视的点中断里不要做耗时操作比如串口打印、OLED刷新、复杂浮点运算尽量少做或者移到主循环。我见过不少人把姿态解算的浮点运算全堆在1ms中断里结果中断还没跑完下一次中断又来了系统直接卡死。3.2 MPU6050姿态解算DMP与互补滤波怎么选MPU6050自带DMP数字运动处理器可以直接输出四元数再转换成欧拉角精度和稳定性都够用。使用方法是在初始化时向DMP加载固件、配置采样频率和FIFO然后用条件判断检测新数据从FIFO读出四元数调用姿态转换函数得到Pitch、Roll、Yaw。DMP方案的好处是省掉复杂的滤波算法代码量也小比较适合新手快速跑通。如果你想做深一层或者硬件上INT引脚没接可以自己写互补滤波。思路很简单加速度计解算出的倾角长期稳定但短期噪声大陀螺仪积分得到的角度短期准但会漂移。把两者按比例融合比如姿态角等于0.98乘上一次角度加陀螺仪角速度乘时间间隔加0.02乘加速度计解算角度这就是最基础的互补滤波。代码不超过十行效果已经能跑。我个人的建议是先跑DMP确认整个系统没问题再尝试换成互补滤波对比一下两种方案在振动环境下的表现差异。这种对比学习的收益非常大因为你能直观理解“为什么传感器融合能互补缺陷”。另外上电后一定要做陀螺仪零偏校准让小车静止几秒钟采集若干帧陀螺仪数据求平均值作为零偏否则小车即使放平也会朝一个方向缓慢旋转这就是零漂在捣乱。3.3 三环PID控制直立环、速度环、转向环的执行逻辑平衡车的控制核心是串级PID通常由三个环组成。直立环是基础目标是让小车维持竖直状态速度环负责让小车能稳定在原地或按给定速度移动转向环控制小车转向让左右轮按需求产生转速差。直立环本质上是一个PD控制器。输入是当前倾角和目标倾角默认0度附近输出是让小车向直立方向运动的力矩这里通过左右电机的PWM占空比实现。Kp决定“纠正倾角的力度”Kd对应对角速度的阻尼用来抑制震荡。直立环输出的是PWM基值速度环的输出会对直立环的目标角进行微调让小车通过前倾或后仰产生前进或后退的加速度。速度环通常用PI控制器。输入是当前速度和目标速度输出是一个角度修正量叠加到直立环的目标角度上。举个例子目标速度为0但小车被外力推开往前移动了速度环检测到正速度误差输出一个负向角度修正让小车往后仰产生一个反向加速度把车拉回来。这里积分项很关键用来消除稳态误差但积分必须限幅否则积分饱和后小车会猛冲。转向环的输入是左右轮编码器转速差输出是左右电机PWM的差量一般用PD控制就够。PID参数整定方法我在后面单独讲。这里只提醒一点三个环的优先级不要搞反直立环越稳速度环和转向环越容易调。如果直立环还在震荡别急着去调速度环。3.4 编码器测速与PWM输出细节测速方式上这套资料基本会选择定时器的编码器模式。STM32的TIM2、TIM3、TIM4可以工作在编码器接口模式两个通道接电机编码器的A、B相输出硬件自动判断方向和计数。这样CPU不用额外处理外部中断代码简单计数精度也高。接法上注意A、B相不要接反如果方向反了只需要软件里把计数值取负或者交换接线。编码器计数频率要和控制周期匹配。比如1ms控制周期内读取一次编码器值然后求差换算成当前速度。换算是关键编码器线数乘减速比再除以一圈的脉冲数才能得到真实转速。常见电机比如1:30减速比配13线霍尔编码器电机轴转一圈编码器输出13乘4倍频个脉冲输出轴一圈是13乘4乘30就是1560个脉冲。这个换算关系不搞清楚速度环参数会一直调不出来。PWM输出这边频率建议设置在20kHz左右。频率太低电机转动噪声大出现可听见的“吱吱”声频率太高驱动芯片开关损耗增加MOS管发热。20kHz正好超出人耳听觉范围电机安静且驱动效率高。输出占空比时要注意电机存在死区电压尤其是小占空比时电机根本不转。解决办法是在软件里设置一个最小占空比偏置让输出低于死区时直接给到死区附近这样启动会顺滑很多。4. 安卓蓝牙遥控器APK及源码开发要点4.1 蓝牙通信方式选型经典蓝牙SPP和BLE差异HC-05是市面上最常见的蓝牙串口透传模块使用的是经典蓝牙SPP串口配置文件。SPP的底层就是模拟串口传输单片机端发串口数据手机端就能收到反之亦然。这套方案成熟、兼容性好而且安卓系统把SPP的UUID固定封装好开发时直接用标准串口UUID就能连接。BLE低功耗蓝牙则是另一种思路优点是功耗极低适合穿戴设备、传感器节点但它和SPP不兼容HC-05也不支持BLE。如果你想把APP改成BLE版本就得换BLE模块比如CC2541或者JDY-23这类。对于平衡车这种需要持续双向通信、距离要求不高的场景经典蓝牙SPP完全够用而且稳定。所以决策很简单先用HC-05搭配SPP跑通整个项目如果后续想做低功耗和小体积再考虑BLE方案。不要在第一步就卡在选型上。4.2 安卓权限设置与设备连接流程开发安卓蓝牙应用最闹心的是系统权限。老版本只需要BLUETOOTH和BLUETOOTH_ADMIN两个权限但Android 6.0之后如果要搜索设备需要申请定位权限Android 12之后又把蓝牙权限拆分成了BLUETOOTH_SCAN、BLUETOOTH_CONNECT、BLUETOOTH_ADVERTISE运行时还需要动态申请。如果你的APK编译版本比较新不处理这些权限扫码搜不到任何设备是必然的。连接流程整体是这样先检查设备是否支持蓝牙、蓝牙是否开启然后获取所有已配对设备列表找到HC-05模块名称比如“HC-05”或修改过的自定义名称再通过BluetoothDevice.createRfcommSocketToServiceRecord(UUID)创建一个SocketUUID固定用“00001101-0000-1000-8000-00805F9B34FB”这是SPP服务的标准UUID最后调用connect()建立连接。连接有几个容易踩的坑。第一连接必须在子线程里做不能在主线程跑否则一旦设备暂时不可达界面直接ANR。第二如果设备在已配对列表里但连接失败可以尝试取消配对后重新配对部分HC-05模块的配对缓存会导致连接异常。第三HC-05默认配对密码是1234个别出厂版本是0000配对时输入正确密码才有可能成功。连接成功之后通信就是标准的输入输出流操作。发送指令时把命令字符串按约定格式编码后写入OutputStream接收数据时在独立线程里循环读取InputStream。注意安卓端的输入流读取要处理半包和粘包问题最简单的处理方式是规定每帧数据以固定长度或换行符结尾。4.3 遥控器UI与通信协议设计APP的界面不用复杂但布局要实用。推荐这样安排屏幕中央一个大方向控制区域包含前进、后退、左转、右转四个按钮右侧放一个速度滑条或者加减速按钮底部放急停、回中两个大按钮。按钮的点击和长按事件要区分开来比如点击一下发送一次运动指令长按持续发送当前运动指令松开时发送停止指令。这种交互逻辑在写代码时要理清楚否则操作起来很别扭。通信协议要简单可靠。常见做法是定义一个固定格式的字符串比如“CMD:FORWARD:100\n”或者更紧凑一些用单字节命令加参数“F100”“S0”“X”等等。单片机端解析时先判断帧头再取命令字最后解析参数。校验位可以先用最原始的“帧尾加换行”来保证帧完整性复杂业务等以后真需要再加密校验。协议设计的原则是尽量让单片机端解析代码简单因为单片机资源有限APP端可以把更多的字符串处理工作做掉。比如直接发整型的ASCII码单片机能用sprintf和sscanf轻松处理。如果你发二进制数据反而要处理字节序问题比较容易把新手绕晕。另外调试时建议在APP里加一个“连接状态”显示和“收发日志”窗口把发送和接收的原始数据展示出来。这样单片机端有什么问题你能立刻看出来是数据没发出去、发送格式错误、还是单片机没响应。这个日志窗口虽然不起眼但排查问题能省一半时间。5. 平衡车调试实战常见问题与排查技巧5.1 PID参数整定的实操顺序与注意事项PID参数整定是平衡车的头号难关很多人卡在这一步就放弃了。其实整定顺序比参数本身更重要按下面的路径走成功率很高。第一步先只调直立环。把速度环和转向环的PID输出暂时屏蔽掉只让直立环工作。初始Kp给一个比较小的值比如10到30Kd给0。上电把小车放在平衡位置附近观察它是往一个方向倒还是来回震荡。如果小车软绵绵没有回正力就加大Kp直到小车能明显感觉到“用劲”维持直立如果小车还在震荡就慢慢加Kd增加阻尼直到车身基本稳定只有轻微抖动。这里有个经验值Kp加大后如果出现高频震荡Kd至少要加到Kp的10到30倍才能压住。第二步加速度环。把小车放到地上关闭遥控让速度环激活。速度环Kp先从小值开始比如0.1到0.5观察小车会不会慢慢朝一个方向跑。如果小车朝一个方向漂移说明需要积分项来修正慢慢加Ki。小车能稳定在原地不跑速度环就成功了。注意速度环的输出要限幅修正角度的范围最好不要超过正负3到5度限制太大会让直立环饱和。第三步调转向环。让小车原地转起来观察它转得是否顺滑、是否回中。转向环一般也是先加Kp再加Kd参数值比直立环小一两个数量级很正常不用慌。调参时建议用串口打印或蓝牙回传实时数据。把目标角度、当前角度、PID输出、电机PWM值打印出来你就能看到输出的变化曲线比盲调高效得多。建议每调一次参数保存一次记录数据化调参不要“感觉好像更稳了”就乱继续。5.2 蓝牙通信故障排查从连接不上到数据乱码蓝牙连接不上最容易出的问题有三个。第一个是模块供电电流不够。HC-05工作电流大概在30mA到50mA如果板子上稳压芯片余量不足模块上电后无法正常广播手机自然搜不到。排查方法很简单单独给模块供电试试搜不到说明模块有问题或供电不足。第二个是波特率不匹配。HC-05默认波特率常见9600但很多资料代码里用的是115200。手机端APP发送数据用的是UART字节流单片机端直接用串口接收如果两边波特率不一致收到的数据就是乱码。可以在USB转TTL上先用AT指令查询模块当前波特率再统一修改传输层参数。第三个是配对后无法建连。如果手机端已经配对成功但APP点击连接后一直转圈大概率是UUID配置不对或者同一模块被多个手机连接导致连接占用。解决方法是先用“恢复出厂设置”AT指令把模块清干净再重新配对APP代码里确认UUID是SPP标准值。数据乱码还有一种情况APP发送的字符串编码格式和单片机解析格式不一致。比如APP发送UTF-8中文单片机按ASCII逐字节解析完全没有意义。所以协议设计时建议全部用ASCII可见字符不要发中文不要发特殊符号这是最省心的方案。5.3 电源跌落与电磁干扰导致的疑难问题平衡车调试到后期遇到的问题往往不是算法而是供电。最典型的故障是电机一加速单片机就复位或者MPU6050数据跳变。原因就两个电池电压被拉到单片机复位阈值以下或者电机PWM产生的地弹噪声干扰了传感器。电压跌落问题可以通过实测确认。用万用表或者示波器测量单片机VDD处的电压电机高速转动时如果电压低于3.0V基本就是电源压降太大。解决办法是加强电源路径电池用动力型18650不要用旧电池电源线加粗在电机驱动VM引脚附近加大容量电解电容到470uF甚至1000uF必要时用开关降压模块替代线性稳压器。电磁干扰导致的数据跳变特征是电机转的时候MPU6050的Roll和Pitch偶尔跳一下停下来就正常。处理思路是硬件和软件双管齐下。硬件方面在电机驱动板的电源输入端加共模电感或者磁珠电机本体上并一个小容量的100nF陶瓷电容直接焊在电机端子上软件方面读取MPU6050数据后加中值滤波或滑动平均滤波把偶发的尖峰滤掉。注意滤波器不要加太狠否则姿态数据滞后直立环反而会抖。最后再分享一个小技巧调试平衡车时最好准备一个可调直流稳压电源先不要用电池。因为稳压电源可以设定电流上限如果程序写错导致电机堵转电流限制能避免烧器件。等到控制参数都整定好了再换电池做整机测试。这个习惯帮我避免了很多次“焊完板子一上电就冒烟”的尴尬场面。这套资料能扩展的方向其实不少。比如给小车加一个OLED显示屏显示姿态和电池电压或者加超声波模块做避障再或者把手机端改成手势控制。我个人的体会是参考项目最好的用法不是“照抄跑通就算完”而是把它拆开——硬件直接看布线思维固件看控制任务划分APP看蓝牙通信协议设计——每一块都值得单独学到透。等你把这三部分吃透了再做任何带电机、带传感器的移动机器人项目心里都会有底。本文还有配套的精品资源点击获取