从零开始 | STM32与TB6612电机驱动的智能小车实战
1. 智能小车项目概述
第一次接触STM32和电机驱动的时候,我也是一头雾水。直到亲手用TB6612模块做了个小车,才发现原来从零搭建一个智能硬件项目并没有想象中那么难。这个项目特别适合刚入门嵌入式开发的朋友,既能学习GPIO和PWM控制,又能看到实实在在的机械运动反馈。
TB6612电机驱动模块可以说是智能小车的心脏。它就像个专业的"电机翻译官",把STM32微弱的控制信号转换成电机能听懂的大电流指令。我实测下来,这个模块比传统的L298N效率高不少,发热量小,特别适合电池供电的小车项目。最让我惊喜的是它支持双路1.2A持续电流输出,驱动常见的N20减速电机完全不在话下。
整个项目需要准备的核心硬件其实很简单:一块STM32F103C8T6最小系统板(就是常说的"蓝 pill")、TB6612驱动模块、两个直流电机带减速箱、四节AA电池盒,再加上个轻便的车架。软件方面用Keil MDK或者STM32CubeIDE都行,我更喜欢后者,因为图形化配置特别适合新手。
2. 硬件连接详解
2.1 电源系统设计
电源是很多新手最容易栽跟头的地方。我刚开始做的时候,就因为供电问题烧过一个驱动模块。TB6612需要两路供电:VCC接3.3-5V给逻辑电路用,VM接2.5-12V给电机用。建议用两套独立电源,比如STM32用USB供电,电机用6V电池组。如果非要共用电源,一定要确保电压足够稳定。
具体接线时要注意:电机的GND和STM32的GND必须接在一起!这个共地原则我见过不少人都忽略了,结果导致控制信号紊乱。我的经验是先用万用表确认所有GND都是通的,再上电测试。TB6612的VM引脚建议接6-7.4V锂电池,这个电压区间既能保证电机扭矩,又不会让模块过热。
2.2 信号线连接
STM32和TB6612的信号连接其实很有规律。以驱动两个电机为例:
- PWMA接PA0(TIM2_CH1)
- AIN1接PA1
- AIN2接PA2
- PWMB接PA3(TIM2_CH2)
- BIN1接PA4
- BIN2接PA5
- STBY接高电平(直接接VCC)
这里有个小技巧:PWM信号最好接到定时器的CH通道引脚上,这样后面配置PWM输出会方便很多。我第一次做的时候随便找了几个IO口,结果代码写起来特别麻烦。AIN1/AIN2和BIN1/BIN2就是普通的GPIO输出,用来控制电机转向。
3. 软件配置实战
3.1 GPIO初始化
先用STM32CubeMX配置引脚会省事很多。以标准库为例,电机控制引脚的初始化代码长这样:
void MOTOR_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
// 使能GPIOA时钟
__HAL_RCC_GPIOA_CLK_ENABLE();
// 配置AIN1,AIN2,BIN1,BIN2为推挽输出
GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// 初始化所有控制线为低电平
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5, GPIO_PIN_RESET);
}
3.2 PWM配置
PWM调速是让小汽车平稳运行的关键。TIM2的通道1和通道2正好对应PA0和PA1,配置成PWM输出模式:
void PWM_Init(void)
{
TIM_HandleTypeDef htim2;
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 72-1; // 72MHz/72=1MHz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000-1; // 1MHz/1000=1kHz PWM频率
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&htim2);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0; // 初始占空比0%
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
}
这里有个实用技巧:PWM频率建议设在1-5kHz之间。太低电机会有啸叫声,太高会导致MOS管开关损耗增大。我实测1kHz时电机运行最平稳,TB6612发热也最小。
4. 运动控制逻辑实现
4.1 基础运动函数
写完底层驱动后,可以封装几个常用运动函数:
// 设置左电机速度和方向
void MotorL_Set(int16_t speed)
{
if(speed >= 0) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, speed);
} else {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, -speed);
}
}
// 右电机同理
void MotorR_Set(int16_t speed)
{
/* 类似左电机的实现 */
}
// 小车前进
void Car_Forward(uint16_t speed)
{
MotorL_Set(speed);
MotorR_Set(speed);
}
// 小车后退
void Car_Backward(uint16_t speed)
{
MotorL_Set(-speed);
MotorR_Set(-speed);
}
// 小车左转
void Car_TurnLeft(uint16_t speed)
{
MotorL_Set(-speed/2);
MotorR_Set(speed);
}
// 小车右转
void Car_TurnRight(uint16_t speed)
{
MotorL_Set(speed);
MotorR_Set(-speed/2);
}
// 小车停止
void Car_Stop(void)
{
MotorL_Set(0);
MotorR_Set(0);
}
4.2 运动控制优化
直接给电机供电会导致小车启动太猛,停止时也有惯性。后来我加了加速度控制:
// 平滑加速函数
void Smooth_Accel(int16_t targetSpeed, uint8_t step)
{
static int16_t currentSpeed = 0;
while(currentSpeed != targetSpeed) {
if(currentSpeed < targetSpeed) {
currentSpeed += step;
if(currentSpeed > targetSpeed)
currentSpeed = targetSpeed;
} else {
currentSpeed -= step;
if(currentSpeed < targetSpeed)
currentSpeed = targetSpeed;
}
MotorL_Set(currentSpeed);
MotorR_Set(currentSpeed);
HAL_Delay(20);
}
}
这个函数会让小车速度线性变化,实测效果比直接设置速度要稳得多。step参数控制加速度大小,我一般用5-10之间的值。
5. 常见问题排查
5.1 电机不转排查步骤
- 先检查电源:用万用表量VCC和VM电压是否正常
- 检查STBY引脚:必须接高电平
- 测试PWM信号:用示波器看PA0/PA1是否有波形输出
- 检查方向信号:用LED或万用表测量AIN1/AIN2电平变化
- 单独测试电机:直接给电机加电看是否正常转动
5.2 电机抖动问题
遇到电机吱吱响但不转的情况,通常是:
- PWM频率太低:调到1kHz以上
- 供电不足:加大VM电压或换更大电流电源
- 电机线接触不良:重新焊接电机接头
5.3 驱动模块发热严重
TB6612正常情况下只是微热,如果烫手就要注意:
- 电机电流是否超过1.2A
- VM电压是否超过12V
- 电机是否堵转
- PWM频率是否过高(超过20kHz)
建议在VM端加个10A的保险丝,我烧过两个模块后才学乖。另外可以在电机两端并联0.1uF电容,能有效减少火花干扰。
更多推荐
所有评论(0)