ARDUINO:控制两台步进电机同步运转

要控制两台步进电机同步进行运转,即同时起步,同时加速,同时到达最大速度,同时减速,最后同时停止。
这是要有一定的算法的:
假如B1电机所走的路程是B2的n倍,在同时起步的前提下,v1=n*v2,a1=n*a2, 才能保证以上的同步结果。


本文程序是在太极创客程序的基础上对其修改后的,接线方式完全保持不变。主要的修改如下:

1, data(电机指令参数)和 stepperNum(控制电机编号) 两个变量改为数组;

2,data(电机指令参数)和 stepperNum(控制电机编号) 两个变量由int改为long int;

3, runUserCmd()例程中if语句逻辑关系的修改。
 

在输入以下命令后,可以看到两个步进电机的运行始终保持同步:

 a100,20
 x500,100
 m10240,2048

/* Arduino通过AccelStepper库控制28BYJ-48步进电机示例程序-2
  by 太极创客(www.taichi-maker.com)
  可通过Arduino IDE 串口监视器输入电机指令
  本程序旨在演示move/moveTo/runToNewPosition区别 (两个28BYJ-48电机演示)
  
  如需获得本示例程序详细电路信息以及如何使用Arduino控制电机的更多知识,请参考太极创客网站:
  http://www.taichi-maker.com/homepage/reference-index/arduino-library-index/accelstepper-library/
 
 * 电机指令列表
 * '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 两个电机同时工作
*/
 
#include "AccelStepper.h"
 
// 电机步进方式定义
#define FULLSTEP 4    //全步进参数
#define HALFSTEP 8    //半步进参数
 
// 定义步进电机引脚 
#define motor1Pin1  8     // 一号28BYJ48连接的ULN2003电机驱动板引脚 in1
#define motor1Pin2  9     // 一号28BYJ48连接的ULN2003电机驱动板引脚 in2
#define motor1Pin3  10    // 一号28BYJ48连接的ULN2003电机驱动板引脚 in3
#define motor1Pin4  11    // 一号28BYJ48连接的ULN2003电机驱动板引脚 in4
                        
                        
#define motor2Pin1  4     // 二号28BYJ48连接的ULN2003电机驱动板引脚 in1
#define motor2Pin2  5     // 二号28BYJ48连接的ULN2003电机驱动板引脚 in2
#define motor2Pin3  6     // 二号28BYJ48连接的ULN2003电机驱动板引脚 in3
#define motor2Pin4  7     // 二号28BYJ48连接的ULN2003电机驱动板引脚 in4
 
// 定义两个步进电机对象
// 定义中ULN2003驱动板引脚顺序为 in1-in3-in2-in4
// 1号电机设置为全步进运行,2号电机设置为全步进运行
AccelStepper stepper1(FULLSTEP, motor1Pin1, motor1Pin3, motor1Pin2, motor1Pin4);
AccelStepper stepper2(FULLSTEP, motor2Pin1, motor2Pin3, motor2Pin2, motor2Pin4);
 
char cmd;        //电机指令字符
long int data[2];        //电机指令参数
long int stepperNum[2]={1,1};  //控制电机编号
 
void setup()
{
  stepper1.setMaxSpeed(500.0);    // 1号电机最大速度500 
  stepper1.setAcceleration(50.0);  // 1号电机加速度50.0
 
  stepper2.setMaxSpeed(500.0);    // 2号电机最大速度500 
  stepper2.setAcceleration(50.0);  // 2号电机加速度50.0
 
  Serial.begin(9600);
  Serial.println(F("++++++++++++++++++++++++++++++++++"));     
  Serial.println(F("+ Taichi-Maker AccelStepper 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[0] = Serial.parseInt();   // 获取电机指令中参数信息  
    data[1] = Serial.parseInt();   // 获取电机指令中参数信息  
    Serial.print(F("data = "));
    Serial.print(data[0]);   
    Serial.print(",");   
    Serial.print(data[1]);   
    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.println(F("Current Running Motor: "));  
      if (stepperNum[0] == 1) {
        Serial.println(F("Motor# 0"));  
      }
    if (stepperNum[1] == 1) {
        Serial.println(F("Motor# 1"));  
      }
      break;    
           
    case 'v': //利用moveTo函数使电机运行到用户指定坐标位置,moveTo函数不会“block”程序。
       
      if (stepperNum[0] == 1){
        Serial.print(F("Motor1 'moveTo' "));  Serial.println(data[0]); 
        stepper1.moveTo(data[0]); 
      }
    if (stepperNum[1] == 1){
        Serial.print(F("Motor2 'moveTo' "));  Serial.println(data[1]); 
        stepper2.moveTo(data[1]); 
      } 
      break;
      
    case 'm':   // 利用move函数使电机运行相应步数。move函数不会“block”程序。
      
      if (stepperNum[0] == 1){
        Serial.print(F("Motor1 'move'  "));  Serial.println(data[0]); 
        stepper1.move(data[0]); 
      }
    if (stepperNum[1] == 1){
        Serial.print(F("Motor2 'move'  "));  Serial.println(data[1]);
        stepper2.move(data[1]); 
      }  
      break;
 
    case 'r':  //利用runToNewPosition函数让电机运行到用户指定位置值。  
      if (stepperNum[0] == 1){
        Serial.print(F("Motor1 'runToNewPosition' "));
        Serial.println(data[0]);
        stepper1.runToNewPosition(data[0]);  
      }
    if (stepperNum[1] == 1){
        Serial.print(F("Motor2 'runToNewPosition' "));
        Serial.println(data[1]);
        stepper2.runToNewPosition(data[1]);  
      }      
      break;   
      
    case 's':   //利用setCurrentPosition函数设置当前位置为用户指定位置值。
      if (stepperNum[0] == 1){
        Serial.print(F("Set stepper1 Current Position to "));
        Serial.println(data[0]);
        stepper1.setCurrentPosition(data[0]); 
      }
    if (stepperNum[1] == 1){
        Serial.print(F("Set stepper2 Current Position to "));
        Serial.println(data[1]);
        stepper2.setCurrentPosition(data[1]);
      }         
      break;
 
    case 'a':  //利用setAcceleration函数设置加速度 
      if (stepperNum[0] == 1){
        Serial.print(F("Motor1 'setAcceleration' "));
        Serial.println(data[0]);
        stepper1.setAcceleration(data[0]);  
      }
    if (stepperNum[1] == 1){
        Serial.print(F("Motor2 'setAcceleration' "));
        Serial.println(data[1]);
        stepper2.setAcceleration(data[1]);  
      }       
      break;   
 
    case 'x':  //利用setMaxSpeed函数设置最大速度   
      if (stepperNum[0] == 1){
        Serial.print(F("Motor1 'setMaxSpeed' "));
        Serial.println(data[0]);
        stepper1.setMaxSpeed(data[0]); 
      }
    if (stepperNum[1] == 1){
        Serial.print(F("Motor2 'setMaxSpeed' "));
        Serial.println(data[1]);
        stepper2.setMaxSpeed(data[1]); 
      } 
      break;  
 
    case 'd':  //用户通过此指令可指定哪一个电机进行工作  
      if ( data[0] + data[1] == 1 ){
        stepperNum[0] = data[0];
        stepperNum[1] = data[1];
        Serial.print(F("Running Motor "));  Serial.println((data[0]==1)?(data[0]):(data[1])); 
      }
    if (data[0] + data[1] == 2){
        stepperNum[0] = data[0];
        stepperNum[1] = data[1];
        Serial.println(F("Running Both Motors "));  
      } else {
        Serial.print(F("Motor Number Wrong.")); 
      }
      break;
                     
    default:  // 未知指令
      Serial.println(F("Unknown Command"));
  }
}

TwoSteppers

  • 9
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值