这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 【2025 Let's do 第4期】基于单片机的直流电机控制成果帖

共1条 1/1 1 跳转至

【2025 Let's do 第4期】基于单片机的直流电机控制成果帖

助工
2026-01-13 16:10:58   被打赏 50 分(兑奖)     打赏

项目介绍

基于电位器的模拟调速系统:使用一个摇杆电位器作为输入,实时无级地控制电机的速度和方向。


硬件介绍

本项目基于以下核心硬件构建了一个直观的模拟调速控制系统:

  • 主控平台:NXP FRDM-MCXA153开发板

    • 核心为MCXA153系列微控制器,基于高效的Arm® Cortex®-M33内核。

    • 板载Arduino R3兼容接口,便于扩展。

    • 集成USB调试与供电接口,内置CMSIS-DAP调试器,开发便捷。

  • 驱动模块:Adafruit Motor Shield V2

    • 采用TB6612 MOSFET驱动芯片,支持双路直流电机。

    • 通过I2C接口(默认地址0x60)与主控板通信,节省I/O资源。

    • 提供稳定的电机电源管理及保护。

  • 输入设备:旋转电位器(10kΩ)

    • 作为模拟输入设备,将旋转角度转换为连续的电压信号。

    • 连接到开发板的模拟输入引脚,实现无级调速。


功能概览

系统利用摇杆电位器作为速度与方向指令的输入源。通过实时读取电位器输出的模拟电压值,将其映射为电机的控制参数,最终实现对单个直流电机的无级调速与正反转控制。整个系统运行平滑,响应迅速,直观地演示了模拟信号采集、数据处理与电机驱动控制的完整流程。


设计思路

设计核心在于将连续的模拟输入映射为离散的电机控制命令,关键思路如下:

  1. 信号采集:利用MCXA153内部的ADC(模数转换器)模块,将电位器输出的0-3.3V模拟电压转换为数字值(例如0-1023)。

  2. 控制策略

  • 速度控制:ADC采样值直接对应PWM(脉宽调制)的占空比。采样值越大,占空比越高,电机转速越快。

  • 方向控制:在ADC量程中间设置一个“死区”。当采样值高于死区上限时,电机正转;低于死区下限时,电机反转;位于死区内时,电机停止。这有效避免了因电位器微小抖动导致的误动作。

  1. 电机驱动:通过I2C协议将计算出的PWM占空比与方向指令发送给Adafruit Motor Shield,由其内部的TB6612芯片执行安全、高效的电机驱动。


功能实现软件流程图

deepseek_mermaid_20251227_42c327.png



硬件连接:

  1. 1. 电位器两端分别接3.3V与GND,中间引脚接MCXA153的A0(ADC0_A8)引脚。

  2. 2. Motor Shield堆叠在MCXA153的Arduino接口上。

  3. 3. 直流电机连接至Motor Shield的M4端口。

  4. 4. 外部电源(如7-12V)接入Motor Shield的电源端子,为电机供电。

  5. 基于单片机的直流电机控制面包板接线图_bb.png


核心代码逻辑(关键步骤):

// 1. 初始化ADC,与ADC中断处理函数
/**
 * @brief LPADC中断处理函数
 * @details 当ADC转换完成并将结果放入FIFO时,会触发此中断
 */
void DEMO_LPADC_IRQ_HANDLER_FUNC(void) {
    // 中断计数器加1,记录中断发生次数
    g_LpadcInterruptCounter++;
    // 当LPADC只有1个FIFO时,直接获取结果
    if (LPADC_GetConvResult(ADC0, &g_LpadcResultConfigStruct)) {
        // 设置转换完成标志,通知主循环可以处理结果
        g_LpadcConversionCompletedFlag = true;
    }
    
    // SDK中断退出屏障,确保中断处理完成
    SDK_ISR_EXIT_BARRIER;
}
// 2. 主循环
while(1) {
  // 等待转换完成
  if (g_LpadcConversionCompletedFlag){
    // 打印ADC转换结果和中断计数
    if(g_FreeTurnState) { // 自由调节状态,根据中位值计算方向和速度
      int16_t adcValue = (g_LpadcResultConfigStruct.convValue) >> g_LpadcResultShift;
      uint8_t adcSpeed = map(adcValue, 0, g_LpadcFullRange, 0, 255);
      uint8_t midValue = 176; // 中位值,根据实际情况调整
      // 计算速度与中位值的差值,大于0表示顺时钟转,小于0表示逆时钟转,等于0表示停止。正负10以内表示停止
      uint8_t diffValue = 0;
      uint8_t speed = 0;
      if (adcSpeed > (midValue + 10)) {
        // 逆时钟转
        diffValue = adcSpeed - (midValue + 10);
        speed = map(diffValue, 0, (255 - midValue - 10), 50, 255);
        g_MotorRunningState = true;
        task2(MOTOR_DIR_BACKWARD, speed);
      } else if (adcSpeed < (midValue - 10)) {
        // 顺时钟转
        diffValue = (midValue - 10) - adcSpeed;
        speed = map(diffValue, 0, (midValue - 10), 50, 255);
        g_MotorRunningState = true;
        task2(MOTOR_DIR_FORWARD, speed);
      } else if (g_MotorRunningState) {
        // 停止
        g_MotorRunningState = false;
        task2(MOTOR_DIR_RELEASE, 0);
      }
    }
    // 重置转换完成标志
    g_LpadcConversionCompletedFlag = false;
    // 触发软件转换(1U是触发0的掩码)
    LPADC_DoSoftwareTrigger(ADC0, 1U);
  }
}


关键点:map函数实现了输入到输出的线性映射;死区的设置提高了控制稳定性。


功能展示

系统上电后,操作直观:

正向加速

向前缓慢推动摇杆电位器。当推动过中间停止点(有明显阻力感)后,电机开始正转。随着继续推动摇杆,电机转速平滑、线性地增加,直至最高速。

2026-01-13_15-09-57.gif


反向加速

向后缓慢推动摇杆电位器。同样经过中间停止点后,电机反转,转速随旋转角度增大而平滑增加。

2026-01-13_15-11-32.gif


精确停止

松开摇杆电位器时,摇杆自动回到机械中点附近时,电机可靠停止,无明显抖动或蠕动,得益于软件死区的设置。

2026-01-13_15-12-57.gif


实时响应

摇杆电位器的任何角度变化,电机转速都能在毫秒级内做出对应调整,实现了真正的实时无级调速。

2026-01-13_15-14-24.gif


演示视频


总结

本项目成功构建了一个基于模拟输入的直流电机调速系统。它充分运用了 NXP FRDM-MCXA153 的模拟信号采集能力、Adafruit Motor Shield V2的集成驱动优势以及电位器的直观交互特性,实现了稳定、平滑、双向的电机速度控制。

技术要点总结:

  • 模拟信号处理:掌握了MCU ADC模块的使用,实现了连续模拟量到数字量的精准转换。

  • 控制算法设计:通过“死区”和线性映射策略,将单一模拟输入优雅地解耦为速度与方向两个控制维度,提升了系统鲁棒性。

  • 硬件协作:熟练运用I2C总线控制外围驱动模块,体现了模块化开发的高效性。


本系统作为一个基础平台,可轻松扩展,例如增加第二个电位器控制另一台电机实现差速转向,或移植到更复杂的机器人底盘控制中,具有很好的实践教学价值与工程参考意义。


传送门

【2025 Let's do 第4期】基于单片机的直流电机控制开箱帖

【2025 Let's do 第4期】基于单片机的直流电机控制过程贴


参考资料





关键词: Let's do     DIY     NXP     C/C++     Ar    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]