零基础入门学用Arduino 第四部分(三)

news2024/11/17 16:19:23

重要的内容写在前面:

  1. 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。
  2. 个人把这个教程学完之后,整体感觉是很好的,如果有条件的可以先学习一些相关课程,学起来会更加轻松,相关课程有数字电路(强烈推荐先学数电,不然可能会有一些地方理解起来很困难)、模拟电路等,然后就是C++(注意C++是必学的)
  3. 文章中的代码都是跟着老师边学边敲的,不过比起老师的版本我还把注释写得详细了些,并且个人认为重要的地方都有详细的分析。
  4. 一些函数的介绍有参考太极创客官网给出的中文翻译,为了便于现查现用,把个人认为重要的部分粘贴了过来并做了一些修改。
  5. 如有错漏欢迎指正。

视频链接: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();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1838878.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nodejs爬取小红书图片

昨天的文章已经描述了可以抓取评论区内容&#xff0c; 抓取图片内容和抓取评论区的内容基本一致 我们可以看到接口信息中含有图片链接&#xff0c;我们要做的就是爬取图片链接然后下载 这边要用到的模块为const downloadrequire(download) 将爬到的图片链接存放到images数组…

STM8单片机的GPIO口介绍

本篇文章依托于stm8单片机和lora模块 目录 一、GPIO口测试相关硬件电路图 &#xff08;a&#xff09;USB转串口底板PA3控制LED6 (b)Lora模块底板PA3接口 &#xff08;c&#xff09;LED灯电路 二、参考官方例程实现GPIO口的输出 三、GPIO相关函数的了解 &#xff08;1&a…

docker安装使用

文章目录 docker产生的原因传统虚拟机容器化技术 docker组成安装docker镜像加速docker安装过程中遇到的问题以及解决办法Errors during downloading metadata for repository root_:Failed to set locale, defaulting to C.UTF-8 docker产生的原因 传统虚拟机 在不使用docker…

从“野人饭”走红,探索品牌户外化营销趋势丨小红书内容分析

wildeat&#xff0c;户外是人的天性的回归 近来&#xff0c;“wildeat&#xff08;户外野吃&#xff09;”的风潮在小红书逐渐兴起。越来越多的人选择到户外吃一顿&#xff0c;做一次“野人”&#xff0c;主打一个只要氛围到了&#xff0c;就地开饭&#xff0c;不愁吃什么&…

AI智能写作工具, 免费在线智能创作内容网站

对于需要创作内容的同学&#xff0c;选择一款适合自己的AI写作工具可以极大的提高创作效率。下面小编就来和大家分享几款可以生成高质量原创内容的AI写作工具。 1. Kimi智能助手 Kimi智能助手是一款集成了先进算法的AI工具&#xff0c;它能够理解复杂的语言模式&#xff0c;生…

如何用Vue3和ApexCharts打造引人注目的3D径向条形图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 使用 ApexCharts 构建美观的 Vue.js 径向条形图 应用场景 径向条形图是一种用于可视化单一数据点及其与目标或理想值的关系的图表类型。它在显示进度、完成率或其他类似度量时非常有用。 基本功能 这段代码…

划分子网和构造超网的学习

子网掩码长度&#xff1d;32位 某位&#xff1d;1&#xff1a;IP地址中的对应位为网络号和子网号 某位&#xff1d;0&#xff1a;IP地址中的对应位为主机号 从一个 IP 数据报的首部并无法判断源主机或目的主机所连接的网络是否进行了子网划分。 使用子网掩码(subnet mask)可…

EasyCVR/EasyDSS无人机直播技术助力野生动物监测

近日有新闻报道&#xff0c;一名挖掘机师傅在清理河道时&#xff0c;意外挖出一只稀有的扬子鳄&#xff0c;挖机师傅小心翼翼地将其放在一边&#xff0c;扬子鳄也顺势游回一旁的河道中。 随着人类对自然环境的不断探索和开发&#xff0c;野生动物及其栖息地的保护显得愈发重要。…

AI产品组件——TTS产品

语音合成TTS 序列猴子TTS&#xff0c;每个发音人付费标准不同&#xff0c;通过序列猴子开放平台使用。 微软TTS&#xff0c;采用信用卡后付费模式。Speech Studio&#xff0c;付费模式采用统一付费的形式&#xff0c;音效有一款女声效果逼真。 女声&#xff1a;晓晓&#xff…

三天带你快速入门Transformer,真的太牛了

前言 听说Transformer很火&#xff1f;但感觉它好复杂&#xff1f;别担心&#xff0c;三天时间&#xff0c;你也可以轻松入门Transformer&#xff01; 第一天&#xff0c;我们先来了解Transformer的“骨架”。简单来说&#xff0c;它就像是一个双层机器&#xff0c;上面一层…

mysql5.7windows安装修改密码

mysql5.7windows安装修改密码 1.首先下载Windows 64位安装包2.安装服务3.my.ini4.初始化4.做成Windows服务5.重置密码 1.首先下载Windows 64位安装包 2.安装服务 双击运行安装服务&#xff0c;一直next&#xff1b; 在Choose Setup Type界面中 选择Custom选项&#xff0c;意思…

万界星空科技QMS质量管理介绍

产品的生产质量是企业发展之根本&#xff0c;对所有企业来说&#xff0c;建立完善质量控制体系&#xff0c;对企业生产经营以及发展竞争具有至关重要的影响&#xff0c;可以说是企业质量保证的防火墙。QMS质量管理系统对任何一家企业都具有重要意义&#xff0c;可帮助企业提高生…

nextjs(持续学习中)

return ( <p className{${lusitana.className} text-xl text-gray-800 md:text-3xl md:leading-normal}> Welcome to Acme. This is the example for the{’ } Next.js Learn Course , brought to you by Vercel. ); } 在顶级 /public 文件夹下提供静态资产 **默认 /…

Linux磁盘格式化与重新分区

1.df -BG查看磁盘挂载情况 2.fdisk -l查看磁盘详细信息 3.sudo mkfs.ext4 /path 格式化磁盘 4.挂载格式化后磁盘 挂载成功

《化工设计通讯》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问&#xff1a;《化工设计通讯》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊 问&#xff1a;《化工设计通讯》级别&#xff1f; 答&#xff1a;省级。主办单位&#xff1a;湖南化工设计院有限公司 主管单位&#xff1…

jeecg spring数据源用户名和密码加密 避免明文安全漏洞

1.目的 由于系统部署在互联网&#xff0c;配置文件中的数据库账号密码使用明文&#xff0c;存在安全隐患&#xff0c;做等保测试时要求对其加密。 2.实现方法 Jeecg框架本身有PasswordUtil可以使用PBEWITHMD5andDES进行加密&#xff0c;这里为方便改造&#xff0c;且安全性较…

andrio复习

第2章 Android常见界面布局 View View与ViewGroup View&#xff1a;按钮&#xff08;Button&#xff09;、文本框&#xff08;TextView&#xff09;和图像视图&#xff08;ImageView&#xff09;等 ViewGroup&#xff1a;LinearLayout、RelativeLayout、FrameLayout等都是Vi…

智慧校园综合解决方案:提供全方位的学校管理支持

在当今数字化时代&#xff0c;学校管理面临着越来越多的挑战&#xff0c;包括学生管理、教职员工管理、校园安全等。为了应对这些挑战&#xff0c;智慧校园综合解决方案应运而生。智慧校园综合解决方案融入了先进的信息技术&#xff0c;为学校带来了一场管理与教育模式的革新。…

欢迎 Stable Diffusion 3 加入 Diffusers

作为 Stability AI 的 Stable Diffusion 家族最新的模型&#xff0c;Stable Diffusion 3(SD3) 现已登陆 Hugging Face Hub&#xff0c;并且可用在 &#x1f9e8; Diffusers 中使用了。 Stable Diffusion 3https://stability.ai/news/stable-diffusion-3-research-paper 当前放出…

为什么Mid journey很容易就能做出很有氛围感的图而SD却容易做图很丑?

前言 6月12日&#xff0c;Midjourney更新了一项新的功能——模型个性化&#xff0c;这一项功能最重要的作用就是能够让生成的图像更加符合你自己的审美标准。就像每个艺术家都有自己的独特风格一样&#xff0c;有了这项模型个性化功能的加持&#xff0c;每个人都能生成具有鲜明…