
以前一直用L298N直流电机驱动模块DIY小车,主要是因为 这个比较便宜,网络上的教程比较多,被大家玩的很熟练了 最近尝试了DRV8833,替换了原来自平衡车里的L298N,感觉对于入门DIY很方便,下面这篇教程比较不错,简单翻译了一下
使用 DRV8833 电机驱动器和 Arduino 控制直流电机
毫无疑问,L293D和L298N是Arduino项目中首选的电机驱动器。它们可靠性高,在数百甚至数千个项目中被使用过。然而,它们有一个主要缺点 - 它们使用双极晶体管(BJT),这使它们效率极低。
BJT的问题在于它们有一个导通时的电压降。这个电压的能量需要去某个地方,事实上也确实如此;它会以热量的形式散失。随着时间的推移,这可能导致相当大量的能量损失,并且在某些情况下,会导致驱动器过热。对于必须长时间运行的项目来说,这可能是一个重大劣势。
值得庆幸的是,像DRV8833这样的现代电机驱动器在效率方面表现出色。DRV8833不是使用BJT,而是使用MOSFET。MOSFET几乎没有电压降,这意味着几乎所有来自电源的电压都被传送到电机。这就是为什么DRV8833不仅比基于BJT的电机驱动器更节能,而且产生的热量要少得多,使其更安全地长时间使用。
因此,让我们深入了解一下DRV8833电机驱动器的出色功能。
DRV8833电机驱动器
该模块的核心是一款来自德州仪器的集成H桥驱动器IC,专为电机驱动应用进行了优化 - DRV8833
DRV8833具有两个NMOS H桥驱动器,使其能够控制两个直流刷式电机、双极步进电机、电磁铁和其他感性负载。
它在2.7V至10.8V的电压范围内工作,每个通道可持续提供高达1.2A的电流。此外,它可以容忍每个通道高达2A的峰值电流,持续几秒钟。
DRV8833还包含多种保护功能,例如欠压锁定、过电流和过温保护,提供了高可靠性。每次发生这些事件时,都会禁用H桥MOSFET。在故障条件被排除后,设备将恢复其操作。
它还包括低功耗睡眠模式,可在电机不使用时节省电力。
所有这些功能使其成为为小型低电压电机供电的优秀选择。 技术规格 以下是规格:
| 参数 | 值 |
|---|---|
| 电机电压 | 2.7V – 10.8V |
| 逻辑电压 | 3V和5V兼容 |
| 连续输出电流 | 1.2A(每通道) |
| 峰值输出电流 | 2A(每通道) |
| 电机通道 | 2 |
| 保护功能 | 欠压锁定、过电流和过温 |
DRV8833电机驱动器引脚图
DRV8833驱动器共有12个引脚,连接到外部世界。引脚图如下:
让我们逐个了解所有引脚。
电源引脚
与大多数电机驱动器不同,DRV8833只有一个电源连接(因为电机电压与逻辑电压相同)。

VCC 和 GND 是连接驱动电机的电源供应的地方,电压范围可以在 2.7V 到 10.8V。
请注意,DRV8833可以使用低至 2.7V 的电压。这意味着它非常适合低电压项目,比如使用单体锂聚合物电池和低电压电机的项目。
输出引脚
DRV8825 电机驱动器的输出引脚,即 OUT1、OUT2、OUT3 和 OUT4,方便地位于模块的一侧,以便进行简单的接口连接。

电机 A 应连接到 OUT1 和 OUT2,而电机 B 应连接到 OUT3 和 OUT4。您可以将任何电压在 2.7V 到 10.8V 范围内的直流刷式电机连接到这些引脚。
请记住,DRV8833可以连续为一对直流电机提供每通道 1.2A 的电流(峰值为 2A)。
控制输入引脚
每个电机都有两个控制输入;IN1 和 IN2 是电机 A 的控制输入,而 IN3 和 IN4 是电机 B 的控制输入。这些控制输入允许您控制电机的速度和旋转方向。

方向控制:
电机的旋转方向可以通过将逻辑高(5V)或逻辑低(地)应用于这些输入来控制。下面的真值表显示了输入如何影响驱动器输出。
| IN1/IN3 | IN2/IN4 | 旋转方向 |
|---|---|---|
| 低(0) | 低(0) | 电机关闭 |
| 高(1) | 低(0) | 正向 |
| 低(0) | 高(1) | 反向 |
| 高(1) | 高(1) | 电机关闭 |
速度控制:
如果要控制速度,可以在通常高电平的引脚上使用脉冲宽度调制(PWM)。如果不需要速度控制,只需将它们设置为高电平或低电平。
请注意,控制输入在内部被拉低,从而默认情况下有效地禁用了电机驱动器输出。
睡眠模式引脚
SLEEP 引脚(在板上的丝印上标记为EEP)控制 DRV8833 的睡眠模式。将此引脚设置为低电平会将 DRV8833 设置为低功耗睡眠模式,而将其设置为高电平会使其重新激活。
在这种模式下,H桥被禁用,门极驱动充电泵停止工作,所有内部逻辑被重置,所有内部时钟被停止,所有输入被忽略。需要注意的是,当从睡眠模式返回时,电机驱动器需要一点时间,最多1毫秒,才能再次完全运行。
默认情况下,板上的 SLEEP 引脚被拉高,因此如果您不打算使用低功耗睡眠模式,可以将其保持未连接。
在 DRV8833 模块的背面,有一个焊接跳线 J1。
默认情况下,J1 是闭合的,它将板载上拉连接到 SLEEP 引脚,从而保持 DRV8833 处于启用状态。然而,如果您打开 J1,板载上拉将与 SLEEP 引脚断开连接。这个动作启用了芯片上的下拉,这意味着 DRV8833 将默认保持禁用状态。因此,如果您选择打开 J1,请记住在需要时需要手动将 DRV8833 打开。
故障检测引脚 FAULT 引脚(在板上的丝印上标记为ULT)是一个开漏输出,当芯片发生过电流、过温度或欠电压条件时,它会被拉低。
默认情况下,此引脚保持浮动状态。因此,如果您想监视驱动器上的故障条件,您将需要连接一个外部上拉电阻(或者使用带有内置上拉的微控制器输入)。
电流限制
DRV8833 可以主动限制通过电机的电流。通常,通过在 AISEN 引脚和地之间连接一个电阻来设置电机 A 的限制,并通过在 BISEN 引脚和地之间连接另一个电阻来设置电机 B 的限制来实现这一点。
然而,这个特定的 DRV8833 breakout board 将这些电流感应引脚直接连接到地,有效地禁用了电流限制功能。
将 DRV8833 模块接线到 Arduino
现在我们已经了解了模块的一切,我们可以开始将其连接到我们的 Arduino!
首先,连接电机电源。VCC 引脚是电机的电源,应根据您的电机要求(2.7V 到 10.8V)连接到适当的电源。在我们的实验中,我们使用的是直流齿轮箱电机,也称为“TT”电机,它们经常出现在双驱动机器人中。它们的额定电压为 3 到 12V。因此,我们将通过外部 5V 电源将其连接到 VCC 引脚。
现在将 DRV8833 的控制输入(IN1、IN2、IN3 和 IN4)连接到 Arduino 上的四个数字输出引脚(10、9、6 和 5)。请注意,所有这些引脚都支持 PWM。
将一个电机连接到 A 端子(OUT1 和 OUT2),将另一个电机连接到 B 端子(OUT3 和 OUT4)。您可以交换电机的连接方式。从技术上讲,没有对或错的方式。
如果您想监视故障条件,可以将 FAULT 引脚连接到 Arduino 上的数字引脚。请记住,因为它是一个开漏输出,所以为了这个引脚使用一个外部上拉电阻或在 Arduino 中启用内部上拉电阻。
最后,请确保您的电路和 Arduino 共用一个公共地。
以下表格列出了将 DRV8833 电机驱动器连接到 Arduino 的引脚连接情况:
下面图片展示了arduino电路连接图:
下面的sketch将向您展示如何使用 DRV8833 电机驱动器控制一对直流电机的速度和旋转方向,并可以作为更实际的实验和项目的基础。
这个sketch以不同的速率和方向移动一对直流电机。
当加速或减速电机时,您可能会听到它发出嗡嗡声,特别是在较低的 PWM 值下。这是正常的;不用担心。这是因为直流电机需要一定的电压才能运转。 - 代码
// Define the control inputs
#define MOT_A1_PIN 10
#define MOT_A2_PIN 9
#define MOT_B1_PIN 6
#define MOT_B2_PIN 5
void setup(void)
{
// Set all the motor control inputs to OUTPUT
pinMode(MOT_A1_PIN, OUTPUT);
pinMode(MOT_A2_PIN, OUTPUT);
pinMode(MOT_B1_PIN, OUTPUT);
pinMode(MOT_B2_PIN, OUTPUT);
// Turn off motors - Initial state
digitalWrite(MOT_A1_PIN, LOW);
digitalWrite(MOT_A2_PIN, LOW);
digitalWrite(MOT_B1_PIN, LOW);
digitalWrite(MOT_B2_PIN, LOW);
// Initialize the serial UART at 9600 baud
Serial.begin(9600);
}
void loop(void)
{
// Generate a fixed motion sequence to demonstrate the motor modes.
// Ramp speed up.
for (int i = 0; i < 11; i++) {
spin_and_wait(25*i, 25*i, 500);
}
// Full speed forward.
spin_and_wait(255,255,2000);
// Ramp speed into full reverse.
for (int i = 0; i < 21 ; i++) {
spin_and_wait(255 - 25*i, 255 - 25*i, 500);
}
// Full speed reverse.
spin_and_wait(-255,-255,2000);
// Stop.
spin_and_wait(0,0,2000);
// Full speed, forward, turn, reverse, and turn for a two-wheeled base.
spin_and_wait(255, 255, 2000);
spin_and_wait(0, 0, 1000);
spin_and_wait(-255, 255, 2000);
spin_and_wait(0, 0, 1000);
spin_and_wait(-255, -255, 2000);
spin_and_wait(0, 0, 1000);
spin_and_wait(255, -255, 2000);
spin_and_wait(0, 0, 1000);
}
/// Set the current on a motor channel using PWM and directional logic.
///
/// \param pwm PWM duty cycle ranging from -255 full reverse to 255 full forward
/// \param IN1_PIN pin number xIN1 for the given channel
/// \param IN2_PIN pin number xIN2 for the given channel
void set_motor_pwm(int pwm, int IN1_PIN, int IN2_PIN)
{
if (pwm < 0) { // reverse speeds
analogWrite(IN1_PIN, -pwm);
digitalWrite(IN2_PIN, LOW);
} else { // stop or forward
digitalWrite(IN1_PIN, LOW);
analogWrite(IN2_PIN, pwm);
}
}
/// Set the current on both motors.
///
/// \param pwm_A motor A PWM, -255 to 255
/// \param pwm_B motor B PWM, -255 to 255
void set_motor_currents(int pwm_A, int pwm_B)
{
set_motor_pwm(pwm_A, MOT_A1_PIN, MOT_A2_PIN);
set_motor_pwm(pwm_B, MOT_B1_PIN, MOT_B2_PIN);
// Print a status message to the console.
Serial.print("Set motor A PWM = ");
Serial.print(pwm_A);
Serial.print(" motor B PWM = ");
Serial.println(pwm_B);
}
/// Simple primitive for the motion sequence to set a speed and wait for an interval.
///
/// \param pwm_A motor A PWM, -255 to 255
/// \param pwm_B motor B PWM, -255 to 255
/// \param duration delay in milliseconds
void spin_and_wait(int pwm_A, int pwm_B, int duration)
{
set_motor_currents(pwm_A, pwm_B);
delay(duration);
}
代码解释
这个Arduino代码非常简单,不需要任何库来工作。草图首先声明了连接到 DRV8833 控制引脚的 Arduino 引脚。
// 定义控制输入
#define MOT_A1_PIN 10
#define MOT_A2_PIN 9
#define MOT_B1_PIN 6
#define MOT_B2_PIN 5
代码的设置部分初始化硬件。它将所有电机控制引脚配置为数字输出,并将它们设置为 LOW,最初禁用两个电机。然后,它以 9600 波特率初始化串行通信。
void setup(void)
{
// 将所有电机控制输入设置为输出
pinMode(MOT_A1_PIN, OUTPUT);
pinMode(MOT_A2_PIN, OUTPUT);
pinMode(MOT_B1_PIN, OUTPUT);
pinMode(MOT_B2_PIN, OUTPUT);
// 关闭电机 - 初始状态
digitalWrite(MOT_A1_PIN, LOW);
digitalWrite(MOT_A2_PIN, LOW);
digitalWrite(MOT_B1_PIN, LOW);
digitalWrite(MOT_B2_PIN, LOW);
// 初始化串行 UART,波特率为 9600
Serial.begin(9600);
}
代码的循环部分生成一个固定的运动序列,以演示电机模式。
它首先逐渐增加电机的速度,然后全速前进,再次减速并反向到全速,最后停止。
// 加速
for (int i = 0; i < 11; i++) {
spin_and_wait(25i, 25i, 500);
}
// 全速前进
spin_and_wait(255,255,2000);
// 减速到全速反转
for (int i = 0; i < 21 ; i++) {
spin_and_wait(255 - 25i, 255 - 25i, 500);
}
// 全速反转
spin_and_wait(-255,-255,2000);
// 停止
spin_and_wait(0,0,2000);
在停止后,它演示了一个两轮机器人底盘的转向操作,其中一个轮子向前移动,而另一个轮子向后移动,导致机器人转向。在演示了所有这些动作之后,循环重复。
// 全速前进,转向,反转,转向
spin_and_wait(255, 255, 2000);
spin_and_wait(0, 0, 1000);
spin_and_wait(-255, 255, 2000);
spin_and_wait(0, 0, 1000);
spin_and_wait(-255, -255, 2000);
spin_and_wait(0, 0, 1000);
spin_and_wait(255, -255, 2000);
spin_and_wait(0, 0, 1000);
此草图中使用了三个用户定义的函数:set_motor_pwm()、set_motor_currents() 和 spin_and_wait()。
set_motor_pwm() 函数使用 PWM 和方向逻辑设置电机通道上的电流。如果 pwm 值为负,则电机向一个方向旋转。如果 pwm 值为 0 或正数,则电机停止或向另一个方向旋转。
void set_motor_pwm(int pwm, int IN1_PIN, int IN2_PIN)
{
if (pwm < 0) { // 反向速度
analogWrite(IN1_PIN, -pwm);
digitalWrite(IN2_PIN, LOW);
} else { // 停止或前进
digitalWrite(IN1_PIN, LOW);
analogWrite(IN2_PIN, pwm);
}
}
set_motor_currents() 函数使用上述函数设置两个电机的电流。它将每个电机的当前 PWM 值打印到串行监视器上。
void set_motor_currents(int pwm_A, int pwm_B)
{
set_motor_pwm(pwm_A, MOT_A1_PIN, MOT_A2_PIN);
set_motor_pwm(pwm_B, MOT_B1_PIN, MOT_B2_PIN);
// 向控制台打印状态消息
Serial.print("Set motor A PWM = ");
Serial.print(pwm_A);
Serial.print(" motor B PWM = ");
Serial.println(pwm_B);
}
spin_and_wait() 函数设置速度并等待指定的时间,然后再进行下一步。它使用 set_motor_currents() 函数设置两个电机的 PWM 值,然后等待指定的时间(以毫秒为单位)。
void spin_and_wait(int pwm_A, int pwm_B, int duration)
{
set_motor_currents(pwm_A, pwm_B);
delay(duration);
}
将电机驱动这部分用DRV8833替换L298N,很容易将之前作的arduino self-balance robot改造一下,感觉电路更简单一些,代码控制差不多了多少,比较一下下图两个DIY作品:
使用L298N,简单的使用杜邦线连接,有点零乱

使用DRV8833,加上焊接的电路板,结构更紧凑一些


评论