原文地址:http://www.taichi-maker.com/homepage/reference-index/motor-reference-index/arduino-motor-shield/

Arduino AFMotor 电机扩展板详解

Arduino AFMotor 电机扩展板概述

电机扩展板作为Arduino平台最为流行的扩展板之一具有连接便利,功能丰富的特点。很多朋友们喜欢用这款电机扩展板驱动机器人或智能小车的电机。本页将向您介绍如何使用Arduino Uno开发板通过AFMotor电机扩展板来控制通用模型直流电机28BYJ-48步进电机以及舵机(伺服电机)。如果您希望学习如何使用Arduino Uno通过CNC扩展板来控制NEMA步进电机,请点击这里进入该页面

扩展板外观

在这里插入图片描述

Arduino AFMotor 电机扩展板正面
在这里插入图片描述
Arduino AFMotor电机扩展板背面
在这里插入图片描述
Arduino AFMotor电机扩展板侧面

AFMOTOR电机扩展板主要功能特点

  • 可最多驱动4个模型直流电机
  • 可最多驱动2个28BYJ-48步进电机
  • 可最多驱动2个舵机(伺服电机)
  • 板载两块L293D芯片负责电机驱动的核心工作
  • 可配合Arduino Uno/Mega开发板使用(本页面主要针对Uno开发板进行讲解)

端口介绍

电机扩展板各个端口情况请见下图
在这里插入图片描述
Arduino AFMotor 电机扩展板


外接电源供电

如下图所示,AFMotor电机扩展板上配有外接电源接口。该接口所连接的直流电源可以为电机和Arduino开发板供电。
在这里插入图片描述
Arduino-AFMotor电机扩展板外接电源接口

使用AFMotor电机扩展板驱动电机时,首要考虑的问题就是如何为扩展板供电。如果电源输出功率达不到驱动电机的要求,那么电机是无法正常工作的。在考虑如何选择电源时,我们需要重点关注两个方面 ,一个是电源电压,一个是电源电流。

注意:外接电源极性千万不要接反,否则会对扩展板造成损坏!

外接电源电压要求

AFMotor扩展板中起关键作用的芯片是L293D。该芯片所允许的直流电源电压范围是4.5V ~25V。因此AFMotor扩展板外接电源接口允许我们连接的电源也是4.5V ~25V。请注意:这是一个很宽泛的电压指标。具体我们应该连接的电源电压有多大,这是由被驱动的电机工作电压来决定的。

在购买电机时,卖家应该为您提供电机技术参数信息。这其中就有电机的工作电压这一参数。比如您所驱动的电机工作电压是+5V,那么您在使用AFMotor扩展板驱动该电机时,可以使用+5V的直流电源连接到外接电源接口上。但遗憾的是,不是所有卖家都能给您提供电机的技术参数,甚至有些卖家提供的参数是错的。这就需要您自己“猜”电机工作电压了。

这个“猜”电压的操作实在是无奈之举。如下图所示,假如您所购买的电机是这种通用的直流模型电机,那么可以试着使用+5V电压为该电机供电。
在这里插入图片描述
130直流电机
在这里插入图片描述
模型直流电机

在电机工作中,要特别注意电机是否有异常发热的现象。就是说您在用手轻轻触碰电机时,不能感到烫手。一旦发现电机太热,那么请更换电机。千万不要明明知道电机很烫,还让它持续工作,这很容易产生危险。

另外对于工作电压低于4.5V的直流电机,我不建议您使用AFMotor驱动板来驱动这些电机的。

外接电源电流要求

与上面提到的电源电压要求相同,外接电源的电流要求也是由被驱动的电机来决定的。通常我们使用AFMotor电机扩展板所驱动的电机就是普通的模型电机(如以上电源讲解中的图片所示)。对于这一类型的电机,它们的工作电流大约是500mA左右,因此我们只要为扩展板配一个500 mA~1000 mA的外接电源就足够了。请注意,假如您所驱动的电机工作电流超过500mA,那么就要考虑为扩展板上的L293D加装芯片了。

在本页教程中,我们给您举了三个示例。它们分别是驱动直流模型电机、驱动28BYJ-48步进电机以及驱动舵机(伺服电机)。这里没有驱动NEMA17步进电机的讲解。可能有的朋友会认为这是因为AFMotor电机扩展板不能用于驱动NEMA17步进电机。

其实不然。AFMotor电机扩展板是可以用于驱动NEMA17步进电机。但前提条件是要为扩展板上的L293D芯片配备散热装置。否则扩展板就会因为过热而停止工作,严重的还有可能烧毁L293D芯片。这是为什么呢?

由于大多数NEMA17步进电机的工作电流是在1000mA左右。如果让L293D芯片输出如此高的电流,芯片会产生很严重的发热现象。因此要想用AFMotor扩展板驱动NEMA17步进电机,就必须要为L293D芯片上加装散热片。然而通常我们买来的AFMotor电机扩展板是没有配备散热装置的。这是因为AFMotor电机扩展板主要就是驱动普通的直流模型电机,很少有人会用它来驱动NEMA17步进电机。所以也就无需为L293D芯片配备散热装置了。

对于驱动NEMA17步进电机来说,通常我们使用的是Arduino CNC 步进电机扩展板。假如您想了解更多的这方面信息,请点击这里进入该页面


安装AFMotor电机库

使用AFMotor电机扩展板驱动电机以前,需要先将AFMotor库安装到Arduino IDE中。如果您不知道如何进行操作,请点击这里进入Arduino IDE安装库的说明页面

在这里我们向您推荐两个电机程序库。一个是必须安装的,一个是可按您需要选择安装的。

必装的库是AFMotor库。这个库是AFMotor扩展板的开发团队Adafruit专门为该扩展板编写的。它的优点是非常简单易用,但是功能相对单一。假如您只是驱动直流模型电机,那么这个AFMotor库就足够了。

但是如果您还想用AFMotor扩展板驱动28BYJ-48步进电机的话,AFMotor库虽然也可以实现这一功能,但是它的功能太简单了。所以我们建议您使用AccelStepper库来控制步进电机。请注意:AccelStepper库本身不能配合AFMotor电机扩展板工作。只有安装了AFMotor库以后,AccelStepper库在AFMotor库的配合下才能用于AFMotor电机扩展板驱动步进电机。这也就是说,无论您是否使用AccelStepper库,都要首先安装AFMotor库。

以下是这两个库的下载链接:

下载 AFMotor库
下载 AccelStepper库


连接电机引线

如下图所示,在AFMotor电机扩展板的两侧共有4个直流电机端口,每一个端口都有独立的编号,即:M1,M2,M3,M4。每一个电机端口都是由两个接线端子所构成。
在这里插入图片描述
AFMotor电机扩展板电机端口

这些端子上的螺丝可以起到紧固电机引线的作用。如下图所示,通过顺时针旋转螺丝,插入端子的引线将会被固定住。相反,逆时针旋转螺丝可以松开端子中的引线。
在这里插入图片描述
螺丝刀拧紧AFMotor扩展板接口中的电机连接线


驱动直流电机电路

AFMotor电机扩展板最多可以驱动4个直流电机。以下我们将给您介绍两种电机扩展板的使用方法。第一种是在您开发项目时的使用方法,第二种是项目开发完毕后,您在使用扩展板驱动电机工作时的方法。这两种方法最大的区别在于:开发时的Arduino开发板是通过USB数据线连接在电脑上的。但是在工作时开发板是不连接电脑的。

项目开发时AFMOTOR电机扩展板使用方法

首先介绍的是在项目开发时AFMotor电机扩展板的使用方法。请看下图展示的电路连接说明。
在这里插入图片描述
AFMotor电机扩展板驱动直流电机(开发过程)

在开发时,Arduino的电源是由电脑通过USB线提供的。但由于电机运行所需的电源功率远远超过Arduino能提供的电源功率,因此Arduino是无法为电机供电的。要想让电机获得充足的电源供应,我们就需要在扩展板的外接电源端口接上直流电源来为电机供电。在这种情况下,扩展板上的跳线一定要移除。否则可能会损坏Arduino开发板以及电机扩展板!请务必注意!

另外,当扩展板上的跳线没有安置插针时,如果我们不给扩展板外接电源,而只是将Arduino开发板连接在电脑USB端口上。这时,当您把本页的示例程序上传给Arduino以后,您有可能看到电机在没有外接电源的情况下也可以运动,但是动力很弱。这是因为此时驱动电机的电能是来自于Arduino开发板的。由于Arduino开发板输出的电能远远无法满足电机正常运行的要求,所以您虽然看到电机也在动,但是动起来很没有力气。要想让电机以正常的方式运行,还是需要您给扩展板连接外接直流电源的,这样电机才有充足的动力来运行。

工作运行时AFMOTOR电机扩展板使用方法

一般在正常工作状态下,Arduino开发板是不会与电脑通过数据线进行连接的。这时我们就要通过AFMotor电机扩展板上外接电源端口同时为扩展板和Arduino供电。如下图所示:
在这里插入图片描述
AFMotor电机扩展板驱动直流电机(工作阶段)

注意:当使用外接电源同时为Arduino和电机扩展板供电时,扩展板上的跳线必须安置在插针上。否则Arduino是无法工作的。

扩展板跳线的作用

在以上两种工作方式里,我们对电机扩展板上的跳线采取了不同的操作方法。该跳线的作用是控制Arduino开发板是否通过外接电源来供电。当跳线移除的时候,外接电源不会为Arduino开发板供电。相反当跳线安置在插针上,外接电源将会为Arduino供电。

因此在程序开发过程中,当Arduino与电脑通过USB线连接时,我们需要将跳线从插针上移除。假如我们不移除该跳线,Arduino会有两路供电。而这两路电源同时工作会产生问题,严重的可能会造成开发板以及扩展板的损坏。

关于直流电机引线

可能有些朋友会感到好奇,直流电机有两根引线,这两根引线在连接到AFMotor扩展板电机端口时有没有顺序呢?这个问题的答案是“既有顺序也无顺序”。

如果您只是单纯的想要让电机转起来,那么这两根引线连接到扩展板端口上是没有顺序的。但如果您发现电机旋转的方向与您所期待的相反,您可以将这两根电机引线从扩展板上断开,然后交换顺序再接到扩展板端子上,这时您会看到电机旋转的方向就反过来了。


AFMotor电机扩展板驱动直流电机示例程序

示例程序

以下示例程序为演示如何使用Arduino Uno开发板通过AFMotor电机扩展板 驱动4个直流电机。
如需查看此示例程序演示视频,请点击这里

AFMotor电机扩展板驱动4个直流电机示例程序

/*
AFMotor电机扩展板驱动4个直流电机示例程序
By 太极创客(http://www.taichi-maker.com)
2019-02-27
 
本示例程序旨在演示如何使用Arduino Uno开发板通过AFMotor电机扩展板
驱动4个直流电机。
 
如需获得更多关于本示例程序的电路连接以及AFMotor电机扩展板的资料信息,
请参考太极创客网站,并在首页搜索栏中搜索关键字:AFMotor。
*/
 
#include <AFMotor.h> // 本程序中使用AFMotor库
 
AF_DCMotor motor1(1); // 这4条语句的作用是建立4个直流电机对象,它们的名称分别是:motor1/2/3/4.
AF_DCMotor motor2(2); // 这四条语句括号中的数字代表各个电机对象所连接在AFMotor扩展板的电机端口号码。
AF_DCMotor motor3(3); // AF_DCMotor motor1(1); 代表motor1对象连接在AFMotor扩展板的M1端口上。
AF_DCMotor motor4(4); // AFMotor电机扩展板最多可以驱动4个直流电机,最少可以驱动1个直流电机。
 
void setup() {
  motor1.setSpeed(200); // 这4条语句的作用是通过setSpped库函数设置电机运行速度。
  motor2.setSpeed(200); // setSpped库函数中的参数是运行速度参数。
  motor3.setSpeed(200); // 运行速度参数允许范围是0~255。
  motor4.setSpeed(200); // 速度参数越大,运转速度越快。参数为0时电机停止转动。
 
  motor1.run(RELEASE); // 这4条语句的作用是让4个电机在启动时停止转动
  motor2.run(RELEASE); // run库函数允许使用的关键字参数有RELEASE、FORWARD、BACKWARD
  motor3.run(RELEASE); // 使用关键字RELEASE作为参数使用时,run库函数将会让扩展板停止提供电机运转动力
  motor4.run(RELEASE); // 电机旋转一旦失去动力就会自然的停止转动。
}
 
void loop() {
  motor1.run(FORWARD); // 这4条语句的作用是利用run库函数控制4个电机"正向"旋转。
  motor2.run(FORWARD); // 这里所谓的“正向”旋转只是一种说法,假如您发现电机旋转方向和您所要的“正向”不一致。
  motor3.run(FORWARD); // 您可以将电机的两个引线从扩展板上断开,然后交换顺序再接到扩展板接口上
  motor4.run(FORWARD); // 这时您会看到同样使用FORWARD关键字作为run库函数的参数,电机的旋转方向却反过来了。
  
  for (int i=0; i<=255; i++) {   // 这里使用for循环语句控制4个电机速度由停止逐步加速,最终电机运转达到最大速度。
    motor1.setSpeed(i);          // 在for循环语句的作用下,setSpeed库函数的速度参数i由0逐渐增大,最终达到255。
    motor2.setSpeed(i);          // 因此电机运行速度也是由停止逐渐加速,最终达到最大速度。
    motor3.setSpeed(i);          // 对于一些模型电机来说,当速度参数小于一定数值以后就不能转动了。也就是说,也许您的电机
    motor4.setSpeed(i);          // 在速度参数在小于某一个速度参数数值的时候就无法转动了。这属于正常现象。
    delay(10);                   // 具体这个最小值是多少,对于不同的电机来说是不同的。有的可能是50也有的可能是100。
 }                               // 换句话说,很可能您的某一个直流电机在速度参数小于50的情况下就无法转动了。
                                 // 也可能您的另一个直流电机在参数100以下的情况下就无法转动了。
                                 
  for (int i=255; i>=0; i--) {   // 这里使用for循环语句控制4个电机由最大旋转速度逐步减速最终停止旋转。
    motor1.setSpeed(i);          // 这一系列语句的操作与上一段for循环语句类似。唯一区别是上一段for循环控制速度参数i由0涨到255
    motor2.setSpeed(i);          // 而这一段语句控制速度参数i由255减小到0。同样您可能会发现当速度参数没有减小到零的时候,电机就已经
    motor3.setSpeed(i);          // 停止旋转了。这其中的原因在上一段for循环语句中已经介绍了。不在这里赘述了。
    motor4.setSpeed(i); 
    delay(10);
 }
  
  motor1.run(BACKWARD); // 这4条语句的作用是利用run库函数控制4个电机"反向"旋转。
  motor2.run(BACKWARD); // 同样的,这里所谓的“反向”旋转也只是一种说法。这部分程序内容 
  motor3.run(BACKWARD); // 与本程序33-36行中的内容十分类似。唯一区别就是使用了“BACKWARD”
  motor4.run(BACKWARD); // 关键字参数来通过库函数run控制电机“反向”旋转。
  
  for (int i=0; i<=255; i++) {   // 利用for循环语句控制速度参数i由小到大
    motor1.setSpeed(i);          // 电机也会以“反向”旋转的方式由停止逐步达到最大速度
    motor2.setSpeed(i); 
    motor3.setSpeed(i); 
    motor4.setSpeed(i); 
    delay(10);
 }
 
  for (int i=255; i>=0; i--) {   // 利用for循环语句控制速度参数i由大到小
    motor1.setSpeed(i);          // 电机也会以“反向”旋转的方式由最大速度逐步减小到停止
    motor2.setSpeed(i); 
    motor3.setSpeed(i); 
    motor4.setSpeed(i); 
    delay(10);
 }
  
  motor1.run(RELEASE);   // 这四条语句作用是使用关键字RELEASE作为run函数的参数。
  motor2.run(RELEASE);   // 在这种情况下,AFMotor扩展板将会停止为电机旋转提供动力。
  motor3.run(RELEASE);   // 电机也就会自然的停止转动。
  motor4.run(RELEASE);   // 本段程序后面的delay(1000)的作用就是让4个电机保持无旋转动力状态1秒钟
  
  delay(1000);
}

驱动28BYJ-48步进电机电路

AFMotor电机扩展板最多可以驱动2个28BYJ-48步进电机。以下我们将给您介绍两种电机扩展板的使用方法。第一种是在您开发项目时的使用方法,第二种是项目开发完毕后,您在使用扩展板驱动电机工作时的方法。这两种方法最大的区别在于:开发时的Arduino开发板是通过USB数据线连接在电脑上的。但是在工作时开发板是不连接电脑的。

项目开发时AFMOTOR电机扩展板使用方法

首先介绍的是在项目开发时AFMotor电机扩展板的使用方法。请看下图展示的电路连接说明。
在这里插入图片描述
AFMotord电机扩展板驱动28BYJ-48步进电机(开发时电路连接)

与驱动直流电机的原理相同,在使用AFMotor扩展板开发步进电机项目时,扩展板上的跳线也一定要移除!请务必注意!

工作运行时AFMOTOR电机扩展板使用方法

一般在正常工作状态下,Arduino开发板是不会与电脑连接的。这时我们就要通过AFMotor电机扩展板上外接电源端口为扩展板和Arduino同时供电。在这种情况下的电路连接如下图所示:
在这里插入图片描述
AFMotord电机扩展板驱动28BYJ-48步进电机(工作时电路连接)


驱动28BYJ-48步进电机示例程序

示例程序1

本示例程序旨在演示如何使用Arduino Uno开发板通过AFMotor电机扩展板以及AFMotor库来驱动2个28BYJ-48步进电机。
如需查看此示例程序演示视频,请点击这里

AFMotor电机扩展板驱动2个28BYJ-48步进电机示例程序-1

/*
AFMotor电机扩展板驱动2个28BYJ-48步进电机示例程序-1
By 太极创客(http://www.taichi-maker.com)
2019-03-01
 
本示例程序旨在演示如何使用Arduino Uno开发板通过AFMotor电机扩展板以及AFMotor库来驱动2个28BYJ-48步进电机。
 
如需获得更多关于本示例程序的电路连接以及AFMotor电机扩展板的资料信息,
请参考太极创客网站(http://www.taichi-maker.com),并在首页搜索栏中搜索关键字:AFMotor。
 
AFMotor库虽然可以用于驱动步进电机,但是它的功能太简单了。所以我们建议您使用AccelStepper库来控制28BYJ-48步进电机。
关于如何使用AccelStepper库控制步进电机的相关参考资料,请您前往太极创客网站(http://www.taichi-maker.com),并且在首页
的搜索栏中输入关键字“AFMotor”就可以找到我站专门介绍AFMotor电机扩展板的页面。在该页面里除了有如何使用AccelStepper库
控制AFMotor电机扩展板的资料,还有很多其它资料信息帮助您学习使用Arduino控制AFMotor电机扩展板。
*/
#include <AFMotor.h> // 本程序中使用AFMotor库
 
AF_Stepper motor1(2048, 1);  // 这2条语句的作用是建立2个步进电机对象,它们的名称分别是:motor1/2。
AF_Stepper motor2(2048, 2);  // 对象名称后面括号中的两个参数分别代表了步进电机旋转一周的步数以及
                              // 步进电机连接在扩展板上的端口号。如AF_Stepper motor1(2048, 1)语句中
                              // 参数2048代表motor1旋转一周需要走2048步。假如您的电机旋转一周需要32步,
                              // 那么请在第一个参数位置输入32这一数字参数。
                              // 括号中第二个参数1代表motor1连接在M1和M2端口。
                              // 对于motor2对象,它括号中的参数2代表该电机连接在M3和M4端口。
 
void setup() {
  Serial.begin(9600);         //启动串口通讯
  
  motor1.setSpeed(10);        // 这2条语句的作用是通过setSpped库函数设置电机运行速度。
  motor2.setSpeed(10);        // setSpped库函数中的参数是运行速度参数。
                              // 速度参数越大,运转速度越快。参数为0时电机停止转动。
}
 
/*
以下的loop函数中有4段程序语句。它们的内容十分类似,主要语句都是是通过step库函数来控制
步进电机的运行模式。step库函数一共有3个参数。如loop函数的第二行语句:motor1.step(2048, FORWARD, SINGLE)。
括号中的第一个参数是控制电机走的步数,这里的参数2048就是让电机走2048步。
接下来的关键字参数"FORWARD"作用是控制电机旋转方向。"FORWARD"是控制电机"正转",
这里也可以使用关键字"BACKWARD"让电机"反转"。
最后一个关键字参数是用于控制步进电机运转模式的。这里可选的关键字参数有:
SINGLE - 全步进模式(单线圈)。电机每走一步,扩展板只给一相线圈供电。
DOUBLE - 全步进模式(双线圈)。电机每走一步,扩展板会同时给两相线圈供电。
         此模式运行的电机比SINGLE模式下的扭矩要更大,但是电机耗电也会更多。
INTERLEAVE - 半步进模式。这种模式是SINGLE和DOUBLE的混合。电机每走一步,扩展板对线圈供电方式
             在一相和两相之间交替切换。举例来说,电机走第一步时,只有一相线圈通电。
             走第二步时,会有两相线圈供电,然后又是一相,再两相......这样交替通电。
             这种控制模式的优点是电机运行更流畅,但是缺点是运行速度大打折扣。
MICROSTEP - 微步进模式。此模式下的电机运行更光滑,但缺点是扭矩会打折扣。    
*/
 
void loop() {
  Serial.println("Single Mode");        //串口监视器输出当前运行模式为“Single”
  motor1.step(2048, FORWARD, SINGLE);    //步进电机以SINGLE模式"正转"2048步
  motor1.step(2048, BACKWARD, SINGLE);   //步进电机以SINGLE模式"反转"2048步
 
  Serial.println("Double Mode");        //串口监视器输出当前运行模式为“Double”
  motor2.step(2048, FORWARD, DOUBLE);    //步进电机以DOUBLE模式"正转"2048步
  motor2.step(2048, BACKWARD, DOUBLE);   //步进电机以DOUBLE模式"反转"2048步
 
  Serial.println("Interleave Mode");        //串口监视器输出当前运行模式为“Interleave”
  motor1.step(2048, FORWARD, INTERLEAVE);    //步进电机以INTERLEAVE模式"正转"2048步
  motor1.step(2048, BACKWARD, INTERLEAVE);   //步进电机以INTERLEAVE模式"反转"2048步
 
  Serial.println("Micrsostep Mode");         //串口监视器输出当前运行模式为“Micrsostep”
  motor2.step(2048, FORWARD, MICROSTEP);      //步进电机以MICROSTEP模式"正转"2048步
  motor2.step(2048, BACKWARD, MICROSTEP);     //步进电机以MICROSTEP模式"反转"2048步
}

示例程序2

无法复制本示例程序?

本示例程序旨在演示如何使用Arduino Uno开发板通过AFMotor电机扩展板以及AccelStepper库驱动2个28BYJ-48步进电机。由于本程序主要目的是演示AFMotor电机扩展板使用方法,因此本程序仅仅是让28BYJ-48步进电机在AFMotor的控制下匀速旋转。 对于AccelStepper库的丰富功能,本程序没有做出很完整的演示。AccelStepper库的功能远远超过本示例程序所演示的内容。 如果您希望了解AccelStepper库的详细使用方法,请点击这里进入本站的AccelStepper库页
如需查看此示例程序演示视频,请点击这里

AFMotor电机扩展板通过AccelStepper库驱动2个28BYJ-48步进电机示例程序

/*
AFMotor电机扩展板通过AccelStepper库驱动2个28BYJ-48步进电机示例程序
By 太极创客(http://www.taichi-maker.com)
2019-02-27
 
本示例程序旨在演示如何使用Arduino Uno开发板通过AFMotor电机扩展板以及AccelStepper库驱动2个28BYJ-48步进电机。
 
由于本程序主要目的是演示AFMotor电机扩展板使用方法,因此本程序仅仅是让28BYJ-48步进电机在AFMotor的控制下匀速旋转。
对于AccelStepper库的丰富功能,本程序没有做出很完整的演示。AccelStepper库的功能远远超过本示例程序所演示的内容。
如果您希望了解AccelStepper库的详细使用方法,请参考太极创客网站的AccelStepper库介绍页面。网址:
http://www.taichi-maker.com/homepage/reference-index/arduino-library-index/accelstepper-library/
 
如需获得更多关于本示例程序的电路连接以及AFMotor电机扩展板的资料信息,
请参考太极创客网站,并在首页搜索栏中搜索关键字:AFMotor。
*/
#include <AFMotor.h>       // 本程序将用到AFMotor库
#include <AccelStepper.h>  // 本程序将用到AccelStepper库
 
AF_Stepper motor1(2048, 1);  // 这2条语句的作用是建立2个步进电机对象,它们的名称分别是:motor1/2。
AF_Stepper motor2(2048, 2);  // 对象名称后面括号中的两个参数分别代表了步进电机旋转一周的步数以及
                              // 步进电机连接在扩展板上的端口号。如AF_Stepper motor1(2048, 1)语句中
                              // 参数2048代表motor1旋转一周需要走2048步。假如您的电机旋转一周需要32步,
                              // 那么请在第一个参数位置输入32这一数字参数。
                              // 括号中第二个参数1代表motor1连接在M1和M2端口。
                              // 对于motor2对象,它括号中的参数2代表motor2连接在M3和M4端口。
/*
以下4个函数(forwardstep1/backwardstep1/forwardstep2/backwardstep2)
都仅有一条调用AFMotor库函数onestep的语句。 如函数名称所示,onestep库函数可以让电机运行1步。
onestep库函数有两个参数,参数1用于控制运行方向。参数2用于控制步进电机运行模式。对于第2个参数,还可以
使用DOUBLE,INTERLEAVE,MICROSTEP。在本程序末尾部分有这些参数所对应的运行模式详细说明。
*/
void forwardstep1() {                
  motor1.onestep(FORWARD, SINGLE);    
}                                     
void backwardstep1() {  
  motor1.onestep(BACKWARD, SINGLE);
}
void forwardstep2() {  
  motor2.onestep(FORWARD, SINGLE);
}
void backwardstep2() {  
  motor2.onestep(BACKWARD, SINGLE);
}
 
/*
以下2条语句的作用是建立2个步进电机对象,它们的名称分别是:stepper1、stepper2。
步进电机对象名称后的括号里有两个参数。这两个参数是步进电机“正转1步”和“反转1步”
的函数名称。
 
我们来看一个例子:AccelStepper stepper1(forwardstep1, backwardstep1)
该程序语句括号中第1个参数是motor1电机正转1步的函数名称forwardstep1。
第2个参数是motor1电机反转1步的函数名称backwardstep1。
有了这两个函数名称,AccelStepper库就可以建立stepper1对象控制步进电机motor1了。
同理,stepper2是用来控制motor2的AccelStepper库对象。
*/
 
AccelStepper stepper1(forwardstep1, backwardstep1); 
AccelStepper stepper2(forwardstep2, backwardstep2); 
 
void setup(){        
   stepper1.setMaxSpeed(500);	
   stepper1.setSpeed(300);	
   stepper2.setMaxSpeed(500); 
   stepper2.setSpeed(300);  
}
 
void loop(){  
   stepper1.runSpeed();
   stepper2.runSpeed();
}
 
/*
AFMotor的onestep库函数运行模式说明:
 
SINGLE - 全步进模式(单线圈)。电机每走一步,扩展板只给一相线圈供电。
DOUBLE - 全步进模式(双线圈)。电机每走一步,扩展板会同时给两相线圈供电。
         此模式运行的电机比SINGLE模式下的扭矩要更大,但是电机耗电也会更多。
INTERLEAVE - 半步进模式。这种模式是SINGLE和DOUBLE的混合。电机每走一步,扩展板对线圈供电方式
             在一相和两相之间交替切换。举例来说,电机走第一步时,只有一相线圈通电。
             走第二步时,会有两相线圈供电,然后又是一相,再两相......这样交替通电。
             这种控制模式的优点是电机运行更流畅,但是缺点是运行速度大打折扣。
MICROSTEP - 微步进模式。此模式下的电机运行更光滑,但缺点是扭矩会打折扣。   
*/

示例程序3

以下示例程序旨在演示如何使用AccelStepper库配合AFMotor电机扩展板以及AccelStepper库的丰富功能。由于此程序大量使用AccelStepper库的程序内容,如果想要完全理解这段程序,需要您首先了解AccelStepper库的使用方法。太极创客网站中有专门介绍AccelStepper库的讲解,您可以点击这里进入该页面

Arduino通过AFMotor电机扩展板以及AccelStepper库控制28BYJ-48步进电机示例程序-2

Arduino

/*
  Arduino通过AFMotor电机扩展板以及AccelStepper库控制28BYJ-48步进电机示例程序-2
  by 太极创客(www.taichi-maker.com)
  2019-03-01
  
  本程序旨在演示AccelStepper库的丰富功能以及如何使用AccelStepper库配合AFMotor电机扩展板。
  您可以通过Arduino IDE的串口监视器输入电机控制指令从而控制步进电机。
  
  注意:使用此示例程序时应将串口监视器设置为“没有结束符”。
    
 * 电机指令列表
 * 'o' 利用currentPosition获取当前电机输出轴位置并通过串口监视器输出该信息
 * 'v' 利用moveTo函数使电机运行到用户指定坐标位置,moveTo函数不会“block”程序。
 *     例:v1024 - 将电机moveTo到1024位置
 * 'm' 利用move函数使电机运行相应步数。move函数不会“block”程序。
 *     例:m1024 - 使电机运行1024步 
 * 'r' 利用runToNewPosition函数让电机运行到用户指定坐标位置。runToNewPosition函数功能
 *     与moveTo函数功能基本相同。唯一区别是runToNewPosition函数将“block”程序运行。
 *     即电机没有到达目标位置前,Arduino将不会继续执行后续程序内容。
 *     这一点很像Arduino官方Stepper库中的step函数。
 *     例:r1024 - 将电机runToNewPosition到1024位置。Arduino在电机达到1024位置前将停止
 *     其它程序任务的执行。
 * 's' 利用setCurrentPosition函数设置当前位置为用户指定位置值。
 *     例:s0 - 设置当前位置为0
 * 'a' 利用setAcceleration函数设置加速度 
 *     例:a100 - 设置电机运行的加速度为100 
 * 'x' 利用setMaxSpeed函数设置最大速度 
 *     例:x500 - 设置电机运行的最大速度为500 
 * 'd' 用户通过此指令可指定哪一个电机进行工作  
 *     例:d1 一号电机工作,d2 二号电机工作, d0 两个电机同时工作
 
  如需获得更多关于本示例程序的电路连接以及AFMotor电机扩展板的资料信息,
  请参考太极创客网站,并在首页搜索栏中搜索关键字:AFMotor。
 
  如果您希望了解AccelStepper库的详细使用方法,请参考太极创客网站的AccelStepper库介绍页面。网址:
  http://www.taichi-maker.com/homepage/reference-index/arduino-library-index/accelstepper-library/  
*/
#include <AccelStepper.h>
#include <AFMotor.h>
 
#define stepperSpeed 300
 
AF_Stepper motor1(2048, 1);
AF_Stepper motor2(2048, 2);
 
char cmd;        //电机指令字符
int data;        //电机指令参数
int stepperNum;  //控制电机编号
 
void forwardstep1() {  
  motor1.onestep(FORWARD, DOUBLE);
}
void backwardstep1() {  
  motor1.onestep(BACKWARD, DOUBLE);
}
 
void forwardstep2() {  
  motor2.onestep(FORWARD, DOUBLE);
}
void backwardstep2() {  
  motor2.onestep(BACKWARD, DOUBLE);
}
 
AccelStepper stepper1(forwardstep1, backwardstep1); // use functions to step
AccelStepper stepper2(forwardstep2, backwardstep2); // use functions to step
void setup(){    
   stepper1.setMaxSpeed(stepperSpeed);	
   stepper1.setAcceleration(100.0);  // 1号电机加速度50.0
   stepper2.setMaxSpeed(stepperSpeed); 
   stepper2.setAcceleration(100.0);  // 2号电机加速度50.0 
 
  Serial.begin(9600);
  Serial.println(F("++++++++++++++++++++++++++++++++++"));     
  Serial.println(F("+Taichi-Maker AFMotor Shield Demo+"));   
  Serial.println(F("+     www.taichi-maker.com       +"));  
  Serial.println(F("++++++++++++++++++++++++++++++++++"));  
  Serial.println(F(""));  
  Serial.println(F("Please input motor command:"));    
}
 
void loop(){  
 if (Serial.available()) {     // 检查串口缓存是否有数据等待传输 
    cmd = Serial.read();        // 获取电机指令中指令信息    
    Serial.print(F("cmd = "));
    Serial.print(cmd);    
    Serial.print(F(" , ")); 
    
    data = Serial.parseInt();   // 获取电机指令中参数信息  
    Serial.print(F("data = "));
    Serial.print(data);   
    Serial.println(F(""));    
    
    runUsrCmd();
  }
 
  stepper1.run();
  stepper2.run();
}
 
void runUsrCmd(){
  switch(cmd){ 
    case 'o': //利用currentPosition获取当前电机输出轴位置并通过串口监视器输出该信息
    
      Serial.print(F("stepper1 Position: ")); 
      Serial.println(stepper1.currentPosition());   
      Serial.print(F("stepper2 Position: ")); 
      Serial.println(stepper2.currentPosition()); 
      Serial.print(F("Current Running Motor: "));  
      
      if (stepperNum == 1 || stepperNum == 2 ) {
        Serial.print(F("Motor# ")); 
        Serial.println(stepperNum); 
      } else if (stepperNum == 0 ) {
        Serial.println(F("Both Motors")); 
      }
      break;    
           
    case 'v': //利用moveTo函数使电机运行到用户指定坐标位置,moveTo函数不会“block”程序。
       
      if (stepperNum == 1){
        Serial.print(F("Motor1 'moveTo' "));  Serial.println(data); 
        stepper1.moveTo(data); 
      } else if (stepperNum == 2){
        Serial.print(F("Motor2 'moveTo' "));  Serial.println(data); 
        stepper2.moveTo(data); 
      }else if (stepperNum == 0){
        Serial.print(F("Both Motors 'moveTo' "));  Serial.println(data); 
        stepper1.moveTo(data);
        stepper2.moveTo(data); 
      } 
      break;
      
    case 'm':   // 利用move函数使电机运行相应步数。move函数不会“block”程序。
      
      if (stepperNum == 1){
        Serial.print(F("Motor1 'move'  "));  Serial.println(data); 
        stepper1.move(data); 
      } else if (stepperNum == 2){
        Serial.print(F("Motor2 'move'  "));  Serial.println(data);
        stepper2.move(data); 
      }else if (stepperNum == 0){
        Serial.print(F("Both Motors 'move'  "));  Serial.println(data);
        stepper1.move(data);
        stepper2.move(data); 
      } 
      break;
 
    case 'r':  //利用runToNewPosition函数让电机运行到用户指定位置值。  
      if (stepperNum == 1){
        Serial.print(F("Motor1 'runToNewPosition' "));
        Serial.println(data);
        stepper1.runToNewPosition(data);  
      } else if (stepperNum == 2){
        Serial.print(F("Motor2 'runToNewPosition' "));
        Serial.println(data);
        stepper2.runToNewPosition(data);  
      }else if (stepperNum == 0){
        Serial.print(F("Both Motors 'runToNewPosition' "));
        Serial.println(data);
        stepper1.runToNewPosition(data); 
        stepper2.runToNewPosition(data);   
      }      
      break;   
      
    case 's':   //利用setCurrentPosition函数设置当前位置为用户指定位置值。
      if (stepperNum == 1){
        Serial.print(F("Set stepper1 Current Position to "));
        Serial.println(data);
        stepper1.setCurrentPosition(data); 
      } else if (stepperNum == 2){
        Serial.print(F("Set stepper2 Current Position to "));
        Serial.println(data);
        stepper2.setCurrentPosition(data);
      }else if (stepperNum == 0){
        stepper1.moveTo(data);
        Serial.print(F("Set both steppers' Current Position to "));
        Serial.println(data);
        stepper1.setCurrentPosition(data);
        stepper2.setCurrentPosition(data);
      }         
      break;
 
    case 'a':  //利用setAcceleration函数设置加速度 
      if (stepperNum == 1){
        Serial.print(F("Motor1 'setAcceleration' "));
        Serial.println(data);
        stepper1.setAcceleration(data);  
      } else if (stepperNum == 2){
        Serial.print(F("Motor2 'setAcceleration' "));
        Serial.println(data);
        stepper2.setAcceleration(data);  
      }else if (stepperNum == 0){
        Serial.print(F("Both Motors 'setAcceleration' "));
        Serial.println(data);
        stepper1.setAcceleration(data); 
        stepper2.setAcceleration(data); 
      }      
      break;   
 
    case 'x':  //利用setMaxSpeed函数设置最大速度   
      if (stepperNum == 1){
        Serial.print(F("Motor1 'setMaxSpeed' "));
        Serial.println(data);
        stepper1.setMaxSpeed(data); 
      } else if (stepperNum == 2){
        Serial.print(F("Motor2 'setMaxSpeed' "));
        Serial.println(data);
        stepper2.setMaxSpeed(data); 
      }else if (stepperNum == 0){
        Serial.print(F("Both Motors 'setMaxSpeed' "));
        Serial.println(data);
        stepper1.setMaxSpeed(data); 
        stepper2.setMaxSpeed(data); 
      } 
      break;  
 
    case 'd':  //用户通过此指令可指定哪一个电机进行工作  
      if ( data == 1 || data == 2 ){
        stepperNum = data;
        Serial.print(F("Running Motor "));  Serial.println(stepperNum); 
      } else if (data == 0 ){
        stepperNum = data;
        Serial.println(F("Running Both Motors "));  
      } else {
        Serial.print(F("Motor Number Wrong.")); 
      }
      break;
                     
    default:  // 未知指令
      Serial.println(F("Unknown Command"));
  }
}

驱动舵机(伺服电机)电路连接

AFMotor扩展板驱动舵机实际上就是通过Arduino的9号和10号引脚来驱动舵机。10号引脚对应的是扩展板上的servo1端口,9号引脚对应的是servo2端口。

如果您希望更多的了解如何使用Arduino驱动舵机,请点击这里进入舵机资料页面
在这里插入图片描述
Arduino AFMotor扩展板驱动舵机(伺服电机)电路连接说明


驱动舵机(伺服电机)示例程序

AFMotor电机扩展板驱动2个舵机示例程序

Arduino

/*
AFMotor电机扩展板驱动2个舵机示例程序
By 太极创客(http://www.taichi-maker.com)
2019-03-02
 
本示例程序旨在演示如何使用Arduino Uno开发板通过AFMotor电机扩展板
驱动2个舵机。AFMotor扩展板驱动舵机实际上就是通过Arduino的9号和10号
引脚来驱动舵机。10号引脚对应的是扩展板上的servo1端口,9号引脚对应的
是servo2端口。
 
如需获得更多关于本示例程序的电路连接以及AFMotor电机扩展板的资料信息,
请参考太极创客网站,并在首页搜索栏中搜索关键字:AFMotor。
 
如果您希望更多的了解如何使用Arduino驱动舵机,请参阅太极创客网站的舵机资料。
http://www.taichi-maker.com/homepage/reference-index/circuit-reference-index/#servo
*/
 
#include <Servo.h>
 
Servo servo1;   //建立舵机对象servo1
Servo servo2;   //建立舵机对象servo2
 
int pos = 0;    
void setup() {
  servo1.attach(10);    //servo1对象接在扩展板servo1端口。
                        //servo1端口是由Arduino的10号引脚来控制的。
  servo2.attach(9);     //servo2对象接在扩展板servo2端口。
                        //servo2端口是由Arduino的9号引脚来控制的。 
}
 
void loop() {
  //以下程序将控制servo1输出轴左右旋转180度
  for (pos = 0; pos <= 180; pos += 1) { 
    servo1.write(pos);              
    delay(15);                       
  }
  for (pos = 180; pos >= 0; pos -= 1) { 
    servo1.write(pos);    
    delay(15);       
  }
  
  //以下程序将控制servo2输出轴左右旋转180度
  for (pos = 0; pos <= 180; pos += 1) { 
    servo2.write(pos);              
    delay(15);                       
  }
  for (pos = 180; pos >= 0; pos -= 1) { 
    servo2.write(pos);    
    delay(15);       
  }  
}

其它AFMotor扩展板相关资料

模拟输入输出引脚

Arduino开发板的模拟输入输出引脚(A0~A5)没有被AFMotor扩展板所占用。如下图右下角黑色文字和箭头指示,模拟输入输出引脚被AFMotor扩展板延申至板上以便使用。模拟引脚旁的另外两排引脚分别是Arduino的+5V引脚,和接地引脚。它们的具体位置也用黑色文字在下图中进行了标注。
在这里插入图片描述

Arduino 电机扩展板 端口说明

遗憾的是,市场上销售的AFMotor扩展板并没有为模拟引脚以及旁边的+5V和GND引脚焊接插针。如果您需要使用这些引脚的话,需要自己焊接插针。

未占用引脚

Arduino引脚2 和引脚13都没有被AFMotor电机扩展板所占用。如果您手中有AFMotor扩展板,您可以在扩展板的正面靠近2号引脚的位置找到一个没有焊接插针的预留孔。这个预留孔就是用于焊接额外插针以便于您使用引脚2的。与上面所提到的模拟引脚一样,引脚2预留孔也没有预先焊好插针。如果要用到此引脚,需要您自行焊接插针。

引脚13虽然没有被AFMotor扩展板占用,但是扩展板上没有将该引脚引出。使用引脚13需要您自行焊接额外引线才能使用。

AFMOTOR电机扩展板电路

在这里插入图片描述

AFMOTOR电机扩展板电路资料

百度网盘下载:https://pan.baidu.com/s/1zNbOb2hMowRBCPY095myyw (提取码:16p4)

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐