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 电机不转排查步骤

  1. 先检查电源:用万用表量VCC和VM电压是否正常
  2. 检查STBY引脚:必须接高电平
  3. 测试PWM信号:用示波器看PA0/PA1是否有波形输出
  4. 检查方向信号:用LED或万用表测量AIN1/AIN2电平变化
  5. 单独测试电机:直接给电机加电看是否正常转动

5.2 电机抖动问题

遇到电机吱吱响但不转的情况,通常是:

  • PWM频率太低:调到1kHz以上
  • 供电不足:加大VM电压或换更大电流电源
  • 电机线接触不良:重新焊接电机接头

5.3 驱动模块发热严重

TB6612正常情况下只是微热,如果烫手就要注意:

  • 电机电流是否超过1.2A
  • VM电压是否超过12V
  • 电机是否堵转
  • PWM频率是否过高(超过20kHz)

建议在VM端加个10A的保险丝,我烧过两个模块后才学乖。另外可以在电机两端并联0.1uF电容,能有效减少火花干扰。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐