拓冰建站拓冰建站
首页 / 资讯中心 / 正文

STM32智能小车实战:PID循迹与超声波避障开源项目解析

这次我们来看一个非常适合电赛和嵌入式入门实战的开源项目STM32 智能小车资料包。项目核心不复杂但覆盖面很完整PID 循迹、超声波避障、距离跟随、蓝牙遥控、HCSR04 测距、TB6612 电机驱动、SG90 舵机控制全部集成在同一套小车平台上。如果你正在备赛、上单片机课程或者想把手里的 STM32 开发板变成一辆能跑、能躲、能跟、能遥控的小车这套资料可以直接作为起点。先说最值得关注的几个点整份资料以开源形式发布包含工程源码、接线说明和功能测试思路控制逻辑不是硬编码“死走”而是用 PID 做速度和方向闭环后期调参数是重点硬件选型都是淘宝能直接买到的常用模块成本可控功能之间通过状态机切换循迹、避障、跟随、蓝牙可以共存在一套主程序里不需要改接线就能切换模式。本文不会只贴一个“下载链接”就结束。我会把这套小车的功能拆开讲清楚每个模块解决什么问题、接线怎么排、驱动层怎么写、核心逻辑怎么实现、调 PID 时看哪些数据、遇到车不走直或者超声波读数异常时怎么排查。文章末尾会给出电赛场景下的工程化建议。1. 核心能力速览能力项说明项目类型STM32 智能小车嵌入式实战项目控制芯片STM32F103 系列为主具体型号以资料标注为准主要功能PID 循迹、超声波避障、距离跟随、蓝牙控制、HCSR04 测距、SG90 舵机控制电机驱动TB6612双路 H 桥支持 PWM 调速测距传感器HCSR04 超声波模块舵机SG90用于超声波探头扫描方向循迹传感器常见三路/五路红外循迹模块五路在复杂赛道更稳通信方式串口/蓝牙模块常见 HC-05/HC-06 方案开发环境Keil MDK STM32 标准外设库/固件库配合 ST-Link 下载调试上位机调参支持串口打印配合 Vofa 等工具观察 PID 波形适合场景电赛备赛、STM32 学习、智能车入门、毕业设计需要说明一点这套资料的源码是基于轮式差速小车写的。底盘是两个电机加一个万向轮的结构转向靠左右轮转速差实现这也是多数电赛智能小车和入门循迹小车最通用的结构。2. 适用场景与使用边界这个项目适合三类人第一类是电赛备赛队伍。智能小车类是电赛常见题型方向资料里踩过的坑、写好的驱动、PID 调参思路能省很多前期时间你只需要根据自己的赛道和传感器布局去改参数。第二类是正在学 STM32 的在校学生。HCSR04、TB6612、SG90、蓝牙这些模块是嵌入式基础外设的集合作业把每个模块驱动读懂比自己从头啃芯片手册轻松很多。第三类是做课程设计或毕业设计的同学。题目往往是“基于 STM32 的智能循迹避障小车”这套资料基本可以覆盖题目的功能要求再补一些显示、调速、状态指示就能成稿。使用边界也很明确这套资料不是拿来就能用的商业成品。它需要你自己去熔焊接线、烧录程序、根据实际赛道调 PID 参数。不同底盘、轮胎摩擦系数、电机减速比会直接影响循迹效果换一块板子或换一套轮子之后原来的 PID 参数大概率要做调整。还有一条合规和安全边界必须强调智能小车在实验和比赛场景下使用没有问题但改装遥控模型、在公共道路上测试或让他人不明所以地被小车跟随都不合适。调试时注意防止电机堵转过热锂电池充电和放电要按规范操作飞线多的地方先断电再改接线避免短路。3. 硬件平台与环境准备3.1 硬件清单一套完整可跑的最小系统至少需要这些模块型号/规格用途主控板STM32F103C8T6 / F103RCT6 最小系统板逻辑控制电机驱动TB6612FNG驱动左右两路直流电机直流电机带减速箱的 TT 电机或类似 6V 电机提供动力超声波模块HCSR04测距、避障、跟随舵机SG90 180 度控制超声波探头朝向循迹模块三路或五路红外循迹传感器检测黑线蓝牙模块HC-05/HC-06手机遥控降压模块如 MP1584 或 AMS1117 组合给主控和传感器供稳定电压电池2S 锂电池 7.4V 或 4 节 AA 电池盒整车供电下载器ST-Link V2烧录程序资料中的电源方案建议把电机电源和逻辑电源分开处理。TB6612 的 VM 接电池电压VCC 接 3.3V 或 5V逻辑部分和电机部分共地这样电机启动瞬间的压降不会把一个单片机直接拉复位。3.2 软件环境开发环境推荐用 Keil MDK 5配合 ST-Link 驱动使用。工程建议基于 STM32 标准外设库建立也可以直接使用 STM32CubeMX 生成 HAL 库工程再移植驱动代码。无论用哪种方式都需要确认三件事Keil 里安装了对应芯片型号的 Device PackST-Link 驱动已经装好下载器能识别目标板工程里已经正确添加标准外设库或 HAL 库文件。常见问题是新装 Keil 之后没有安装 STM32F1 系列的 Pack编译时报 cannot open source file 或者烧录时无法识别芯片。解决方法是到 Keil 的 Pack Installer 里选择 STM32F1xx 系列安装或者按“STM32 芯片包官网下载流程”手动下载离线包再导入。3.3 工程结构建议建议把代码按模块拆分不要所有逻辑堆在一个main.c里。推荐结构如下Project/ |-- USER/ // main.c, stm32f10x_it.c |-- HARDWARE/ | |-- motor.c/h // TB6612 电机驱动 | |-- ultrasonic.c/h // HCSR04 测距 | |-- servo.c/h // SG90 舵机控制 | |-- tracking.c/h // 循迹传感器读取 | |-- bluetooth.c/h // 蓝牙串口命令解析 |-- SYSTEM/ // 时钟、延时等基础文件 |-- PID/ | |-- pid.c/h // PID 控制器 |-- CORE/ |-- OBJ/这样的好处是调试时只改一个模块不用全局找代码换传感器型号时也只替换对应驱动文件。4. 核心模块接线参考接线是新手最容易翻车的环节。下面给出一套常见接线参考具体引脚以你手里的资料和开发板丝印为准。4.1 TB6612 电机驱动接线TB6612 引脚接 STM32PWMATIM 通道输出引脚控制左电机速度AIN1 / AIN2普通 GPIO控制左电机方向PWMBTIM 通道输出引脚控制右电机速度BIN1 / BIN2普通 GPIO控制右电机方向VM电池正极VCC3.3V 或 5V 逻辑电源GND公共地STBY接 STM32 GPIO 高电平或直接接 VCC禁用低电平TB6612 比传统 L298N 好的地方是压降小、发热低适合两节锂电池直接供电。注意 STBY 引脚如果被拉低整个驱动芯片会进入待机状态电机完全不动。排查“电机不转”时要先量这个引脚电压。4.2 HCSR04 超声波接线HCSR04 引脚接 STM32VCC5VGND公共地TRIG触发引脚普通 GPIO 输出ECHO回波引脚需要支持输入捕获或用 GPIO 模拟测宽HCSR04 的 ECHO 引脚返回的是 5V 高电平脉冲如果 STM32 引脚不是 5V 容忍引脚建议串联电阻分压后再接避免长期使用损坏引脚。4.3 SG90 舵机接线SG90 引脚接 STM32红线5V棕线GND橙线TIM 通道输出引脚50Hz PWMSG90 对 PWM 周期敏感需要 50Hz 的脉宽调制信号0.5ms 到 2.5ms 的脉宽对应 0 度到 180 度。大多数资料会让超声波探头固定在舵机臂上需要避障时舵机摆动扫描左、中、右三个方向。4.4 蓝牙模块接线蓝牙模块引脚接 STM32VCC3.3V 或按模块要求接 5VGND公共地TXD接 STM32 的 RX 引脚RXD接 STM32 的 TX 引脚交叉连接是重点蓝牙的 TX 接单片机的 RX蓝牙的 RX 接单片机的 TX。如果接成同向串口数据完全收不到。HC-05 和 HC-06 的注意点还不太一样HC-05 有 AT 模式可以改名字和主从角色HC-06 一般只能做从机手机直接配对使用。5. 基础驱动层实现资料里所有功能到最后都落到底层驱动上。先用标准外设库风格写几个关键驱动代码帮助你理解框架具体引脚宏定义需要按你的资料替换。5.1 电机 PWM 驱动TB6612 需要两路 PWM 和一个方向控制引脚。以 TIM2 输出 PWM 为例#include stm32f10x.h #define MOTOR_PWM_GPIO GPIOA #define MOTOR_PWM_PIN GPIO_Pin_1 #define MOTOR_AIN1_GPIO GPIOB #define MOTOR_AIN1_PIN GPIO_Pin_0 #define MOTOR_AIN2_GPIO GPIOB #define MOTOR_AIN2_PIN GPIO_Pin_1 void Motor_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin MOTOR_PWM_PIN; GPIO_Init(MOTOR_PWM_GPIO, GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin MOTOR_AIN1_PIN | MOTOR_AIN2_PIN; GPIO_Init(MOTOR_AIN1_GPIO, GPIO_InitStructure); } void Motor_PWM_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; OCInitTypeDef OC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseStructure.TIM_Period 999; TIM_TimeBaseStructure.TIM_Prescaler 71; TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure); OC_InitStructure.TIM_OCMode TIM_OCMode_PWM1; OC_InitStructure.TIM_OutputState TIM_OutputState_Enable; OC_InitStructure.TIM_Pulse 0; OC_InitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC1Init(TIM2, OC_InitStructure); TIM_Cmd(TIM2, ENABLE); } void Motor_SetSpeed(int16_t speed) { if (speed 0) { GPIO_SetBits(MOTOR_AIN1_GPIO, MOTOR_AIN1_PIN); GPIO_ResetBits(MOTOR_AIN2_GPIO, MOTOR_AIN2_PIN); } else if (speed 0) { GPIO_ResetBits(MOTOR_AIN1_GPIO, MOTOR_AIN1_PIN); GPIO_SetBits(MOTOR_AIN2_GPIO, MOTOR_AIN2_PIN); speed -speed; } else { GPIO_ResetBits(MOTOR_AIN1_GPIO, MOTOR_AIN1_PIN); GPIO_ResetBits(MOTOR_AIN2_GPIO, MOTOR_AIN2_PIN); } if (speed 1000) speed 1000; TIM_SetCompare1(TIM2, (uint16_t)speed); }代码里TIM_Period设成 999Prescaler设成 71在 72MHz 主频下 PWM 频率是 1kHz。这样的频率驱动普通直流减速电机够用。左右两个电机需要各自初始化一个 TIM 通道调方向时注意左右电机安装方向可能相反一个用正逻辑一个用反逻辑是常见操作。5.2 HCSR04 超声波测距HCSR04 的时序很简单TRIG 拉高 10us 以上模块自动发八个 40kHz 的脉冲ECHO 输出高电平时间就是声音往返一次的时间。高电平时间除以 58单位是厘米。用 GPIO 模拟测量 ECHO 高电平时长#include stm32f10x.h #define TRIG_GPIO GPIOA #define TRIG_PIN GPIO_Pin_6 #define ECHO_GPIO GPIOA #define ECHO_PIN GPIO_Pin_7 void Ultrasonic_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Pin TRIG_PIN; GPIO_Init(TRIG_GPIO, GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin ECHO_PIN; GPIO_Init(ECHO_GPIO, GPIO_InitStructure); } float Ultrasonic_GetDistance(void) { uint32_t timeout 0; GPIO_SetBits(TRIG_GPIO, TRIG_PIN); Delay_us(15); GPIO_ResetBits(TRIG_GPIO, TRIG_PIN); while (GPIO_ReadInputDataBit(ECHO_GPIO, ECHO_PIN) 0) { if (timeout 100000) return -1.0f; } TIM3-CNT 0; TIM_Cmd(TIM3, ENABLE); while (GPIO_ReadInputDataBit(ECHO_GPIO, ECHO_PIN) 1) { if (TIM3-CNT 30000) { TIM_Cmd(TIM3, DISABLE); return -1.0f; } } TIM_Cmd(TIM3, DISABLE); return (float)TIM3-CNT * 0.034f / 2.0f; }使用定时器计数来测量高电平宽度比纯软件延时更准确。超声波模块测距原理是固定的但实际使用会有测量盲区、声速受温度影响、不同物体反射率不同、长时间连续测距发热导致漂移等问题。建议连续测量时每次间隔 50ms并做简单的均值滤波或滑动平均。5.3 SG90 舵机控制舵机角度控制用 50Hz PWM脉宽从 0.5ms 到 2.5ms。如果 PWM 周期是 20ms占空比 2.5% 到 12.5%。在标准库下可以配置 TIM 重载值为 19999比较值到 500 到 2500 对应 0 到 180 度void Servo_SetAngle(uint16_t angle) { uint16_t compare 500 (uint16_t)(angle * 2000.0f / 180.0f); TIM_SetCompare2(TIM4, compare); }调用Servo_SetAngle(90)可以让舵机转至中间位置。避障模式下可以先把舵机转到 90 度测前方距离再转到 30 度或 150 度分别测左右两个方向然后根据三组距离判断往哪边转。舵机扫到边缘位置后要注意加一点延时让舵机舵盘稳定后再触发超声波测量否则读数会偏大或偶尔为 0。6. 核心功能实现与分析6.1 PID 循迹循迹是这套资料的技术核心。红外循迹模块输出的是一排数字信号在黑线上输出一种电平在白色地面上输出另一种电平。因为每个传感器返回的是“是黑还是白”的状态所以直接用状态跳变来转弯会非常生硬表现为车在线上左右横摆。更好的做法是把传感器信息换算成一个“位置偏差值”。以五路循迹为例假设五个传感器的权重是-2, -1, 0, 1, 2把当前传感器的输出值读出来计算加权和。如果只有中间传感器压线偏差为 0如果车偏左右边传感器压线偏差为正如果车偏右左边传感器压线偏差为负。偏差计算出来之后用增量式 PID 输出修正量叠加到左右轮基础速度上typedef struct { float Kp; float Ki; float Kd; float error; float last_error; float integral; } PID_t; int16_t PID_Increment(PID_t *pid, float error) { float P 0, I 0, D 0; float delta; P error - pid-last_error; I error; D error - 2.0f * pid-last_error pid-last_error; pid-integral error; delta pid-Kp * P pid-Ki * I pid-Kd * D; pid-last_error error; return (int16_t)delta; }左右轮速度的计算方式#define BASE_SPEED 450 #define MAX_SPEED 850 void Tracking_Control(PID_t *pid, int16_t error) { int16_t correction PID_Increment(pid, error); int16_t left_speed BASE_SPEED correction; int16_t right_speed BASE_SPEED - correction; if (left_speed MAX_SPEED) left_speed MAX_SPEED; if (left_speed -MAX_SPEED) left_speed -MAX_SPEED; if (right_speed MAX_SPEED) right_speed MAX_SPEED; if (right_speed -MAX_SPEED) right_speed -MAX_SPEED; Motor_SetLeftSpeed(left_speed); Motor_SetRightSpeed(right_speed); }这里BASE_SPEED是基础速度correction是 PID 修正量。PID 修正量加到左侧、右侧减掉后车会朝偏差的反方向回中。增量式 PID 的好处是只输出偏差变化量不会因为积分项累积导致系统失控。调参顺序是固定的先调 KpKp 太小会过弯拉不回来太大则车在直线上来回震荡再调 KdKd 提供阻尼能有效减少直线抖动最后才是 Ki通常在存在稳态误差时才加。循迹调试还有个技巧把 PID 修正量和传感器偏差通过串口打印出来用 Vofa 上位机看波形。如果偏差曲线快速收敛说明参数方向是对的如果始终等幅震荡说明 Kp 偏大。6.2 超声波避障避障逻辑本质上是一个状态决策机。主循环周期性地获取超声波距离根据距离判断当前状态距离大于 30cm认为前方安全直行。距离小于 30cm 大于 15cm说明前方有障碍物减速。距离小于 15cm紧急停车开始绕行。绕行时先让舵机摆动测左右两个方向的距离选较远的一侧转向然后前进一段再回到直行状态。状态机可以用简单的 switch-case 实现void Avoid_Process(void) { float front Ultrasonic_GetDistance(); if (front 30.0f) { Motor_SetLeftSpeed(BASE_SPEED); Motor_SetRightSpeed(BASE_SPEED); return; } if (front 15.0f) { Motor_Stop(); Servo_SetAngle(150); Delay_ms(200); float left Ultrasonic_GetDistance(); Servo_SetAngle(30); Delay_ms(200); float right Ultrasonic_GetDistance(); Servo_SetAngle(90); Delay_ms(200); if (left right) { Motor_SetLeftSpeed(-BASE_SPEED / 2); Motor_SetRightSpeed(BASE_SPEED / 2); } else { Motor_SetLeftSpeed(BASE_SPEED / 2); Motor_SetRightSpeed(-BASE_SPEED / 2); } Delay_ms(500); } else { Motor_SetLeftSpeed(BASE_SPEED - 100); Motor_SetRightSpeed(BASE_SPEED); } }避障调试点主要集中在两个地方一是超声波每次测距后要加延时不要连续触发否则回波可能串扰二是舵机扫描后要等舵机到位再测距否则测量方向不对。从实际经验看很多“避障失败”不是逻辑问题而是测距方向滞后导致的误判。6.3 距离跟随跟随功能看着高级本质还是超声波数据的使用。把跟随目标保持在一定距离范围内比如 20cm 到 35cm距离大于 35cm说明目标太远当前方向前进同时提高速度。距离在 20cm 到 35cm 之间保持当前速度或停止等待。距离小于 20cm说明离目标太近后退或者减速。跟随的 PID 控制和循迹不太一样。循迹的输入是传感器偏差跟随的输入是目标距离和实测距离的差值void Follow_Process(float target_distance) { float current_distance Ultrasonic_GetDistance(); float error current_distance - target_distance; int16_t correction PID_Increment(follow_pid, error); if (correction 0) { Motor_SetLeftSpeed(correction); Motor_SetRightSpeed(correction); } else { Motor_SetLeftSpeed(correction); Motor_SetRightSpeed(correction); } }跟随的调参思路和循迹一致先减小基础速度再逐步增大 Kp。如果车在目标点来回震荡说明 Kp 偏大或目标死区太小。更稳妥的做法是设置一段“不灵敏区”误差在正负 3cm 以内时不更新速度避免在临界距离反复启动和停车。6.4 蓝牙遥控蓝牙遥控是这套小车里最容易出效果的功能。模块和手机连接后手机发送字符STM32 串口中断接收主循环解析后执行对应动作。串口接收初始化之后在中断里做一个简单的命令缓存uint8_t cmd_buffer 0; void USART2_IRQHandler(void) { if (USART_GetITStatus(USART2, USART_IT_RXNE) ! RESET) { cmd_buffer USART_ReceiveData(USART2); } }主循环里根据收到的字符执行动作void Bluetooth_CommandProcess(uint8_t cmd) { switch (cmd) { case F: Motor_SetLeftSpeed(650); Motor_SetRightSpeed(650); break; case B: Motor_SetLeftSpeed(-650); Motor_SetRightSpeed(-650); break; case L: Motor_SetLeftSpeed(-200); Motor_SetRightSpeed(650); break; case R: Motor_SetLeftSpeed(650); Motor_SetRightSpeed(-200); break; case S: Motor_Stop(); break; default: break; } }蓝牙控制使用 9600 或 115200 波特率具体以模块默认配置为准。手机端可以用通用的蓝牙串口助手 APP也可以自己做上位机。如果发现发送指令后小车没有反应先检查串口数据能不能收到把蓝牙模块断开直接用 USB 转 TTL 接 STM32 的串口发同样的字符看小车是否动作这样就能定位是串口问题还是蓝牙模块问题。7. 调试与效果验证嵌入式项目不能只看代码理论必须有一套可以复现的验证方法。7.1 基础功能验证顺序先把复杂功能拆开逐个验证验证步骤操作通过标准第 1 步下载电机驱动程序左右电机能正转、反转、调速第 2 步下载超声波程序串口打印距离值用手挡在探头前数值连续变化第 3 步下载舵机程序SG90 能转到 0、90、180 三个位置第 4 步下载蓝牙程序手机发送 F/B/L/R/S 小车响应正确第 5 步下载循迹程序车能沿黑线从直道进入弯道并回正第 6 步避障与跟随用静止物体做目标小车能避开或保持距离每完成一步就把对应代码备份一次不要让未知问题叠加。比如避障失败时如果超声波测距本身不准就会很难判断是传感器问题还是决策逻辑问题。7.2 用串口和 Vofa 观察 PID 波形PID 调参最怕“看不见数据”。调试时把传感器偏差和 PID 输出通过串口打印出来格式可以按error:%.2f,output:%d的文本形式打印。Vofa 上位机还支持 JustFloat 协议一次传输多个 float 数据适合观察多条曲线的实时变化。在循迹测试时把偏差值和修正量同时发出来。如果修正量方向始终和偏差方向相反说明控制方向反了需要交换左右轮逻辑或改 PID 符号。如果修正量在快速正负振荡说明 Kp 过大。如果修正量收敛很慢车在入弯后拉不回来说明 Kp 过小或基础速度太快。7.3 性能与资源占用观察STM32 智能小车不强求 GPU、显存这类资源但有几个指标值得关注主循环执行周期。超声波测距、舵机运动、PID 计算都在一个循环里循环周期越短控制响应越快。常见问题是加了Delay_ms延时后主循环周期长到 50ms 以上导致循迹反应迟钝。CPU 占用。用调试器在线运行观察代码块耗时确认没有死循环阻塞。电池电压波动。TB6612 的 VM 端电压跌落会导致 PWM 输出脉宽对应的实际电压变低表现为速度漂移和 PID 输出不稳定。建议在电池电压低于 3.7V/节时及时充电不要在低压下调参否则调出来的参数到满电时又会偏激。8. 常见问题与排查方法问题现象可能原因排查方式解决方案编译报缺少 .h 文件标准库或固件库路径没添加检查 Keil 的 Include Paths 设置在 C/C 选项卡中加入工程目录路径ST-Link 下载失败驱动未装好查看设备管理器是否识别下载器重新安装 ST-Link 驱动检查连接线 SWDIO/SWCLK电机完全不转TB6612 STBY 引脚为低用万用表量 STBY 引脚电压拉高 STBY 或直接接 VCC电机只转一个方向另一路 PWM 没初始化检查 TIM 通道是否使能确认两路 PWM 都配置并开启输出电机转速最低时仍太快基础 PWM 值设置过高串口打印当前 PWM 值降低 BASE_SPEED或调整 PWM 频率车沿黑线左右剧烈摆动循迹逻辑只做开关判断没有 PID观察车能否直线回正改用偏差计算 PID 修正车入弯后拉不回来Kp 太小或基础速度太高用 Vofa 观察偏差收敛过程增大 Kp 或降低 BASE_SPEED超声波距离固定不变ECHO 引脚高电平检测失效量 ECHO 引脚电压变化检查 GPIO 配置和模块供电电压超声波距离跳动大连续测距间隔太短加延时打印连续 10 次数据每次测距间隔至少 50ms蓝牙手机搜不到模块模块处于 AT 模式或未上电检查模块指示灯状态重新上电进入配对模式蓝牙发送指令无反应TX/RX 接反检查串口 RX/TX 方向交叉连接 TX-RX、RX-TX小车跑一段后失控电池电压跌落测量电池空载和带载电压使用锂电池组和低压报警模块SG90 舵机抖动PWM 频率不是 50Hz用示波器确认 PWM 波形周期重新配置 TIM 周期为 20ms避障模式频繁急停舵机扫描方向和测距时序不同步代码中扫描后未加延时舵机到位后再触发超声波测距排查原则是“从底层往上验证”。硬件不动时先不怀疑程序先用万用表和示波器确认供电、信号、电平是否正常程序出现行为异常时先在关键位置加串口打印缩小问题范围不要靠猜。9. 电赛实践与工程化建议如果你是把这套资料用于电赛备赛有几个建议值得注意。第一不要比赛前夜才第一次调 PID。循迹参数和环境光、赛道材质、电机损耗都有关必须提前至少三天在模拟赛道上反复测试。准备一组保守参数和一组激进参数赛前根据现场光线临时切换。第二模块化测试数据要留档。每套速度、PID 参数、循迹传感器布局都对应一组实测表现建议用表格记录日期、基础速度、Kp、Ki、Kd、直线表现、弯道表现、备注。节省重复调参时间。第三硬件留冗余。比赛现场最容易坏的是电机和杜邦线。备件里准备两台电机、一套 TB6612 模块、至少 20 根不同颜色的杜邦线比准备很多大件更有效。第四胶水和扎带要用对。传感器支架、电池、主板要固定牢靠但也要方便快速拆装。强烈推荐用铜柱加尼龙扎带的方式固定主要模块避免热熔胶在震动下脱落也方便换传感器位置。第五合规使用器件和代码。写论文、做作品展示时引用别人的开源代码、接线图、算法思路要标注来源。比赛规则明确禁止抄袭源码和未授权使用的方案这一点要提前查清楚。10. 总结与下一步这套 STM32 智能小车资料最有价值的地方在于把嵌入式学习的核心模块串成了完整项目。B 站和论坛里讲 HCSR04、TB6612、PID 的零散教程很多但能把这些功能集成到一台可在赛道上跑起来的小车并给出完整开源工程和接线逻辑的资料才是真正值得收藏的。拿到资料后建议按照这个顺序推进先跑通电机驱动这是所有功能的基础再让超声波测距和舵机扫描工作验证距离数据稳定接着用蓝牙做遥控确认整车控制链路没问题最后才上 PID 循迹和避障逻辑。最容易踩的坑不是代码看不懂而是电机方向搞反、超声波时序不对、PID 参数给得太大导致车直接原地振荡。下一步可以继续扩展的方向很多加 OLED 显示当前距离和模式、增加按键切换运行模式、用 MPU6050 做姿态解算站上平衡车、把摄像头接入做视觉循迹、通过 ESP8266 模块接入 WiFi 实现局域网内控制和数据回传。对一个已经能把小车跑顺的开发者来说这些扩展方向都建立在同样的电机、传感器和 PID 控制基础上上手会非常快。建议先把资料保存好再从第一行代码开始亲手把小车转起来。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门