ARDUINO板驱动两个NEMA17电机同步运转

最近在做一个案例,要求ARDUINO板驱动两个NEMA17电机. 查了以下,有个AccelStepper.h库,用着也挺方便.但我有另一个硬性的要求,用这个库很难实现.索性自己写了个程序,完成了这一目标.

这个硬性的要求就是:两个电机要同步,即同时起步,同时停止.旋转的速度和方向可以不一样.

下面是实现的详细过程.

1.BOM

ARDUINO uno R3,1

A4988,2

5V power,1(单独给电机供电)

小面包板,1

面包线,若干

2,示意图

3,操作说明

通过ARDUINO IDE的串口监视器输入控制命令:

1,点亮LED灯

0,熄灭LED灯

4,前进200步

5,后退200步

8,先前进,再后退,即两电机先正转,再反转

9,先右旋转,再左旋转,即两电机先左正右反,再左反右正.

在电机运转时,LED等点亮.

4,指令说明

指令格式:200,400,1000000,1

200-左电机运行步数,正为前进,负为后退;

400-右电机运行步数,正为前进,负为后退;

1000000-表示在1秒内完成运行动作,单位为微秒;

1-为舵机预留的控制位.

5,源程序

// UNO + A4988 + NEMA17

//此模式两个电机可以是同步运行的,即能保持“以不同的旋转速度”同时旋转(同时开始,同时停止)。
// 逐步改进,时间、速度可输入;
// 停止是处于非激活状态 
 

int ledpin=13 ;    //定义LED灯引线。
 
//  步进电机
//  Enable,STEP步距,DIR方,MS1/MS2
int PIN[2][3]={
  {4,3,2}, //电机1 的IO引脚, 
  {7,6,5}  //电机2 的IO引脚, 
};
 
void setup()
{
  Serial.begin(9600);   //用蓝牙监视器代替

//  初始化步进电机的引脚  
  for(int i=0;i<2;i++)
  for(int j=0;j<3;j++)
    pinMode(PIN[i][j]   ,OUTPUT);  
  
  pinMode(ledpin, OUTPUT);       //设置管脚2为输出模式 , 板载LED
 
  Serial.begin(9600);
 
  digitalWrite(PIN[0][0],HIGH);    // 输出高电平,关闭电机
  digitalWrite(PIN[1][0],HIGH);    // 输出高电平,关闭电机   

}

long int num = 0;

void loop()
{
  int inChar;         // 接受从串口监视器传来的信息,如果是蓝牙监视器的话,则接受从蓝牙监视器传来的信息。
  if (Serial.available()) {
    inChar = Serial.read();
    Serial.write(inChar);
    switch (inChar) {
    case '1':
      digitalWrite(ledpin, HIGH);   // 点亮LED
      break;
    case '0':
      digitalWrite(ledpin, LOW);   // 熄灭LED
      break; 
    case '4':
      CarRun("200,400,1000000,1");
      break;
    case '5':
      CarRun("-200,-400,1000000,0");
      break;  
    case '8':
      CarRun("2000,2000,10000000,1,-2000,2000,10000000,0");
      break;
    case '9':
      CarRun("1000,-2000,10000000,1,-1000,2000,10000000,0");
      break;
    default:
      Serial.println(F("Wrong Input :("));
      break;
    }
  }
}
 
//  步进电机的旋转,200步为一周,正值为逆时针,负值为顺时针
//  step1 电机1的步进数
//  step2 电机2的步进数
//  msec  旋转时间,单位为微秒(us)
void Run(long int step1,long int step2,unsigned long int msec) {
  if(step1>0){
    digitalWrite(PIN[0][2],HIGH); // 设置高电平的方向 逆
  } else {
    digitalWrite(PIN[0][2],LOW);  // 设置低电平的方向 顺
    step1 = -step1;
  }
  if(step2>0){
    digitalWrite(PIN[1][2],HIGH); // 设置高电平的方向 逆
  } else {
    digitalWrite(PIN[1][2],LOW);  // 设置低电平的方向 顺
    step2 = -step2;
  }
  
unsigned long int mtime0,n1,n2;

mtime0=micros(); 
n1 = 0;
n2 = 0;

//  以下循环中不要出现与运转无关的语句或运算,否则可能出现较大的运行误差。
   while(micros()-mtime0<msec){
    if((micros()-mtime0)>=n1*(unsigned long int)(msec/step1))
      { digitalWrite(PIN[0][1],HIGH);
        delayMicroseconds(10);
        digitalWrite(PIN[0][1],LOW);
        delayMicroseconds(10); 
        n1++;
      }
    if((micros()-mtime0)>=n2*(unsigned long int)(msec/step2))
      { digitalWrite(PIN[1][1],HIGH);
        delayMicroseconds(10);
        digitalWrite(PIN[1][1],LOW);
        delayMicroseconds(10);
        n2++;
      } 
   }  
} 

//小车运动
void CarRun(String Dstr)
{  
  long int data1,data2,time1;
  int servo;
  long int dats[100];
  for(int i=0;i<100;i++){
    dats[i]=0;
  } 
    
  int N = GetNums(Dstr,dats); //4的倍数
  
  digitalWrite(PIN[0][0],LOW);    // 输出低电平,启动电机
  digitalWrite(PIN[1][0],LOW);    // 输出低电平,启动电机
  digitalWrite(ledpin, HIGH);   // 点亮LED
  for(int n=0;n<N/4;n++) {

  data1 = dats[n*4];
  data2 = dats[n*4+1];
  time1 = dats[n*4+2];
  servo = dats[n*4+3];

  Serial.print(F("data:"));   
  Serial.print(data1); Serial.print(F(","));   
  Serial.print(data2); Serial.print(F(","));   
  Serial.print(time1); Serial.print(F(","));   
  Serial.print(servo); Serial.println(F("<<<"));  
 
   Run(data1,data2,time1);
  }
  digitalWrite(PIN[0][0],HIGH);    // 输出高电平,关闭电机
  digitalWrite(PIN[1][0],HIGH);    // 输出高电平,关闭电机   
  digitalWrite(ledpin, LOW);   // 熄灭LED
}

//将从串口读取的数据串str进行解析到num中
//输入:str---字符串指针,
//    num---要保存数字的数组指针
//返回:数字个数
//    只取整型
int GetNums(const String str,long int* num)
{
    int len=str.length(); //strlen(str);
    int index=0;  //数值个数
    int t;    //某位的数字
    int p=1;  //默认为正数,-1为负数
    int nFlag=0;  //1:表示取到一个数字
    for(int i=0;i<len;i++)
    {
        if(str[i]=='-') {
          p=-1; 
          continue;
        }
        while(!((str[i]>='0'&&str[i]<='9')||str[i]=='+'))
        {
          i++;
        }
        while(str[i]>='0'&&str[i]<='9')
        {
          nFlag=1;
          t=str[i]-'0';
          num[index]=num[index]*10+t; 
          i++;
          if(i==len) break;
        }
        if(nFlag==1){
          num[index] *= p; 
          index++;

        }
        p=1;
        nFlag=0;
    }
    return index;
}

最后说明:

电机请接12V电源,5V可能运转不畅!

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值