结合 FreeRTOS 和 Arduino C33,使用 MDD3A H 桥控制有刷直流电机

什么是 H 桥?

H桥是一种包含四个半导体开关的电路。在最简单的形式中,H桥可以使用四个开关构建。本工程简报重点介绍H桥家族中的一个模块化子集,称为电机控制器模块。这是一种用于驱动小型有刷直流电机的流行拓扑结构,如图1所示。通过相对简单的微控制器代码,我们可以控制电机的方向和旋转速度。

本工程简报介绍了MDD3A双通道电机驱动器,它采用了基于MOSFET的H桥。它包括在FreeRTOS环境下运行的Arduino PORTENTA Pro C33的示例代码。

1Seeed MDD3A电机驱动器、Polilu 4754电机、Arduino C33分线板和Digilent Analog Discovery的图片。

技术提示 :MDD3A配备了一个5 VDC稳压器,为您的微控制器电路提供方便的电源,容量为200 mA。这是一个可选连接,应谨慎使用,特别是对于3.3 VDC设备。请注意,MDD3A的地线必须连接。这个共享连接用于在微控制器的逻辑输出和电机驱动器的输入之间提供共同的参考。

什么是脉宽调制?

典型的电机驱动模块支持脉宽调制(PWM)输入。对于大多数应用,电机的旋转速度与PWM的占空比大致成正比。许多文章已经介绍了如何使用PWM。例如,您可能已经熟悉Arduino的analogWrite()函数。也许这是您通过硬件和代码调暗LED来了解PWM的入门。

在本简报中,我们将使用C33的增强PWM功能。如果您还没有这样做,请查看这篇关于Arduino Nano Every PWM的文章和这篇关于Arduino C33 PWM的文章。这两篇文章都展示了如何从各自的微控制器中提高PWM性能的方法。请花时间阅读C33文章,因为本文的其余部分假设您已经熟悉底层的Arduino PWM应用程序编程接口(API)。

H 桥电机控制器如何物理连接到微控制器?

微控制器和电机控制模块之间有两种通用接口,包括:

  • 方向加PWM
  • 双PWM

两种接口类型的结果是相同的,因为电机方向和转速都由微控制器直接控制。这些技术在硬件权衡上有所不同。方向引脚加PWM对电机控制器施加了额外的限制,同时将微控制器资源最小化为单个数字I/O(输入/输出)引脚和一个PWM。另一方面,双PWM简化了电机控制器,但消耗了两个微控制器的PWM。请注意,在双接口中,任何时候只有一个PWM输出驱动是活动的。“未使用”的PWM通常设置为零占空比。请参考制造商的规格书以获取特定设备的配置。

例如,Cytron(Seeed)MD13S具有方向加PWM功能。本文中展示的小型MDD3A具有双PWM接口。

用于基于 PWM H 桥电机控制器的微控制器软件是什么?

正如引言中暗示的那样,我们使用Arduino,但我们偏离了传统的软件路径。我们没有使用analogWrite()函数,而是利用PORTENTA Pro C33的强大功能,使用Arduino IDE深处的基于类的API。

FreeRTOS任务如下所示。代码的末尾显示,可以使用传递给pulse_perc方法的浮点参数来设置各个PWM。代码的中间部分使电机根据float DutyCycle变量从全顺时针缓慢振荡到全逆时针。FreeRTOS任务的setup()部分配置了PWM。

这段代码紧密遵循了本文中概述的技术。具体来说,它利用了包含在以下路径中的API:C:\Users\your_name\AppData\Local\Arduino15\packages\arduino\hardware\renesas_portenta\1.1.0

请注意,稍作修改即可使用方向加PWM控制器。

#include "TaskHeartbeat.h"

static uint32_t state = 1;
static float DutyCycle = 0;

void heartbeat_thread_func(void *pvParameters) {

  /* setup() */

  pinMode(HEARTBEAT_PIN, OUTPUT);		         // Defined in "TaskHeartbeat.h"
  pinMode(PWM_PIN_1A, OUTPUT);
  pinMode(PWM_PIN_1B, OUTPUT);

  PwmOut pwm_1A(PWM_PIN_1A), pwm_1B(PWM_PIN_1B); // Instantiate two PWM objects
  pwm_1A.begin();
  pwm_1B.begin();

  pwm_1A.period_us(PWM_PERIOD_us);               // Set for a PWM frequency of 10 kHz
  pwm_1B.period_us(PWM_PERIOD_us);

  pwm_1A.pulse_perc(0);
  pwm_1B.pulse_perc(0);

  /* loop() */

  for (;;) {

    digitalWrite(HEARTBEAT_PIN, HIGH);
    vTaskDelay(1);
    digitalWrite(HEARTBEAT_PIN, LOW);
    vTaskDelay(9);

    if (state) {		                          // Smooth transition from zero, to full CW, to zero, to full CW, to zero, repeat forever
      DutyCycle += 0.025;                 
      if (DutyCycle > 100.0) {
        DutyCycle = 100.0;
        state = 0;
      }
    } else {
      DutyCycle -= 0.025;
      if (DutyCycle < -100) {
        DutyCycle = -100;
        state = 1;
      }
    }

    if (DutyCycle > 0) {		                   // Bidirectional motor control with Duty cycle bounded at +/- 100.0 %
      pwm_1A.pulse_perc(fabs(DutyCycle));
      pwm_1B.pulse_perc(0);
    } else {
      pwm_1A.pulse_perc(0);
      pwm_1B.pulse_perc(fabs(DutyCycle));
    }
  }
}

技术提示 :代码将Arduino C33配置为以10 kHz运行。当电机低速运行时,开关频率刚刚可闻。可能希望将PWM频率调整到MDD3A的最大值20 kHz。这将消除电机的啸叫声。然而,高频PWM可能会引起不良的电磁干扰(EMI)。使用AM收音机可以很容易地观察到这一点,因为PWM音调会出现在PWM频率的谐波处。例如,20 kHz PWM的第75次谐波可能会出现在1.5 MHz处。通常,我们不会担心这些高次谐波。然而,高电流电机引线长且未屏蔽。靠近的收音机可能会揭示这种不良干扰。务必复习一下你的傅里叶理论。

最后的思考

控制基于H桥的电机控制模块相对容易。挑战在于为所需的PWM频率配置PWM。我个人喜欢Arduino API解决方案,因为它允许将PWM设置为百分比(+/- 100)。这种抽象使得编码变得容易。然而,这确实会带来CPU开销的代价。我们不应该太掉以轻心,但强大的C33往往使这成为一个学术讨论。