在这个arduino教程中,我们将学习如何使用arduino控制直流电机。我们来看看控制直流电机的一些基本技术,并通过两个例子,学习如何使用l298n电机驱动器和arduino板来控制直流电机。
在以往的文章中,我们知道可以通过简单地控制输入电压来控制直流电机的速度,最常用的方法是使用pwm信号。延伸可阅读:pwm
pwm控制直流电机
使用pwm控制直流电机
pwm,即脉冲宽度调制技术,它是一种允许我们通过调整进入电机的电压的平均值,通过高电平和低电平的持续时间来控制电机运动的技术。平均电压取决于占空比,即信号在一段时间内打开的时间与关闭的时间之比。
脉冲宽度调制技术
因此,根据电机的大小,我们可以简单地将arduinopwm输出连接到晶体管的底座或mosfet的栅极,通过控制pwm输出来控制电机的速度。低功率arduinopwm信号开关在mosfet上,通过pwm信号开关可驱动大功率电机。
arduinopwm控制直流电机
h桥直流电机控制
另一方面,为了控制电机的旋转方向,我们只需要对电流流过电机的方向进行逆转,最常用的方法是用h桥。一个h桥电路包含四个开关元件,晶体管或mosfet,形成一个类似于h的结构。通过同时激活两个特定的开关,我们可以改变电流流动的方向,从而改变电机的旋转方向。
h桥的结构
所以,如果我们把pwm和h桥这两种方法结合起来,我们就可以完全控制直流电机的运动了。有许多直流电机驱动器都具有这些特性,l298n就是其中之一。
l298n驱动模块
l298n是一个双h桥电机驱动器,它允许在同一时间,在速度和方向上对两个直流电机进行控制。该模块可以驱动电压在5–35v之间的直流电机,峰值工作电流可达2a。
l298n驱动模块
让我们仔细看看l298n模块的接口定义,并解释它是如何工作的。该模块包括两个电机(a、b)的连接端子、接地gnd端子、电机的vcc和一个可作为输入或输出的5v引脚,这主要取决于在电机vcc上使用的电压,具体使用请往下看。
该模块有一个板载5v调节器,可通过跳线启用或禁用。如果电机供电电压低于12v,我们可以启用5v调节器,5v引脚可以作为输出,例如为我们的arduino板供电;但是如果电机电压大于12v,我们必须断开跳线,因为这些电压会对板载5v调节器造成损坏。在这种情况下,5v引脚将作为输入,因为我们需要连接到5v电源,以便ic正常工作。
使用中这个集成电路的电压降大约是2v。例如,如果我们使用12v电源,电机端子的电压大约是10v,这意味着我们无法从12v直流电机中获得最大速度。
l298n的电压降
接下来是逻辑控制信号输入。使能a和使能b引脚用于使能和控制电机的速度。如果跳线出现在这个引脚上,电机将被启用并以最大速度工作,如果我们移除跳线,我们可以将pwm输入连接到这个引脚上,以这种方式控制电机的速度。如果我们把这个插针接在地gnd上,马达就会不工作。
l298n的逻辑输入控制
其中,输入1和2针用于控制电动机a的转动方向,输入3和4用于控制电机b。这些插针实际上控制的是h桥的开关l298n芯片。它的控制原理是:当输入1是低,2是高马达a会向前转动,反之亦然,如果输入1高2低电机a将反方向旋转。如果两个输入都相同,无论高低电平,电机a都会停止。同样的道理也适用于输入3和4。
arduino上l298n的使用
现在让我们做一些实际的测试。在第一个示例中,我们将使用电位器控制电机的速度,并使用一个按钮改变旋转方向。这是电路原理图。
arduino上l298n的使用
测试元件包括:一个l298n驱动器,一个直流电机,一个电位器,一个按钮开关和一个arduino板以及12v电源。
arduino 控制代码如下
/* arduino dc motor control - pwm | h-bridge | l298n - example 01
*/
#define ena 9
#define in1 6
#define in2 7
#define button 4
int rotdirection = 0;
int pressed = false;
void setup() {
pinmode(ena, output);
pinmode(in1, output);
pinmode(in2, output);
pinmode(button, input);
// set initial rotation direction
digitalwrite(in1, low);
digitalwrite(in2, high);
}
void loop() {
int potvalue = analogread(a0); // read potentiometer value
int pwmoutput = map(potvalue, 0, 1023, 0 , 255); // map the potentiometer value from 0 to 255
analogwrite(ena, pwmoutput); // send pwm signal to l298n enable pin
// read button - debounce
if (digitalread(button) == true) {
pressed = !pressed;
}
while (digitalread(button) == true);
delay(20);
// if button is pressed - change rotation direction
if (pressed == true & rotdirection == 0) {
digitalwrite(in1, high);
digitalwrite(in2, low);
rotdirection = 1;
delay(20);
}
// if button is pressed - change rotation direction
if (pressed == false & rotdirection == 1) {
digitalwrite(in1, low);
digitalwrite(in2, high);
rotdirection = 0;
delay(20);
}
}
代码解释:首先我们需要为程序定义引脚和一些变量。在 setup 部分,我们需要设置引脚模式和电机的初始旋转方向。在 loop 部分,我们首先读取电位器的值,然后将我们从电位器中得到的值,0到 1023 映射到pwm信号值 0 到 255,也就是pwm信号从0到100%的占空比。然后使用 analogwrite() 函数,发送pwm信号到l298n板的使能端,从而实现电机的驱动。接下来,检查是否按下了按钮,如果是,将通过反方向设置输入1和输入2的状态来改变电机的旋转方向。这个按钮将作为切换按钮工作,每次我们按下它,它都将改变电机的旋转方向。
arduino采用l298n驱动机器人小车
如果我们理解了上面的知识,下面我们就可以制造自己的arduino机器人小车了。下面是电路原理图:
arduino采用l298n驱动机器人小车
我们需要两个直流电机,l298n驱动器,一个arduino板和一个操纵杆joystick。在电源方面,我选择了三节3.7v的锂离子电池作为电源,电压约11v。小车采用3毫米的胶合板做了底盘,用金属支架把电机固定在上面,把轮子连在电机上,底盘的前面安装了一个转向轮。在网上有成品底盘,例如:智能小车底盘
现在让我们看看arduino代码,看看它是如何工作的。
int xaxis = analogread(a0); // read joysticks x-axis
int yaxis = analogread(a1); // read joysticks y-axis
在loop部分定义了引脚之后,我们首先读取操纵杆x和y轴的值。操纵杆实际上是由两个电位器连接到arduino的模拟输入,它们的值从0到1023。当操纵杆保持在中心位置时,电位器或轴的值都在512左右。
操纵杆joystick 模块的值
我们将增加一点公差,以470到550的值为中心。所以如果向后移动操纵杆的y轴,数值低于470,将使用四个输入引脚将两个电机的旋转方向设置为向后。然后,我们将从470到0的下降值转换为pwm从0到255的上升值,这实际上是控制电机的速度。
// y-axis used for forward and backward control
if (yaxis < 470) {
// set motor a backward
digitalwrite(in1, high);
digitalwrite(in2, low);
// set motor b backward
digitalwrite(in3, high);
digitalwrite(in4, low);
// convert the declining y-axis readings for going backward from 470 to 0 into 0 to 255 value for the pwm signal for increasing the motor speed
motorspeeda = map(yaxis, 470, 0, 0, 255);
motorspeedb = map(yaxis, 470, 0, 0, 255);
}
类似的,如果我们向前移动操纵杆的y轴,数值超过550,我们将设置电机向前移动,并将读数从550到1023转换为pwm值从0到255。如果操纵杆保持在它的中心,电机的速度将为零。接下来,让我们看看如何使用x轴来控制小车左右转动 。
// x-axis used for left and right control
if (xaxis < 470) {
// convert the declining x-axis readings from 470 to 0 into increasing 0 to 255 value
int xmapped = map(xaxis, 470, 0, 0, 255);
// move to left - decrease left motor speed, increase right motor speed
motorspeeda = motorspeeda - xmapped;
motorspeedb = motorspeedb + xmapped;
// confine the range from 0 to 255
if (motorspeeda 255) {
motorspeedb = 255;
}
}
首先,需要把x轴的读数转换成0到255之间的速度值。对于向左移动,我们使用这个值来降低左电机速度并增加右电机速度。在这里,由于算术函数,我们使用两个额外的“if”语句来限制电机速度范围从0到255。
机器人小车的左转和右转
同样的方法也适用于向右移动小车。
根据所施加的电压和采用电机本身的不同,在较低的速度下,电机无法启动,并产生嗡嗡声。在我本文的例子中,如果pwm信号的值低于70,电机就无法启动。因此,使用这两个if语句,我实际上把速度限制在70到255之间。最后,发送电机速度控制值或pwm信号到l298n驱动器的使能引脚。
// prevent buzzing at low speeds (adjust according to your motors. my motors couldn't start moving if pwm value was below value of 70)
if (motorspeeda < 70) {
motorspeeda = 0;
}
if (motorspeedb < 70) {
motorspeedb = 0;
}
analogwrite(ena, motorspeeda); // send pwm signal to motor a
analogwrite(enb, motorspeedb); // send pwm signal to motor b
最后附上arduino机器人小车示例的完整代码:
*/
#define ena 9
#define in1 4
#define in2 5
#define enb 10
#define in3 6
#define in4 7
int motorspeeda = 0;
int motorspeedb = 0;
void setup() {
pinmode(ena, output);
pinmode(enb, output);
pinmode(in1, output);
pinmode(in2, output);
pinmode(in3, output);
pinmode(in4, output);
}
void loop() {
int xaxis = analogread(a0); // read joysticks x-axis
int yaxis = analogread(a1); // read joysticks y-axis
// y-axis used for forward and backward control
if (yaxis 550) {
// set motor a forward
digitalwrite(in1, low);
digitalwrite(in2, high);
// set motor b forward
digitalwrite(in3, low);
digitalwrite(in4, high);
// convert the increasing y-axis readings for going forward from 550 to 1023 into 0 to 255 value for the pwm signal for increasing the motor speed
motorspeeda = map(yaxis, 550, 1023, 0, 255);
motorspeedb = map(yaxis, 550, 1023, 0, 255);
}
// if joystick stays in middle the motors are not moving
else {
motorspeeda = 0;
motorspeedb = 0;
}
// x-axis used for left and right control
if (xaxis 550) {
// convert the increasing x-axis readings from 550 to 1023 into 0 to 255 value
int xmapped = map(xaxis, 550, 1023, 0, 255);
// move right - decrease right motor speed, increase left motor speed
motorspeeda = motorspeeda + xmapped;
motorspeedb = motorspeedb - xmapped;
// confine the range from 0 to 255
if (motorspeeda > 255) {
motorspeeda = 255;
}
if (motorspeedb < 0) {
motorspeedb = 0;
}
}
// prevent buzzing at low speeds (adjust according to your motors. my motors couldn't start moving if pwm value was below value of 70)
if (motorspeeda < 70) {
motorspeeda = 0;
}
if (motorspeedb < 70) {
motorspeedb = 0;
}
analogwrite(ena, motorspeeda); // send pwm signal to motor a
analogwrite(enb, motorspeedb); // send pwm signal to motor b
}
中国芯片发展机缘及芯片发展历程
IoT时代,先进的RFID企业已经充当了试金石
上半年中国半导体企业取得不错成绩
产业数字化对于智慧城市的发展有什么影响
中国存储的千钧一战 中国存储的三大加速度分析
如何使用L298N和Arduino板控制直流电机
为Mate 40系列做准备,华为5nm麒麟1020提升50%的性能
科技实力再获认可!海尔智家获评国家级服务型制造示范企业
智能配电系统的现状与趋势分析
2019年全球并网太阳能产能达到580GW,水力发电是主要来源
基于CMSIS标准的Cortex-M3应用软件开发
Infineon IDP2303120W PFC+LLC转换器参考设计手册
新基建:数字时代的新结构性力量
不仅仅是手机在寻求区块链,整个电信行业都在寻求区块链!
有源滤波器怎么配置_有源滤波器的优点和缺点
云米首款5G全网通的智能路由器正式发布
三巨头大战OLED江湖 撬动韩企版图
福建移动正式公布了2019-2021年25G光模块集中采购项目中标结果
作弊黑科技,假装自己是橡皮的显示器
未来人工智能的五大发展趋势是怎么样的?