从玩具到竞赛级:STM32智能小车电机选型与编码器测速实战

第一次用TT马达组装智能小车时,那种看到轮子转动的兴奋感至今难忘。但当我带着作品参加高校智能车竞赛,才发现玩具级电机在精准控制和持续负载下的力不从心——速度波动大、响应延迟、无法反馈实时转速。这促使我深入研究带编码器的直流电机方案,本文将分享如何用STM32实现工业级电机控制的技术跃迁。

1. 电机选型:从TT马达到编码器电机的性能跨越

许多创客的第一个智能小车项目都从橙色外壳的TT马达开始,这种售价不足10元的直流电机因价格低廉成为入门首选。但当我们开始实现循迹、避障或竞速等需要精确控制的应用时,TT马达的三大缺陷就会显现:

  1. 无速度反馈 :只能通过PWM占空比估算转速,实际速度受负载影响波动可达±30%
  2. 扭矩不足 :130电机在6V电压下扭矩仅0.3kg·cm,爬坡或加速时易出现失速
  3. 寿命短暂 :碳刷结构在连续工作2-3小时后性能明显下降

相比之下,带霍尔编码器的直流电机(如JGA25-370)在同等尺寸下可实现:

参数 TT马达 编码器电机 提升幅度
扭矩 0.3kg·cm 3.2kg·cm 10.6倍
编码器分辨率 11PPR×64
最大转速 200RPM 450RPM 2.25倍
持续工作时间 2-3小时 50小时+ 25倍

实际测试显示:在5cm爬坡测试中,TT马达需要100%占空比才能勉强登顶,而编码器电机在60%占空比下即可稳定运行,且通过PID控制可将速度误差控制在±2RPM内。

2. 硬件架构:STM32与双电机驱动方案设计

要实现真正的闭环控制,需要构建包含速度检测、中央处理和功率驱动的完整硬件链路。以下是基于STM32F407的推荐配置:

// 电机驱动核心组件清单
1. STM32F407ZGT6  // 带高级定时器,适合编码器接口
2. L298N双H桥模块 // 峰值电流2A,支持PWM调速
3. JGA25-370电机  // 内置霍尔编码器(11PPR)
4. 18650电池组    // 7.4V电压,2000mAh容量
5. 铝合金底盘     // 尺寸20x15cm,带电机安装孔

关键电路连接要点

  • 将编码器A/B相分别接入TIM2_CH1/TIM2_CH2(支持正交解码)
  • 电机驱动IN1/IN2接PA6/PA7(普通GPIO),ENA接PB0(PWM输出)
  • 在VS(驱动电压)和VSS(逻辑电压)间跨接100uF电容滤波

接线示意图

注:实际布线时应将电机电源与MCU电源地线在一点共地,避免大电流干扰。

3. 编码器数据采集:四倍频与速度计算实战

STM32的编码器接口模式可将霍尔信号转换为精确的转速数据。以11PPR编码器为例,配合四倍频技术可实现每转44个计数脉冲。配置步骤如下:

// TIM2编码器模式初始化
void Encoder_Init(void) {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    
    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_Period = 65535; // 16位最大值
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    
    TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, 
                             TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
    TIM_ICStructInit(&TIM_ICInitStructure);
    TIM_ICInitStructure.TIM_ICFilter = 6; // 设置输入滤波器
    TIM_ICInit(TIM2, &TIM_ICInitStructure);
    
    TIM_Cmd(TIM2, ENABLE);
}

速度计算算法

  1. 每50ms读取一次计数器值CNT
  2. 计算ΔCNT = 当前CNT - 上次CNT
  3. 转速RPM = (ΔCNT × 60 × 1000) / (44 × 采样间隔ms)
  4. 重置CNT并启动下次采样

实测发现,在电机加速阶段,原始数据会出现毛刺。通过滑动窗口滤波可有效平滑:

# Python实现的滑动平均滤波
class MovingAverage:
    def __init__(self, window_size=5):
        self.window = []
        self.size = window_size
        
    def update(self, value):
        self.window.append(value)
        if len(self.window) > self.size:
            self.window.pop(0)
        return sum(self.window)/len(self.window)

4. PID控制实现:从理论到参数整定

有了精准的速度反馈后,便可实现闭环PID控制。离散化PID公式为:

u(k) = Kp*e(k) + Ki*∑e(j) + Kd*(e(k)-e(k-1))

在STM32上实现的简化代码:

typedef struct {
    float Kp, Ki, Kd;
    float integral;
    float prev_error;
} PIDController;

float PID_Update(PIDController* pid, float setpoint, float measurement) {
    float error = setpoint - measurement;
    
    pid->integral += error;
    if(pid->integral > 1000) pid->integral = 1000;
    if(pid->integral < -1000) pid->integral = -1000;
    
    float derivative = error - pid->prev_error;
    pid->prev_error = error;
    
    return pid->Kp * error + 
           pid->Ki * pid->integral + 
           pid->Kd * derivative;
}

参数整定经验

  1. 先设Ki=Kd=0,逐渐增大Kp直到出现等幅振荡
  2. 取振荡周期Tu和增益Ku,按Ziegler-Nichols法计算:
    • Kp = 0.6*Ku
    • Ki = 2*Kp/Tu
    • Kd = Kp*Tu/8
  3. 微调时遵循"先稳后快"原则:
    • 出现超调增大Kd
    • 稳态误差大增大Ki
    • 响应慢增大Kp

实测某小车的最佳参数为:Kp=12.5, Ki=0.8, Kd=0.3,速度阶跃响应曲线显示:

  • 上升时间:0.3s
  • 超调量:<5%
  • 稳态误差:±1RPM

5. 系统集成:多传感器融合与无线控制

完成基础速度控制后,可扩展更多竞赛级功能:

循迹方案对比

  • 红外对管:成本低但易受环境光干扰
  • 灰度摄像头:需图像处理算法(OpenMV)
  • 激光雷达:精度高但价格昂贵

推荐性价比方案:TCRT5000红外阵列+STM32 ADC采样:

// 五路红外循迹采样代码
void LineSensor_Read(uint16_t* values) {
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_84Cycles);
    for(int i=0; i<5; i++) {
        GPIO_WriteBit(GPIOA, GPIO_Pin_0<<i, Bit_SET); // 依次选通
        Delay_us(10);
        ADC_SoftwareStartConv(ADC1);
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
        values[i] = ADC_GetConversionValue(ADC1);
        GPIO_WriteBit(GPIOA, GPIO_Pin_0<<i, Bit_RESET);
    }
}

WiFi控制实现

  1. 使用ESP8266模块的AT指令模式
  2. 配置为TCP服务器(端口8080)
  3. STM32通过USART接收控制指令

典型通信协议设计:

[开始符][长度][命令][数据][校验和]
0xAA     0x05 0x01 0x64  0xCE

(表示设置目标速度为100RPM)

6. 性能优化:从实验室到赛道的实战技巧

在真实比赛中,我们发现了几个教科书上不会提及的细节问题:

  1. 电源干扰 :电机启停导致STM32复位

    • 解决方案:在电机电源线加磁环,MCU电源加220uF钽电容
  2. 编码器丢脉冲 :高速时出现计数不准

    • 优化措施:将GPIO速度设置为High,滤波器值设为8
  3. 轮胎打滑 :影响速度测量精度

    • 应对方法:在轮胎内侧贴3M防滑胶带,增加摩擦力

一个有趣的发现:当小车从木地板切换到沥青路面时,最优PID参数需要重新调整。这是因为不同路面的滚动阻力系数变化导致:

路面类型 摩擦系数μ 推荐Kp调整幅度
木地板 0.3 +0%
沥青 0.5 -15%
地毯 0.7 -30%

最后分享一个调试PID的实用技巧——在STM32的DAC输出端接示波器,可以同时观察:

  • 通道1:目标速度(方波)
  • 通道2:实际速度(滤波后)
  • 通道3:PWM输出

这种可视化调试方法比单纯看串口数据效率提升至少3倍。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐