自制STM32智能小车控制板:从Arduino飞线到PCB实战
2026/9/1 7:38:53 网站建设 项目流程

简介:这是一套自制平衡小车控制板项目源文件,面向电子爱好者、嵌入式学习者和硬件开发者,可用于理解两轮自平衡小车的控制板硬件设计,也适合作为高校电子设计竞赛或项目的参考。压缩包内共4个文件,整体约295KB,包含AD格式的原理图(schdoc)与PCB版图(pcbdoc),以及立创EDA的原理图和PCB JSON工程文件,方便在不同设计工具中直接查看、修改和复用。目前已有324人学习下载,内容精简但覆盖完整,可据此学习微控制器引脚分配、电机驱动电路、传感器接口、电源管理以及PCB布局布线等关键环节,对搭建两轮自平衡小车具有直接参考价值。打开原理图能梳理各模块的连接关系,查看PCB版图可了解布局布线要点,而JSON工程文件则便于在立创EDA中继续调整或用于打样,为自制小车改造和二次开发提供良好起点。 前阵子整理云盘,翻出一个名为“河马的自制小车控制板.zip”的压缩包,里面是去年花了整整一个多月做的小项目全套资料——原理图、PCB文件、固件源码、手机遥控App和3D打印底盘的STL模型都在。说句实话,这东西谈不上多高深,核心就是一块完全自己设计、打样、焊板、调通的小车控制板,但折腾它的过程却让我从“只会用模块拼玩具”彻底过渡到了“能独立画板子做系统”。如果你也玩过玩具车,也曾经用一堆杜邦线和Arduino搭过很丑的原型,最后发现根本不够用,那这篇就是为你准备的。

1. 从“嫌弃玩具车”到决定自研控制板:项目缘起

1.1 玩具车套件的痛点

我最早那辆玩具遥控车,是那种几十块钱、带电磁转向功能的便宜货。原厂控制板是封死的,只能跟着原装遥控器玩,别说编程控制,连想给它加个自动避障都无从下手。于是我在网上买了Arduino Nano、L298N电机驱动模块、HC-SR04超声波模块,用杜邦线把它们硬接在一起。这个过程有多痛苦呢?板子上堆了差不多两百根杜邦线,每次改一个功能都要对着接线图查半天;电源也乱,电池正负极被我用鳄鱼夹夹来夹去,稍不留神就反接冒火花。

靠这套飞线方案,原型勉强能跑,但一到实际环境就露馅:电机启动时电流一大,整个系统电压被拉低,Arduino直接复位;杜邦线在震动中松脱,信号时有时无;更别提想把巡线、蓝牙遥控、舵机云台都加上的时候,IO口完全不够用。经验告诉我,模块化堆叠适合验证想法,但当你想做一台“真正能稳定跑起来”的小车时,必须自己画一块整合度更高的控制板。

1.2 目标和技术指标

所以“河马小车控制板”这个项目,立项时定的目标很明确:一版板子把所有常用的功能都整合进去,外接线尽量少,以后的新项目可以直接拿它当底盘平台。硬件规格如下表:

项目规格
主控STM32F103C8T6,72MHz,64KB Flash
电机驱动DRV8833双H桥,支持2路直流电机,可差速转向
供电输入2节18650锂电池(标称7.4V,满电8.4V)
板载稳压5V和3.3V两路
传感器接口超声波、4路巡线、蓝牙、舵机、I2C OLED
扩展接口SWD烧录口、USART1/2排针
板体尺寸60mm x 80mm,四颗M3安装孔

从指标可以看到,这就是一块典型的入门级智能小车主板:不求性能炸裂,但求接口齐全、稳定可靠。用STM32F103C8T6作为核心,是因为它在“性能、价格、资料量”这三个维度上达到了近乎完美的平衡。单片裸片几块钱,淘宝随手能买到,网上例程多到看不完;72MHz主频对普通小车控制来说绰绰有余。对比一下:用Arduino Uno做原型固然方便,但要是把它的芯片直接做到板子上,封装大、引脚少、性能也弱,满足不了后续扩展的需求。

2. 硬件设计:主控、驱动与电源的取舍

2.1 为什么选STM32F103C8T6

很多朋友问我:为什么不直接用ESP32?ESP32确实性能更强还带Wi-Fi,但它的引脚大多不耐5V,外围电路也比STM32复杂一些,对第一次画板的人不那么友好。STM32F103C8T6是LQFP48封装,引脚间距0.5mm,手焊难度虽然略高,但配合助焊剂和拖焊技术完全可以搞定;更重要的是它的3.3V逻辑电源和全板模拟/数字接口都能稳定工作,资料里经常能看到“5V容忍引脚”这一特性,用来接传感器非常方便。

画板时我特意把MCU的关键引脚都引到了排针上,包括UART、I2C、SPI、PWM,以及几个普通GPIO。这样就算以后要做新的实验,也不需要重新打板,从排针飞几根线就能验证功能。这块板子我后来又改了三版,小车的超声波避障、巡线、蓝牙遥控、OLED显示这些功能,都是直接在原有排针上测试通过后才整合进固件里的。

2.2 电机驱动选型对比

小车控制板最关键的电路就是电机驱动。市面上常见方案有三个:L298N、TB6612FNG、DRV8833。我画板前专门列了个表对比:

指标L298NTB6612FNGDRV8833
压降大(约2V)
待机功耗较高
最大驱动电流2A/通道1.2A/通道1.5A/通道
外围电路需要大量电容/续流二极管需要少量电容极少
封装15脚多瓦数SSOP-2416-QFN(带散热焊盘)
价格便宜中等中等

最终选了DRV8833,核心原因是它把两个H桥集成到一个小封装里,逻辑引脚兼容3.3V,省去了电平转换;自带过流保护,电机堵转时不会烧板;驱动小车轮式电机(工作电流不到1A)绰绰有余。封装虽然小,但用热风枪配合助焊剂焊起来不难。

布线时要注意:DRV8833的VM引脚和电机电源进线走线要粗(至少1mm宽),地和逻辑地分开再单点汇合到电池负极,避免电机大电流回流干扰MCU。为了进一步稳住电源,我在VM入口放了一颗470uF电解电容,每颗IC电源脚旁放100nF瓷片电容,实践证明这能解决很多诡异的复位问题。

2.3 电源树与电平适配

整个板子的电源路径是这样设计的:

2 x 18650(7.4V) → 电机VM(DRV8833直供) ↓ 5V LDO(ME6211-5.0) ↓ 3.3V LDO(AMS1117-3.3)

为什么不直接用一颗LDO从7.4V降到3.3V?因为压差太大,比如7.4V降到3.3V,即使电流只有100mA,功耗也有0.4W左右,AMS1117在这种压差下发热明显。用两级降压后,前级负担小,后级输出也更稳定。这里有一点特别提醒:DRV8833的VM必须由电池电压直供,不能和逻辑5V接在一起,否则电机启动瞬间会把5V拉得很低,导致MCU复位。这个坑我在调试时踩过,下面有专节讲。

3.3V主要用于MCU、蓝牙模块、I2C OLED;5V给超声波模块、舵机、巡线传感器供电。蓝牙模块我用的是3.3V逻辑电平的HC-06,配合3.3V供电和3.3V串口,接STM32的USART完全没问题。如果手头HC-05是5V版,建议串口线上加两个电阻分压,避免把芯片打坏。

2.4 引脚分配

我花了比较长时间规划引脚,原则是:PWM通道尽量集中,串口留两个,传感器引脚避开与复用冲突。最终分配如下:

功能引脚说明
电机A PWM/方向PB0 / PB1定时器3通道
电机B PWM/方向PB10 / PB11定时器2通道
超声波 Trig / EchoPA0 / PA1PA1配置普通读IO
巡线传感器PB3、PB4、PB5、PB6数字量/模拟量可选
蓝牙串口PA2(TX)/ PA3(RX)USART2
调试串口PA9(TX)/ PA10(RX)USART1
舵机PWMPA7定时器1通道2
OLED I2CPB8 / PB9I2C1
SWD烧录PA13 / PA14板载4pin排针

这个分配在实际使用中很顺手,特别是把蓝牙串口和调试串口分开,调试时不会互相干扰。注意:如果你用STM32duino,引脚编号和CubeMX里的名字可能不完全一致,源码里全部用了宏定义,改起来很方便。

3. 固件与控制逻辑:从“能跑”到“好开”

3.1 为什么用STM32duino

这块板子的固件我选择用STM32duino(Arduino框架)来写。理由很直白:Arduino的生态太适合快速开发了,PWM、串口、数字IO这些操作都是一行API的事,比直接操作寄存器省太多时间。用HAL库也不是不行,但代码量会明显增加,对刚入门的朋友不够友好。

工程结构上,我用了主循环+定时器中断的经典架构:主循环负责解析串口指令、状态机切换;TIM2定时器每2ms触发中断,负责读取超声波传感器、更新PWM输出、刷新OLED。采用定时器中断来做周期性任务,是避免主循环里忙等导致指令卡顿的关键。

3.2 PWM调速与电机死区处理

电机控制看起来简单,实际有细节。首先PWM频率,我实测在10kHz附近比较合适:低于5kHz时电机会发出明显啸叫,太高又可能超过DRV8833的响应能力。用analogWriteFrequency()把PWM频率设置成10kHz,然后通过analogWrite设置占空比。

另一个经验是电机死区。普通直流减速电机存在启动电压,占空比太低时电机根本不转,但直接输出0又会突然断电,导致小车一顿一顿。我的处理方式是在代码里加一个死区判断:

// 死区补偿:低于阈值时直接输出0 int deadzoneFilter(int speed) { if (abs(speed) < 60) return 0; if (speed > 255) speed = 255; if (speed < -255) speed = -255; return speed; }

这里的60是我实测的启动阈值,不同电机可能不同,接上自己的电机后要重新标定。差速转向逻辑也很简单:左轮速度=基础速度-转向偏移量,右轮速度=基础速度+转向偏移量,偏移量越大转弯越急。

3.3 串口/蓝牙通信协议

小车和手机App之间的通信,我设计了一个很简短的协议:每帧8字节,格式是帧头0xAA、帧头0x55、指令字、数据长度、数据(2字节)、CRC8校验。指令表如下:

指令含义数据说明
0x01前进数据=速度0-255
0x02后退数据=速度
0x03左转数据=偏移量
0x04右转数据=偏移量
0x05停车
0x10开启避障模式
0x11开启巡线模式

CRC8校验很关键。刚开始我偷懒没加校验,蓝牙信号偶尔受电机干扰,出现一个字节错误,小车就莫名左右乱转。加上校验和帧头判断后,误指令基本绝迹。上位机收到正确帧后会返回OK,收到错误帧就返回ERR,方便调试。

3.4 避障与巡线的状态机

避障模式的核心是一段简单的状态机,伪代码如下:

// 避障状态机核心逻辑 enum State { IDLE, FORWARD, TURN_LEFT, TURN_RIGHT, BACKWARD }; State state = FORWARD; void loop() { if (remoteMode) return; // 遥控模式优先 int distCm = readUltrasonic(); // 每100ms触发一次 switch (state) { case FORWARD: if (distCm < 25) { stop(); state = TURN_LEFT; } else { forward(150); } break; case TURN_LEFT: turnLeft(120, 400); // 持续400ms state = (readUltrasonic() > 30) ? FORWARD : TURN_RIGHT; break; case TURN_RIGHT: turnRight(120, 400); state = FORWARD; break; } }

注意超声波触发的间隔一定要大于60ms,否则测距会不稳定。我把Trig引脚放在定时器中断里每100ms触发一次,主循环只读取最新测距值,这样既不会卡住主循环,又能保证触发时序稳定。

巡线模式就简单了:四路巡线传感器输出数字量,我算出一个偏差值,然后做最简单的P控制,把偏差乘一个系数叠加到左右轮速度上。实测效果在黑白胶带场地里很稳定。

4. 制板与焊接调试:踩坑记录

4.1 打样流程

画板用的是立创EDA,从原理图到PCB再输出Gerber下单,整个过程花了三天。第一次打样选择了5片装,价格不到十块钱,典型的低成本打样体验。板子到手后看着还挺精致,2层板、1.6mm厚、银色沉金工艺。焊接前记得先用万用表量一下关键电源网络的电阻,防止PCB加工出现短路。

元件采购方面,BOM表我整理在压缩包里了,大部分是0603封装电阻电容,主控、驱动芯片、稳压芯片都在电商平台买的。这里有个经验:先把主控和驱动芯片这类最难焊的件焊完,再焊电阻电容,最后焊排针和端子,焊接顺序能直接影响成功率和效率。

4.2 焊接经验

STM32F103C8T6的LQFP48封装,手焊其实没那么可怕。我用的方法是:先在焊盘上薄薄涂一层助焊剂,芯片对准后用烙铁稍微固定两个对角,然后顺着引脚方向用拖焊法一次性扫过去。关键点是烙铁温度调到320度左右,焊锡丝用带助焊剂芯的0.5mm细锡丝,先多上一点锡让引脚之间连成一片,再用吸锡带把多余锡吸走,这样焊完引脚干净、不连锡。DRV8833的小封装同理,但要注意底部散热焊盘,焊接时给焊盘也加一点锡,不然芯片悬空会导致过流保护误触发。

4.3 问题一:电机一启动,主板就复位

首次上电调试,小车一跑起来,主板就疯狂复位,现象特别明显:屏幕闪一下,电机突然停,程序从头开始执行。排查链路是这样的:

先用万用表量VM电压,空载时7.4V正常;电机启动瞬间,电压跌到3.2V,这就找到怀疑方向了。再用示波器看MCU的3.3V引脚,也显示跌落,显然问题不是MCU本身,而是整个电源被电机启动电流拉垮。具体原因有两个:一是电机电源走线太窄,只有0.3mm,大电流流过时压降巨大;二是驱动电路的GND和MCU的GND在PCB上连成一片,电机回流电流经过MCU接地网络时产生压差。

修复方式:把电机电源走线全部加宽到1.5mm,在DRV8833的VM和GND之间加470uF

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询