从零打造智能小车:STM32F103C8T6与TB6612/A4950电机驱动实战指南
在创客圈里,智能小车一直是入门嵌入式开发的经典项目。它不仅融合了硬件搭建、电机控制、传感器交互等核心技能,更能让学习过程充满趣味性。本文将带你用最常见的STM32F103C8T6核心板(俗称"蓝莓板")配合TB6612或A4950电机驱动模块,一步步构建可遥控的智能小车底盘。无论你是电子专业学生还是DIY爱好者,只要掌握基础C语言和电路知识,就能在周末完成这个充满成就感的项目。
1. 硬件选型与系统架构设计
1.1 核心组件对比分析
电机驱动模块的选择直接影响整个项目的实现路径。我们先对比两款主流驱动方案的关键参数:
| 特性 | TB6612FNG | A4950 |
|---|---|---|
| 最大驱动电压 | 15V | 40V |
| 持续输出电流 | 1.2A (单路) | 2A |
| 控制逻辑 | 方向+PWM调速 | 双PWM相位控制 |
| 衰减模式 | 快/慢衰减可选 | 固定衰减特性 |
| 典型应用场景 | 小型机器人、智能车 | 高功率直流电机控制 |
对于智能小车项目,TB6612的集成度更高,自带两路H桥可同时驱动两个电机;而A4950需要外围电路支持,但驱动能力更强。初学者建议优先选择TB6612方案。
1.2 最小系统搭建清单
完整的智能小车硬件系统包含以下模块:
- 控制核心:STM32F103C8T6最小系统板(需自带USB转串口芯片)
- 驱动模块:TB6612或A4950电机驱动板(预焊接型最佳)
- 执行机构:N20减速电机(带编码器版本更佳)×2
- 电源系统:
- 18650锂电池两节(带保护板)
- 5V降压模块(如LM2596)
- 人机交互:
- 0.96寸OLED显示屏(I2C接口)
- 5向导航按键模块
- 车体结构:
- 亚克力底盘套件
- 万向轮或球轮
提示:电机与车轮的匹配很重要,建议选择1:48减速比的N20电机搭配65mm橡胶轮,这样既保证扭矩又兼顾速度。
2. 电路连接与电源管理
2.1 电机驱动接线详解
TB6612接线方案(以驱动右轮为例):
电源部分:
- VM接锂电池正极(7.4V)
- VCC与STM32共接5V
- GND与STM32共地
控制信号:
// STM32引脚定义 #define MOTOR_R_PWM PA0 // TIM2_CH1 #define MOTOR_R_IN1 PA4 #define MOTOR_R_IN2 PA5电机输出:
- AO1/AO2接电机两极
A4950的差异点在于控制逻辑:
// A4950典型接线 #define MOTOR_PWM PA0 // TIM2_CH1 #define MOTOR_DIR PA2需要特别注意:A4950的DIR引脚电平决定电流方向,而PWM占空比决定速度。
2.2 电源系统设计
智能小车常见的供电问题包括:
- 电机启动导致MCU复位
- PWM调速时出现抖动
- 电池电压下降影响驱动性能
推荐的分立供电方案:
锂电池组(7.4V) ├─ 电机驱动板(VIN) └─ DC-DC降压模块 ├─ 5V输出 → STM32、传感器 └─ 3.3V输出 → OLED等外设注意:务必在电机电源输入端并联470μF以上的电解电容,可显著改善瞬态响应。
3. STM32开发环境搭建
3.1 基础工程配置
使用STM32CubeIDE创建项目时,关键配置步骤如下:
时钟树设置:
- HCLK = 72MHz
- APB1 Timer clocks = 72MHz
PWM定时器配置(以TIM2为例):
htim2.Instance = TIM2; htim2.Init.Prescaler = 72-1; // 1MHz计数频率 htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 1000-1; // 1kHz PWM频率 htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_PWM_Init(&htim2);GPIO初始化:
- 方向控制引脚设为推挽输出
- PWM引脚设为复用功能
3.2 电机驱动层实现
TB6612控制逻辑封装:
typedef struct { GPIO_TypeDef* dir_port; uint16_t dir_pin; uint16_t pwm_channel; } Motor_TypeDef; void Motor_SetSpeed(Motor_TypeDef* motor, int16_t speed) { if(speed >= 0) { HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin, GPIO_PIN_SET); __HAL_TIM_SET_COMPARE(&htim2, motor->pwm_channel, speed); } else { HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin, GPIO_PIN_RESET); __HAL_TIM_SET_COMPARE(&htim2, motor->pwm_channel, -speed); } }A4950的特殊处理:
void A4950_Drive(Motor_TypeDef* motor, int16_t speed) { if(speed >= 0) { HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin, GPIO_PIN_SET); __HAL_TIM_SET_COMPARE(&htim2, motor->pwm_channel, 1000 - speed); } else { HAL_GPIO_WritePin(motor->dir_port, motor->dir_pin, GPIO_PIN_RESET); __HAL_TIM_SET_COMPARE(&htim2, motor->pwm_channel, -speed); } }4. 运动控制与调试技巧
4.1 基本运动算法实现
智能小车的差速转向需要协调两个电机:
void Move_Car(int16_t linear, int16_t angular) { int16_t left = linear - angular; int16_t right = linear + angular; // 限幅处理 left = constrain(left, -1000, 1000); right = constrain(right, -1000, 1000); Motor_SetSpeed(&left_motor, left); Motor_SetSpeed(&right_motor, right); }4.2 常见问题排查指南
电机不转:
- 检查STBY引脚是否接高电平(TB6612)
- 测量PWM信号是否正常输出
- 确认电机与驱动板连接可靠
转向不对称:
- 对两个电机分别做速度校准
- 检查车轮安装是否同心
- 调整电机死区补偿值
电源不稳定:
- 测量电池电压是否低于6.5V
- 检查各模块接地是否共接
- 增加电源滤波电容
// 死区补偿示例 int16_t applyDeadband(int16_t value, int16_t deadband) { if(abs(value) < deadband) return 0; return value > 0 ? (value - deadband) : (value + deadband); }5. 功能扩展与优化方向
5.1 增加速度闭环控制
对于带编码器的电机,可以实现PID速度调节:
typedef struct { float kp, ki, kd; float integral; float prev_error; } PID_Controller; float PID_Update(PID_Controller* pid, float setpoint, float measurement) { float error = setpoint - measurement; pid->integral += error; float derivative = error - pid->prev_error; pid->prev_error = error; return pid->kp * error + pid->ki * pid->integral + pid->kd * derivative; }5.2 无线遥控方案
通过蓝牙或2.4G模块实现手机控制:
- HC-05蓝牙模块接USART1
- 解析手机APP发送的控制指令
- 实现速度档位切换功能
void USART1_IRQHandler(void) { if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE)) { uint8_t ch = (uint8_t)(huart1.Instance->DR & 0xFF); // 协议解析逻辑... } }在完成基础功能后,可以进一步添加超声波避障、循迹传感器或IMU姿态检测等模块。我曾在一个校园竞赛项目中,通过融合MPU6050数据实现了小车的自平衡功能,这需要仔细调节PID参数和滤波算法。