重要的内容写在前面:
- 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。
- 个人把这个教程学完之后,整体感觉是很好的,如果有条件的可以先学习一些相关课程,学起来会更加轻松,相关课程有数字电路(强烈推荐先学数电,不然可能会有一些地方理解起来很困难)、模拟电路等,然后就是C++(注意C++是必学的)。
- 文章中的代码都是跟着老师边学边敲的,不过比起老师的版本我还把注释写得详细了些,并且个人认为重要的地方都有详细的分析。
- 一些函数的介绍有参考太极创客官网给出的中文翻译,为了便于现查现用,把个人认为重要的部分粘贴了过来并做了一些修改。
- 如有错漏欢迎指正。
视频链接:4-1-1 电机基本结构与工作原理_哔哩哔哩_bilibili
太极创客官网:太极创客 – Arduino, ESP8266物联网的应用、开发和学习资料
四、Arduino AFMotor电机扩展板
1、Arduino AFMotor电机扩展板概述
(1)Arduino AFMotor电机扩展板专门与Arduino开发板配合使用,如下图所示,它是直接插在Arduino开发板上的。
(2)AFMOTOR电机扩展板主要功能特点:
①最多可驱动4个模型直流电机。
②最多可驱动2个28BYJ-48步进电机。
③最多可驱动2个舵机(伺服电机)。
④板载两块L293D芯片负责电机驱动的核心工作
⑤可配合Arduino Uno/Mega开发板使用(这里主要针对Uno开发板进行介绍)。
(3)Arduino AFMotor电机扩展板的各个端口如下所示。
①AFMotor电机扩展板上配有外接电源接口,该接口所连接的直流电源可以为电机和Arduino开发板供电。
[1]使用AFMotor电机扩展板驱动电机时,要考虑的问题就是电源的输出功率需要达到驱动电机的要求(对于工作电压低于4.5V的直流电机,不建议使用AFMotor驱动板来驱动),并且不宜过大。
[2]AFMotor扩展板中起关键作用的芯片是L293D,该芯片所允许的直流电源电压范围是4.5V ~25V,因此AFMotor扩展板外接电源接口允许连接的电源也是4.5V~25V。
[3]通常我们使用AFMotor电机扩展板所驱动的电机就是普通的模型电机,对于这一类型的电机,它们的工作电流大约是500mA左右,因此只要为扩展板配一个500 mA~1000 mA的外接电源就足够了;假如电机工作电流超过500mA,那么就要考虑为扩展板上的L293D加装芯片。
[4]外接电源极性千万不要接反,否则会对扩展板造成损坏。
②Arduino开发板的模拟输入输出引脚(A0~A5)没有被AFMotor扩展板所占用,模拟输入输出引脚被AFMotor扩展板延申至板上以便使用。模拟引脚旁的另外两排引脚分别是Arduino的+5V引脚和接地引脚。
③Arduino引脚2和引脚13都没有被AFMotor电机扩展板所占用。
2、AFMotor库
(1)使用AFMotor电机扩展板驱动电机以前,需要先将AFMotor库(属于第三方库)安装到Arduino IDE中。
(2)AFMotor库函数:
①AF_DCMotor.setSpeed(speed):将电机AF_DCMotor的运行速度设置为speed(取值范围为0-255)。
②AF_DCMotor.run(mode):mode的可选值为RELEASE、FORWARD、BACKWARD。
[1]RELEASE:让扩展板停止为电机AF_DCMotor提供运转动力,电机AF_DCMotor一旦失去动力就会自然的停止转动
[2]FORWARD:设置电机AF_DCMotor的运动方向为正向。
[3]BACKWARD:设置电机AF_DCMotor的运动方向为反向。
③AF_DCMotor.step(steps, mode1, mode2):该函数针对步进电机,其中steps为控制步进电机运动的步数,mode1的可选值为FORWARD、BACKWARD,即选择运动方向为正向或反向,mode2的可选值为SINGLE、DOUBLE、INTERLEAVE、NICROSTEP,其意义分别为全步进模式(单线圈)、全步进模式(双线圈)、半步进模式、微步进模式。
④AF_DCMotor.onestep(mode1, mode2):该函数针对步进电机,其中mode1的可选值为FORWARD、BACKWARD,即选择运动方向为正向或反向,mode2的可选值为SINGLE、DOUBLE、INTERLEAVE、NICROSTEP,即选择运动方式。
(3)借助AF_Stepper类,可以建立AccelStepper库能使用的步进电机对象。根据之前的经验,AccelStepper类的对象的构造函数参数可以是步进模式以及4个控制引脚编号,在这里可以将构造函数的参数替换为两个自定义函数的函数名,两个函数均封装一个AF_Stepper类的onestep函数,分别控制AF_Stepper对象的电机在正反方向上各走一步,根据这两个函数,Arduino可得到AF_Stepper对象的电机的相关信息,用于初始化AccelStepper类的对象。
3、Arduino驱动直流电机
(1)在AFMotor电机扩展板的两侧共有4个直流电机端口,每一个端口都有独立的编号,分别为M1、M2、M3、M4,每一个电机端口都是由两个接线端子所构成,如下图所示。如果只是单纯的想要让电机转起来,那么这两根引线连接到扩展板端口上是没有顺序的;但如果对电机的旋转方向有所要求,而电机旋转的方向与用户所期待的相反,那么可以将这两根电机引线从扩展板上断开,然后交换顺序再接到扩展板端子上,这时会看到电机旋转的方向就反过来了。
(2)驱动直流电机电路的连接:
①项目开发时驱动直流电机电路的连接:(下图红色箭头指示的跳线一定要移除,该跳线的作用是控制Arduino开发板由外接电源供电,而项目开发时Arduino开发板由电脑供电)
②工作运行时驱动直流电机电路的连接:(下图红色箭头指示的跳线要安置好,工作运行时Arduino开发板由外接电源供电)
(3)示例程序:
#include <AFMotor.h>
AF_DCMotor motor1(1); //为1号电机建立对象,1号电机连接AFMotor扩展板的电机端口号码为1
AF_DCMotor motor2(2); //为2号电机建立对象,2号电机连接AFMotor扩展板的电机端口号码为2
AF_DCMotor motor3(3); //为3号电机建立对象,3号电机连接AFMotor扩展板的电机端口号码为3
AF_DCMotor motor4(4); //为4号电机建立对象,4号电机连接AFMotor扩展板的电机端口号码为4
void setup()
{
//4个电机的转速均设置为200
motor1.setSpeed(200);motor2.setSpeed(200);
motor3.setSpeed(200);motor4.setSpeed(200);
//初始时电机全部不转动
motor1.run(RELEASE);motor2.run(RELEASE);motor3.run(RELEASE);motor4.run(RELEASE);
}
void loop()
{
//将4个电机的旋转方向均设置为正向
motor1.run(FORWARD);motor2.run(FORWARD);
motor3.run(FORWARD);motor4.run(FORWARD);
for (int i=0; i<=255; i++){ //从0开始,4个电机的转速每隔10ms增加1,直至增加到255
motor1.setSpeed(i);motor2.setSpeed(i);motor3.setSpeed(i);motor4.setSpeed(i);
delay(10);
}
for (int i=255; i>=0; i--){ //从255开始,4个电机的转速每隔10ms减小1,直至减小到0
motor1.setSpeed(i);motor2.setSpeed(i);motor3.setSpeed(i);motor4.setSpeed(i);
delay(10);
} //对于一些模型电机来说,当速度参数小于一定数值以后就不能转动了,这属于正常现象
//将4个电机的旋转方向均设置为反向
motor1.run(BACKWARD);motor2.run(BACKWARD);
motor3.run(BACKWARD);motor4.run(BACKWARD);
for (int i=0; i<=255; i++){ //从0开始,4个电机的转速每隔10ms增加1,直至增加到255
motor1.setSpeed(i);motor2.setSpeed(i);motor3.setSpeed(i);motor4.setSpeed(i);
delay(10);
}
for (int i=255; i>=0; i--){ //从255开始,4个电机的转速每隔10ms减小1,直至减小到0
motor1.setSpeed(i);motor2.setSpeed(i); motor3.setSpeed(i);motor4.setSpeed(i);
delay(10);
} //对于一些模型电机来说,当速度参数小于一定数值以后就不能转动了,这属于正常现象
//停止为4个电机提供运转动力
motor1.run(RELEASE);motor2.run(RELEASE);motor3.run(RELEASE);motor4.run(RELEASE);
delay(1000); //让4个电机保持无旋转动力状态1秒钟
}
4、Arduino驱动28BYJ-48步进电机
(1)在AFMotor电机扩展板的两侧共有两个步进电机端口,每一个电机端口都是由五个接线端子所构成。
(2)驱动28BYJ-48步进电机电路的连接:
①项目开发时驱动28BYJ-48步进电机电路的连接:(下图红色箭头指示的跳线一定要移除,该跳线的作用是控制Arduino开发板由外接电源供电,而项目开发时Arduino开发板由电脑供电)
②工作运行时驱动28BYJ-48步进电机电路的连接:(下图红色箭头指示的跳线要安置好,工作运行时Arduino开发板由外接电源供电)
(3)示例程序:
①示例程序1:
#include <AFMotor.h>
AF_Stepper motor1(2048, 1); //为步进电机1建立步进电机对象,它旋转一周的步数为2048,连接在扩展板上的端口号为1
AF_Stepper motor2(2048, 2); //为步进电机2建立步进电机对象,它旋转一周的步数为2048,连接在扩展板上的端口号为2
void setup()
{
Serial.begin(9600); //启动串口通讯
motor1.setSpeed(10); //设置电机1的运行速度参数为10
motor2.setSpeed(10); //设置电机2的运行速度参数为10
}
void loop()
{
Serial.println("Single Mode");
motor1.step(2048, FORWARD, SINGLE); //步进电机1以全步进模式(单线圈)"正转"2048步
motor1.step(2048, BACKWARD, SINGLE);//步进电机2以全步进模式(单线圈)"反转"2048步
Serial.println("Double Mode");
motor2.step(2048, FORWARD, DOUBLE); //步进电机1以全步进模式(双线圈)"正转"2048步
motor2.step(2048, BACKWARD, DOUBLE);//步进电机2以全步进模式(双线圈)"反转"2048步
Serial.println("Interleave Mode");
motor1.step(2048, FORWARD, INTERLEAVE); //步进电机1以半步进模式"正转"2048步
motor1.step(2048, BACKWARD, INTERLEAVE); //步进电机2以半步进模式"反转"2048步
Serial.println("Micrsostep Mode");
motor2.step(2048, FORWARD, MICROSTEP); //步进电机1以微步进模式"正转"2048步
motor2.step(2048, BACKWARD, MICROSTEP); //步进电机2以微步进模式"反转"2048步
}
②示例程序2:
#include <AFMotor.h>
#include <AccelStepper.h>
AF_Stepper motor1(2048, 1); //为步进电机1建立步进电机对象,它旋转一周的步数为2048,连接在扩展板上的端口号为1
AF_Stepper motor2(2048, 2); //为步进电机2建立步进电机对象,它旋转一周的步数为2048,连接在扩展板上的端口号为2
void forwardstep1() {
motor1.onestep(FORWARD, SINGLE); //电机1正向旋转1步
}
void backwardstep1() {
motor1.onestep(BACKWARD, SINGLE); //电机1反向旋转1步
}
void forwardstep2() {
motor2.onestep(FORWARD, SINGLE); //电机2正向旋转1步
}
void backwardstep2() {
motor2.onestep(BACKWARD, SINGLE); //电机2反向旋转1步
}
//借助AF_Stepper类,建立AccelStepper库能使用的步进电机对象
AccelStepper stepper1(forwardstep1, backwardstep1); //根据让电机1在正反向各旋转1步的自定义函数,Arduino可得到电机1的相关信息,用于初始化stepper1
AccelStepper stepper2(forwardstep2, backwardstep2); //根据让电机2在正反向各旋转1步的自定义函数,Arduino可得到电机2的相关信息,用于初始化stepper2
void setup()
{
stepper1.setMaxSpeed(500); //设置电机1的最大运行速度为500
stepper1.setSpeed(300); //设置电机1在匀速模式下的运行速度为300
stepper2.setMaxSpeed(500); //设置电机2的最大运行速度为500
stepper2.setSpeed(300); //设置电机2在匀速模式下的运行速度为300
}
void loop()
{
stepper1.runSpeed(); //电机1匀速旋转
stepper2.runSpeed(); //电机2匀速旋转
}
③示例程序3:
[1]全局变量、宏定义、包含头文件及初始化操作:
#include <AccelStepper.h>
#include <AFMotor.h>
#define stepperSpeed 300 //匀速模式下电机的运动速度
AF_Stepper motor1(2048, 1); //为步进电机1建立步进电机对象,它旋转一周的步数为2048,连接在扩展板上的端口号为1
AF_Stepper motor2(2048, 2); //为步进电机2建立步进电机对象,它旋转一周的步数为2048,连接在扩展板上的端口号为2
char cmd; //存储电机指令字符
int data; //存储电机指令参数
int stepperNum; //存储当前控制电机的编号
void forwardstep1() {
motor1.onestep(FORWARD, SINGLE); //电机1正向旋转1步
}
void backwardstep1() {
motor1.onestep(BACKWARD, SINGLE); //电机1反向旋转1步
}
void forwardstep2() {
motor2.onestep(FORWARD, SINGLE); //电机2正向旋转1步
}
void backwardstep2() {
motor2.onestep(BACKWARD, SINGLE); //电机2反向旋转1步
}
//借助AF_Stepper类,建立AccelStepper库能使用的步进电机对象
AccelStepper stepper1(forwardstep1, backwardstep1); //根据让电机1在正反向各旋转1步的自定义函数,Arduino可得到电机1的相关信息,用于初始化stepper1
AccelStepper stepper2(forwardstep2, backwardstep2); //根据让电机2在正反向各旋转1步的自定义函数,Arduino可得到电机2的相关信息,用于初始化stepper2
void setup()
{
stepper1.setMaxSpeed(stepperSpeed); //设置1号电机匀速模式下的运动速度为300
stepper1.setAcceleration(100.0); //设置1号电机的加速度为50.0
stepper2.setMaxSpeed(stepperSpeed); //设置2号电机匀速模式下的运动速度为300
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:"));
}
[2]主循环部分:
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(); //设置电机1为先加速后减速模式
stepper2.run(); //设置电机2为先加速后减速模式
}
[3]用户命令处理部分:
void runUsrCmd()
{
switch(cmd){
case 'o': //获取当前电机输出轴位置
Serial.print(F("stepper1 Position: "));
Serial.println(stepper1.currentPosition()); //获取当前电机1的输出轴位置
Serial.print(F("stepper2 Position: "));
Serial.println(stepper2.currentPosition()); //获取当前电机2的输出轴位置
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': //使电机运行到用户指定的坐标位置
if (stepperNum == 1){
Serial.print(F("Motor1 'moveTo' "));Serial.println(data);
stepper1.moveTo(data); //控制电机1运行到data对应的绝对位置
}
else if (stepperNum == 2){
Serial.print(F("Motor2 'moveTo' "));Serial.println(data);
stepper2.moveTo(data); //控制电机2运行到data对应的绝对位置
}
else if (stepperNum == 0){ //两个电机可以同时运行
Serial.print(F("Both Motors 'moveTo' "));Serial.println(data);
stepper1.moveTo(data); //控制电机1运行到data对应的绝对位置
stepper2.moveTo(data); //控制电机2运行到data对应的绝对位置
}break;
case 'm': //使电机运行相应步数(可顺时针也可逆时针)
if (stepperNum == 1){
Serial.print(F("Motor1 'move' "));Serial.println(data);
stepper1.move(data); //以当前位置为参照点,控制电机1运行到data对应的相对位置
}
else if (stepperNum == 2){
Serial.print(F("Motor2 'move' "));Serial.println(data);
stepper2.move(data); //以当前位置为参照点,控制电机2运行到data对应的相对位置
}
else if (stepperNum == 0){ //两个电机可以同时运行
Serial.print(F("Both Motors 'move' "));Serial.println(data);
stepper1.move(data); //以当前位置为参照点,控制电机1运行到data对应的相对位置
stepper2.move(data); //以当前位置为参照点,控制电机2运行到data对应的相对位置
}break;
case 'r': //让电机运行到用户指定的位置
if (stepperNum == 1){
Serial.print(F("Motor1 'runToNewPosition' "));Serial.println(data);
stepper1.runToNewPosition(data); //控制电机1运行到data对应的绝对位置
}
else if (stepperNum == 2){
Serial.print(F("Motor2 'runToNewPosition' "));Serial.println(data);
stepper2.runToNewPosition(data); //控制电机2运行到data对应的绝对位置
}
else if (stepperNum == 0){ //电机1运行结束后,电机2才能开始运行
Serial.print(F("Both Motors 'runToNewPosition' "));Serial.println(data);
stepper1.runToNewPosition(data); //控制电机1运行到data对应的绝对位置
stepper2.runToNewPosition(data); //控制电机2运行到data对应的绝对位置
}break;
case 's': //设置当前位置为用户指定位置值
if (stepperNum == 1){
Serial.print(F("Set stepper1 Current Position to "));
Serial.println(data); //将电机1输出轴当前位置的数值设置为data
stepper1.setCurrentPosition(data);
}
else if (stepperNum == 2){
Serial.print(F("Set stepper2 Current Position to "));
Serial.println(data); //将电机2输出轴当前位置的数值设置为data
stepper2.setCurrentPosition(data);
}
else if (stepperNum == 0){
Serial.print(F("Set both steppers' Current Position to "));Serial.println(data);
stepper1.setCurrentPosition(data); //将电机1输出轴当前位置的数值设置为data
stepper2.setCurrentPosition(data); //将电机2输出轴当前位置的数值设置为data
}break;
case 'a': //设置电机在先加速后减速模式下运行的加速度
if (stepperNum == 1){
Serial.print(F("Motor1 'setAcceleration' "));Serial.println(data);
stepper1.setAcceleration(data); //将电机1的加速度设置为data
}
else if (stepperNum == 2){
Serial.print(F("Motor2 'setAcceleration' "));Serial.println(data);
stepper2.setAcceleration(data); //将电机2的加速度设置为data
}
else if (stepperNum == 0){
Serial.print(F("Both Motors 'setAcceleration' "));Serial.println(data);
stepper1.setAcceleration(data); //将电机1的加速度设置为data
stepper2.setAcceleration(data); //将电机2的加速度设置为data
}break;
case 'x': //设置电机在先加速后减速模式下运行的最大速度
if (stepperNum == 1){
Serial.print(F("Motor1 'setMaxSpeed' "));Serial.println(data);
stepper1.setMaxSpeed(data); //将电机1的最大速度设置为data
}
else if (stepperNum == 2){
Serial.print(F("Motor2 'setMaxSpeed' "));Serial.println(data);
stepper2.setMaxSpeed(data); //将电机2的最大速度设置为data
}
else if (stepperNum == 0){
Serial.print(F("Both Motors 'setMaxSpeed' "));Serial.println(data);
stepper1.setMaxSpeed(data); //将电机1的最大速度设置为data
stepper2.setMaxSpeed(data); //将电机2的最大速度设置为data
}break;
case 'd': //用户通过此指令可指定哪一个电机进行工作
if (data == 1 || data == 2){ //指定仅控制电机1或电机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"));
}
}
5、Arduino驱动伺服电机
(1)AFMotor扩展板驱动舵机实际上就是通过Arduino的9号和10号引脚来驱动舵机,10号引脚对应的是扩展板上的servo1端口,9号引脚对应的是servo2端口,如下图所示(直流电源的连接这里不再赘述)。
(2)驱动舵机(伺服电机)示例程序:
#include <Servo.h>
Servo servo1; //建立舵机对象servo1
Servo servo2; //建立舵机对象servo2
int pos = 0; //记录舵机轴的当前角度
void setup()
{
servo1.attach(10); //舵机1接在扩展板servo1端口,servo1端口是由Arduino的10号引脚来控制的
servo2.attach(9); //舵机2接在扩展板servo2端口,servo2端口是由Arduino的9号引脚来控制的
}
void loop()
{
for (pos = 0; pos <= 180; pos += 1){ //舵机1从0°旋转至180°
servo1.write(pos);delay(15);
}
for (pos = 180; pos >= 0; pos -= 1){ //舵机1从180°旋转至0°
servo1.write(pos);delay(15);
}
for (pos = 0; pos <= 180; pos += 1){ //舵机2从0°旋转至180°
servo2.write(pos);delay(15);
}
for (pos = 180; pos >= 0; pos -= 1){ //舵机2从180°旋转至0°
servo2.write(pos);delay(15);
}
}
五、Arduino CNC电机扩展板
1、Arduino CNC电机扩展板概述
(1)Arduino CNC电机扩展板专门与Arduino开发板配合使用,如下图所示,它是直接插在Arduino开发板上的。
(2)CNC扩展板可以支持A4988、DRV8825等步进电机驱动板,这里主要介绍如何使用A4988驱动板来配合CNC扩展板使用。下图中CNC电机扩展板装配有3个A4988驱动板,实际上最多可以装配4个,具体安装多少个A4988是根据需要驱动步进电机数量来决定的,一台步进电机需要一个A4988。(安装A4988驱动板的时候注意驱动板安装方向不要搞反)
(3)每一个A4988接口上都有三组步进设置插针,这三组插针旁的电路板上印刷有M0/M1/M2,可以(且仅可以)通过在上面安置跳线帽设置电机的步进模式,如下图所示。
(4)Arduino CNC电机扩展板上配有外接直流电源接口,该接口允许接入的电压范围是12V~36V,具体应该连接多大的电源电压是根据被驱动的电机工作电压所决定的,如果使用的电机是NEMA17步进电机(42步进电机),通常该电机的工作电压是12伏特,那么可以为扩展板配一个12伏特的外接电源。
(5)用于控制电机的Arduino引脚与CNC扩展板上印刷的标识的对应关系如下所示,需要注意的是A端口比较特殊。
①Arduino引脚8 —– CNC扩展板EN(所有电机驱动板的使能引脚,低电平有效)。
②Arduino引脚5 —– CNC扩展板X.DIR(X端口方向控制引脚)。
③Arduino引脚2 —– CNC扩展板X.STEP(X端口步进控制引脚)。
④Arduino引脚6 —– CNC扩展板Y.DIR(Y端口方向控制引脚)。
⑤Arduino引脚3 —– CNC扩展板Y.STEP(Y端口步进控制引脚)。
⑥Arduino引脚7 —– CNC扩展板Z.DIR(Z端口方向控制引脚)。
⑦Arduino引脚4 —– CNC扩展板Z.STEP(Z端口步进控制引脚)。
⑧Arduino引脚13—– CNC扩展板A.DIR(A端口方向控制引脚)。
⑨Arduino引脚12—– CNC扩展板A.STEP(A端口步进控制引脚)。
(6)CNC扩展板的端口A比其它三个端口的功能要更丰富一些,它有两种工作模式。
①第一种模式是复制X、Y、Z中任意一个端口上的电机运行情况(以下简称复制模式),所谓复制模式就是端口A所接的电机完全复制其它端口上的电机运行状态,比如将端口A设置为复制端口X,那么端口A电机的运行状况将是完全复制端口X上的电机运行状况,在复制模式下,端口A电机不受Arduino开发板的程序控制而只是单纯地复制端口X电机运行。
②第二种是独立模式来控制电机,这时端口A上的电机会根据Arduino的程序控制运行,在独立模式下,端口A上安装的A4988驱动板的step引脚受Arduino的12号引脚控制,dir引脚受Arduino的13号引脚控制。
③以上两种模式的设置是通过扩展板上专门用于设置端口A工作模式的一系列插针来完成的,如下图所示。
(7)CNC扩展板的其它引脚功能介绍:
①步进电机控制插针共有两排,在插针旁印有各个引脚的名称标识,每行插针标识都使用“/”作为分割,“/”左侧的文字是图中蓝色插针的引脚标识,“/”右侧的文字是图中黄色插针的引脚标识,这些引脚的作用是便于使用Arduino开发板以外的开发板来控制CNC扩展板。
②CNC扩展板右下部分还配有两排很长的引脚插针,其中黑色的引脚全都是GND引脚,白色引脚插针旁的文字标识是这些引脚的名称,它们与Arduino的引脚是联通的,具体如下:
[1]CNC扩展板Z+引脚——Arduino引脚11。
[2]CNC扩展板Z-引脚——Arduino引脚11。
[3]CNC扩展板Y+引脚——Arduino引脚10。
[4]CNC扩展板Y-引脚——Arduino引脚10。
[5]CNC扩展板X+引脚——Arduino引脚9。
[6]CNC扩展板X-引脚——Arduino引脚9。
[7]CNC扩展板SpnEN引脚——Arduino引脚12。
[8]CNC扩展板SpnDir引脚——Arduino引脚13。
[9]CNC扩展板CoolEn引脚——Arduino引脚A3。
[10]CNC扩展板Abort引脚——Arduino引脚A0。
[11]CNC扩展板Hold引脚——Arduino引脚A1。
[12]CNC扩展板Resume引脚——Arduino引脚A2。
[13]CNC扩展板E-STOP引脚——Arduino引脚Reset。
2、Arduino CNC扩展板驱动NEMA步进电机
(1)Arduino CNC扩展板驱动1个NEMA步进电机:
①电路连接:
②示例程序:
#include <AccelStepper.h>
const int xdirPin = 5; //X端口方向控制引脚连接Arduino的引脚号为5
const int xstepPin = 2; //X端口步进控制引脚连接Arduino的引脚号为2
const int xenablePin = 8; //使能控制引脚连接Arduino的引脚号为8
const int moveSteps = 200; //对于NEMA 17来说,全步进模式下200步转子旋转一周
AccelStepper stepper1(1,xstepPin,xdirPin); //建立步进电机对象
//“1”表示该电机使用A4988电机驱动板驱动
void setup()
{
pinMode(xstepPin,OUTPUT); //Arduino控制A4988步进引脚为输出模式
pinMode(xdirPin,OUTPUT); //Arduino控制A4988方向引脚为输出模式
pinMode(xenablePin,OUTPUT); //Arduino控制A4988使能引脚为输出模式
digitalWrite(xenablePin,LOW); //将使能控制引脚设置为低电平,从而让电机驱动板进入工作状态
stepper1.setMaxSpeed(300.0); //设置电机运行的最大速度300
stepper1.setAcceleration(20.0); //设置电机的加速度20.0
}
void loop()
{
if (stepper1.currentPosition() == 0)
{
stepper1.moveTo(moveStep); //stepper1控制电机正向旋转1周(针对全步进模式)
}
else if (stepper1.currentPosition() == moveSteps)
{
stepper1.moveTo(0); //stepper1控制电机反向旋转1周(针对全步进模式)
}
stepper1.run(); //1号电机以先加速后减速的模式运行
}
(2)Arduino CNC扩展板驱动3个NEMA步进电机:
①电路连接:
②示例程序:
#include <AccelStepper.h>
const int xenablePin = 8; //使能控制引脚连接Arduino的引脚号为8
const int xdirPin = 5; //X端口方向控制引脚连接Arduino的引脚号为5
const int xstepPin = 2; //X端口步进控制引脚连接Arduino的引脚号为2
const int ydirPin = 6; //Y端口方向控制引脚连接Arduino的引脚号为6
const int ystepPin = 3; //Y端口步进控制引脚连接Arduino的引脚号为3
const int zdirPin = 7; //Z端口方向控制引脚连接Arduino的引脚号为7
const int zstepPin = 4; //Z端口步进控制引脚连接Arduino的引脚号为4
const int moveSteps = 200; //测试电机运行使用的运行步数
AccelStepper stepper1(1,xstepPin,xdirPin); //建立步进电机对象1
AccelStepper stepper2(1,ystepPin,ydirPin); //建立步进电机对象2
AccelStepper stepper3(1,zstepPin,zdirPin); //建立步进电机对象3
void setup()
{
pinMode(xstepPin,OUTPUT);pinMode(xdirPin,OUTPUT);pinMode(ystepPin,OUTPUT);
pinMode(ydirPin,OUTPUT);pinMode(zstepPin,OUTPUT);pinMode(zdirPin,OUTPUT);
pinMode(enablePin,OUTPUT);
digitalWrite(enablePin,LOW); //将使能控制引脚设置为低电平,从而让电机驱动板进入工作状态
stepper1.setMaxSpeed(300.0);stepper1.setAcceleration(20.0);
stepper2.setMaxSpeed(300.0);stepper2.setAcceleration(20.0);
stepper3.setMaxSpeed(300.0);stepper3.setAcceleration(20.0);
}
void loop()
{
if (stepper1.currentPosition() == 0)
stepper1.moveTo(moveSteps); //电机1正向旋转1周(针对全步进模式)
else if (stepper1.currentPosition() == moveSteps)
stepper1.moveTo(0); //电机1反向旋转1周(针对全步进模式)
if (stepper2.currentPosition() == 0)
stepper2.moveTo(moveSteps/2); //电机2正向旋转半周(针对全步进模式)
else if (stepper2.currentPosition() == moveSteps/2)
stepper2.moveTo(0); //电机2反向旋转半周(针对全步进模式)
if (stepper3.currentPosition() == 0)
stepper3.moveTo(moveSteps/4); //电机3正向旋转0.25周(针对全步进模式)
else if (stepper3.currentPosition() == moveSteps/4)
stepper3.moveTo(0); //电机3反向旋转0.25周(针对全步进模式)
stepper1.run();stepper2.run();stepper3.run();
}
(3)Arduino CNC扩展板驱动4个NEMA步进电机:
①电路连接:
②示例程序:
#include <AccelStepper.h>
const int xenablePin = 8; //使能控制引脚连接Arduino的引脚号为8
const int xdirPin = 5; //X端口方向控制引脚连接Arduino的引脚号为5
const int xstepPin = 2; //X端口步进控制引脚连接Arduino的引脚号为2
const int ydirPin = 6; //Y端口方向控制引脚连接Arduino的引脚号为6
const int ystepPin = 3; //Y端口步进控制引脚连接Arduino的引脚号为3
const int zdirPin = 7; //Z端口方向控制引脚连接Arduino的引脚号为7
const int zstepPin = 4; //Z端口步进控制引脚连接Arduino的引脚号为4
const int adirPin = 13; //A端口方向控制引脚连接Arduino的引脚号为13
const int astepPin = 12; //A端口步进控制引脚连接Arduino的引脚号为12
const int moveSteps = 200;
AccelStepper stepper1(1,xstepPin,xdirPin); //建立步进电机对象1
AccelStepper stepper2(1,ystepPin,ydirPin); //建立步进电机对象2
AccelStepper stepper3(1,zstepPin,zdirPin); //建立步进电机对象3
AccelStepper stepper4(1,astepPin,adirPin); //建立步进电机对象4
void setup()
{
pinMode(xstepPin,OUTPUT);pinMode(xdirPin,OUTPUT);
pinMode(ystepPin,OUTPUT);pinMode(ydirPin,OUTPUT);
pinMode(zstepPin,OUTPUT);pinMode(zdirPin,OUTPUT);
pinMode(astepPin,OUTPUT);pinMode(adirPin,OUTPUT);
pinMode(enablePin,OUTPUT);digitalWrite(enablePin,LOW);
stepper1.setMaxSpeed(300.0);stepper1.setAcceleration(20.0);
stepper2.setMaxSpeed(300.0);stepper2.setAcceleration(20.0);
stepper3.setMaxSpeed(300.0);stepper3.setAcceleration(20.0);
stepper4.setMaxSpeed(300.0);stepper4.setAcceleration(20.0);
}
void loop()
{
if (stepper1.currentPosition() == 0) stepper1.moveTo(moveSteps);
else if (stepper1.currentPosition() == moveSteps) stepper1.moveTo(0);
if (stepper2.currentPosition() == 0) stepper2.moveTo(moveSteps/2);
else if (stepper2.currentPosition() == moveSteps/2) stepper2.moveTo(0);
if (stepper3.currentPosition() == 0) stepper3.moveTo(moveSteps/4);
else if (stepper3.currentPosition() == moveSteps/4) stepper3.moveTo(0);
if (stepper4.currentPosition() == 0) stepper4.moveTo(moveSteps/8);
else if (stepper4.currentPosition() == moveSteps/8) stepper4.moveTo(0);
stepper1.run();stepper2.run();stepper3.run();stepper4.run();
}