极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

楼主: 万马奔腾

arduino产生脉冲控制工业用的步进电机?

[复制链接]
发表于 2013-6-19 01:51:00 | 显示全部楼层
控制步进电机加工,这才是我学习ARDUINO的唯一原因
rick_hou大侠能指点详细一些吗?
谢谢
回复 支持 反对

使用道具 举报

发表于 2013-6-20 12:29:19 | 显示全部楼层
我也在关注这个,希望能够详细讲讲,帖点代码出来
回复 支持 反对

使用道具 举报

发表于 2013-6-23 23:00:58 | 显示全部楼层
嘿嘿,这两天搬家,所以铣床什么都拆掉了,代码我找找看,因为电脑也打包了。其实你要是真的想控制3轴最好就用现成的运动控制卡,比如usbcnc什么的,并口的很多,usb目前看到的就到4轴,pc跑一个mach3什么的软件,直接读取sw或者ug生成的G代码。这样的比较可靠,也非常成熟。我其实一直想做的就是用arduino识别g码,当作一个控制执行的功能。如果仅仅是单纯的控制一轴步进电机这样的使用方式,并不多轴联动的话,还是有办法的,我用了一个Timeone的定时器生成中断,单位是百万分之一秒的样子,算上代码执行的时间什么的,大约做到50Khz不是问题。用arduino的步进电机控制貌似达不到很高的速度。
回复 支持 反对

使用道具 举报

发表于 2013-6-23 23:05:29 | 显示全部楼层
我现在找到的是相对较早写的一版两轴控制的程序。貌似当初有些问题后来就重写了。但是具体是啥问题已经忘记了,供大家参考下好了。

/*============================================================================================================
***************************   AUTOMOTOR铣床两轴控制系统   ****************************************************
D2、D3为驱动器脉冲口(pul)连接x、y两轴,当驱动器接收到脉冲,就开始驱动步进电机工作。D4、D5两口连接驱动器的dir
、ena 两口,分别控制方向和电机释放,其中ena端口默认是HIGH,LOW时将释放电机锁死功能。D6是急停按钮,当D6被按下(
高电平有效)时,将停止发送脉冲,并且在显示屏上显示停止信息,并发出声音报警信号。D7是手自动切换按钮,当D7被按下
(高电平)时,是自动走刀模式,显示屏会显示Auto,同时方向键不必按下,也会沿着设定的方向自动行进。只有当停止按钮
按下或者关闭自动模式时,才会停止,当切换为手动模式时,显示屏会显示MANUAL。D8~D11为x、y两轴的方向按钮,不可同时
开动两轴。D12为蜂鸣器,当停止按钮按下时,会发出声音警报。D13为led信号灯,无实际的功能。A5(scl),A4(sda)两
端口为IIC端口,用于连接LCD602,显示当前的移动速度和工作模式。A3为空,未连接任何设备。A2为电位器,用于设定当前
的走刀速度因子,生成走刀的脉冲频率。A1,A0为预留端口,为将来连接的摇杆预留。
=============================================================================================================*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <TimerOne.h>

/*-----------============变量定义==========-------------*/

//针脚定义
const int pul_pin_x = 2;//X轴脉冲驱动口
const int pul_pin_y = 3;//脉冲驱动口
const int dir_pin = 4;//方向控制
const int ena_pin = 5;//释放电机
const int key_pin_stop = 6;//紧急停止按钮
const int key_pin_auto = 7;//手动-自动切换开关

//开关方向摇杆,4方向。模拟摇杆使用时,可以不用此4个开关
const int key_pin_x1 = 8;//x轴方向正向
const int key_pin_x2 = 9;//x轴方向反向
const int key_pin_y1 = 10;//y轴方向正向
const int key_pin_y2 = 11;//y轴方向反向

const int buzzer = 12;//蜂鸣器
const int led_pin = 13;//执行状态

int hz = -1;//脉冲频率
int sp = 0;//转速调整的数值
float f = 0;//每秒进给量
boolean output =LOW;//脉冲方波状态
boolean dir = LOW;//方向状态
boolean ena = HIGH;//释放电机锁死状态
boolean auto_old = LOW ;//手自动状态
boolean stop_old = LOW;//急停状态
boolean xx = LOW;//摇杆x轴停止状态
boolean yy = LOW;//摇杆y轴停滞状态
boolean x1,x2,y1,y2 = LOW;
long unsigned beep = 0;//蜂鸣器
int az = 0;//摇杆输出频率

LiquidCrystal_I2C lcd(0x27,16,2);//定义1602LCD,地址为0x27

/*---------=============函数定义==============----------*/

void wave_x()  //摇杆x轴脉冲输出程序
{
  if(( xx == LOW)||(stop_old == HIGH))
  {
     Timer1.detachInterrupt();
     Timer1.stop();
     stop_old = HIGH;
     output = LOW;
     digitalWrite(pul_pin_x,output);      //**********  test code  ***********
     digitalWrite(led_pin,output);
  }
  else
  {
    output = !output;
    digitalWrite(pul_pin_x,output);        //***********  test code ************
    digitalWrite(led_pin,output);
  }  
}

void wave_y()  //摇杆y轴脉冲输出程序
{
  if(( yy == LOW)||(stop_old == HIGH))
  {
     Timer1.detachInterrupt();
     Timer1.stop();
     stop_old = HIGH;
     output = LOW;
     digitalWrite(pul_pin_y,output);
  }
  else
  {
    output = !output;
    digitalWrite(pul_pin_y,output);
  }  
}

void wave_x1() //驱动 x1 x2 轴的脉冲发生函数
{
    if(digitalRead(key_pin_auto)==HIGH)
   {
     if(stop_old==HIGH)
     {
      wave_stop();
     }
     else
     {
       output = !output;
      digitalWrite(pul_pin_x,output);
      digitalWrite(led_pin,output);           //***********  test code  **************
     }
   }
   else
   {
    if((x1==LOW) && (x2==LOW))
    {
     wave_stop();
    }
    else  
    {
      output = !output;
      digitalWrite(pul_pin_x,output);
      digitalWrite(led_pin,output);           //***********  test code  **************
    }
    }
}

void wave_y1()  //驱动y1轴的脉冲发生函数
{
    if(digitalRead(key_pin_auto)==HIGH)
   {
     if(stop_old==HIGH)
     {
      wave_stop();
     }
     else
     {
       output = !output;
      digitalWrite(pul_pin_y,output);
      digitalWrite(led_pin,output);           //***********  test code  **************
     }
   }
   else
   {
    if((y1==LOW) && (y2==LOW))
    {
      wave_stop();
    }
    else  
    {
      output = !output;
      digitalWrite(pul_pin_y,output);
      digitalWrite(led_pin,output);           //***********  test code  **************
    }
    }
}

void wave_stop() //脉冲停止程序
{
    Timer1.stop();
    output = LOW;
    digitalWrite(pul_pin_x,output);
    digitalWrite(pul_pin_y,output);
    digitalWrite(led_pin,output);
    stop_show();
    stop_old = HIGH;
}



void lcd_show()  //1602刷新显示函数
{
  //显示每秒进给量,单位是mm,精度是0.01mm
  f = (hz / 10 )*0.01;
  lcd.clear();
  lcd.print("f=");
  lcd.print(f); //显示输出 每秒进给速度
  lcd.setCursor(10,0);
  //测试手自动按钮状态,高电平显示“自动”,低电平显示“手动”
  if(digitalRead(key_pin_auto)==HIGH)  
  {
    lcd.print("AUTO");
  }
  else
  {
    lcd.print("MANUAL");
  }  
  delay(10);
}

void stop_show() //当停止按钮被按下,显示函数用来在屏幕显示停止警示同事发出蜂鸣器的声音报警信号
{
  lcd.setCursor(4,1);  //设置在第二行显示
  lcd.print("STOP!!");  
  for(int k = 0; k < 2; k++)
  {
    for(int j = 0; j < 2; j++)
    {
      for(int i = 0; i < 60; i++)
      {
        digitalWrite(buzzer,HIGH);
        delay(1);
        digitalWrite(buzzer,LOW);
        delay(1);
      }
    delay(20);
    }
    delay(90);
  }
  lcd_show();
}


/*-----------============参数设置=============-------------*/

void setup()
{
  /*输出端口配置*/
  pinMode(pul_pin_x,OUTPUT);
  pinMode(pul_pin_y,OUTPUT);
  pinMode(dir_pin,OUTPUT);
  pinMode(ena_pin,OUTPUT);
  pinMode(buzzer,OUTPUT);
  pinMode(led_pin,OUTPUT);
  
  /*输入端口配置 */
  pinMode(key_pin_stop,INPUT);
  pinMode(key_pin_auto,INPUT);  
  pinMode(key_pin_x1,INPUT);
  pinMode(key_pin_x2,INPUT);
  pinMode(key_pin_y1,INPUT);
  pinMode(key_pin_y2,INPUT);
  
  /*端口初始化 */
  digitalWrite(pul_pin_x,LOW);
  digitalWrite(pul_pin_y,LOW);
  digitalWrite(dir_pin,LOW);
  digitalWrite(ena_pin,HIGH);
  digitalWrite(buzzer,LOW);
  digitalWrite(led_pin,LOW);
  
  lcd.init();//1602液晶屏初始化
  lcd.backlight();//打开背光灯
  
  Timer1.stop();  
}

/*-----------=============主函数循环体=============-----------*/

void loop()
{
  if(digitalRead(key_pin_stop)==HIGH)  //急停按钮处理
  {
    wave_stop();
  }
  sp = 10;
  //sp = analogRead(A2);      
  //sp = map(sp,0,1024,0,20000);   //从电位器获取参数后,生成频率
  if (((hz > (sp + 45))||(hz < (sp -45)))||(digitalRead(key_pin_auto) != auto_old))  //抖动不造成显示变化,自动走刀状态改变也出发显示变化
  {
    hz = sp;
    auto_old = digitalRead(key_pin_auto);
    lcd_show();
  }
  //判断4个方向的按键那个被按下

    x1 = digitalRead(key_pin_x1);
    x2 = digitalRead(key_pin_x2);
    y1 = digitalRead(key_pin_y1);
    y2 = digitalRead(key_pin_y2);


   
    if (x1 == HIGH)  //x轴正方向:当方向按钮被按下的时候首先解除停止锁定,然后打开定时器,开始执行中断程序
      {
        stop_old = LOW;
        digitalWrite(dir_pin,HIGH);   
        Timer1.initialize(1000000/10);   
        Timer1.attachInterrupt(wave_x1);
      }      
    if (x2 == HIGH)  //x轴负方向:当方向按钮被按下的时候首先解除停止锁定,然后打开定时器,开始执行中断程序
      {
        stop_old = LOW;
        digitalWrite(dir_pin,LOW);   
        Timer1.initialize(1000000/10);     
        Timer1.attachInterrupt(wave_x1);
      }
    if(y1 == HIGH)  //y轴正方向:当方向按钮被按下的时候首先解除停止锁定,然后打开定时器,开始执行中断程序
      {
        stop_old = LOW;
        digitalWrite(dir_pin,HIGH);
        Timer1.initialize(1000000/20);        
        Timer1.attachInterrupt(wave_y1);
      }
    if( y2 == HIGH)  //y轴负方向:当方向按钮被按下的时候首先解除停止锁定,然后打开定时器,开始执行中断程序
      {
        stop_old = LOW;
        digitalWrite(dir_pin,LOW);
        Timer1.initialize(1000000/20);
        Timer1.attachInterrupt(wave_y1);
      }
   //**************  微动摇杆控制程序  ****************
/*     if (analogRead(0) > 524)  //x轴判断程序  0~1023取值之间,分为0-500,500-524,252-1023
      {                              //525 - 1023为x正取向
        xx = HIGH;
        stop_old = LOW;
        digitalWrite(dir_pin,HIGH);
        az = analogRead(A0);
        az = map(az,525,1023,0,100);
        Timer1.initialize(1000000/az);
        Timer1.attachInterrupt(wave_x);
      }
      else if(analogRead(0) < 500)    //0 - 499 为x负取向
      {
        xx = HIGH;
        stop_old = LOW;
        digitalWrite(dir_pin,LOW);
        az = analogRead(A0);
        az = map(az,0,499,100,0);
        Timer1.initialize(1000000/az);
        Timer1.attachInterrupt(wave_x);
      }
      else                            //500 - 524 为停止
      {
        xx = LOW;        
      }
      
       if (analogRead(1) > 524)  //y轴判断程序  0~1023取值之间,分为0-500,500-524,252-1023
      {                               //525 - 1023为y正取向
        yy = HIGH;
        stop_old = LOW;
        digitalWrite(dir_pin,HIGH);
        az = analogRead(A0);
        az = map(az,525,1023,0,100);
        Timer1.initialize(1000000/az);
        Timer1.attachInterrupt(wave_y);
      }
      else if(analogRead(0) < 500)    //0 - 499 为y负取向
      {
        yy = HIGH;
        stop_old = LOW;
        digitalWrite(dir_pin,LOW);
        az = analogRead(A0);
        az = map(az,0,499,100,0);
        Timer1.initialize(1000000/az);
        Timer1.attachInterrupt(wave_y);
      }
      else                            //500 - 524 为停止
      {
        yy = LOW;        
      }
      */
}

回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-6-24 21:52:56 | 显示全部楼层
期待你的arduino识别g码
回复 支持 反对

使用道具 举报

发表于 2013-6-24 21:59:19 | 显示全部楼层
万马奔腾 发表于 2013-6-24 21:52
期待你的arduino识别g码

不是有现成的gcode_interpreter。这个就可以通过串口输入G代码来工作的。我本来也是想做的,后来发现有点难度,而且资料很少,加上人家有现成的东西,我就放弃自己搞了。好的运动控制卡几千上万的,何必自己搞一个高不成低不就的东西出来呢。能实现简单控制就可以了,有特殊需要再搞搞。
回复 支持 反对

使用道具 举报

发表于 2013-6-24 21:59:52 | 显示全部楼层
万马奔腾 发表于 2013-6-24 21:52
期待你的arduino识别g码

http://www.geek-workshop.com/thread-4722-1-1.html 看看这个篇帖子,应该对你有帮助的。虽然写的也不多。
回复 支持 反对

使用道具 举报

发表于 2013-8-13 17:53:46 | 显示全部楼层
mark 一下,两轴电机控制
回复 支持 反对

使用道具 举报

发表于 2013-11-9 21:16:30 | 显示全部楼层
万马奔腾 发表于 2013-6-24 21:52
期待你的arduino识别g码

已经能识别G代码了啊 度娘一下gabl吧
回复 支持 反对

使用道具 举报

发表于 2013-11-9 21:18:43 | 显示全部楼层
rick_hou 发表于 2013-6-18 10:47
前后折腾了大约有半个月,现在已经用上了,准备再做些调整。

我玩arduino的目的也是控制机械加工,但是我想控制等离子切割,毕竟成品太贵了啊
回复 支持 反对

使用道具 举报

发表于 2013-11-10 22:11:39 | 显示全部楼层
wsy0315 发表于 2013-11-9 21:18
我玩arduino的目的也是控制机械加工,但是我想控制等离子切割,毕竟成品太贵了啊

这个想法不错,不过我觉得要是搞Gcode的话还是用专业的板子比较好,arduino更适合做些简单的控制。
回复 支持 反对

使用道具 举报

发表于 2014-4-8 21:55:08 | 显示全部楼层
存档备用~~~~~
回复 支持 反对

使用道具 举报

发表于 2014-4-19 20:33:20 | 显示全部楼层
我觉得要是搞Gcode的话还是用专业的板子比较好,arduino更适合做些简单的控制。
回复 支持 反对

使用道具 举报

发表于 2014-6-6 20:33:25 | 显示全部楼层
脉冲产生函数没看懂~~~~
回复 支持 反对

使用道具 举报

发表于 2014-8-3 13:23:31 | 显示全部楼层
谢谢楼主共享资料,请问楼主有没有什么资料可以把xy变成联动的?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-14 03:22 , Processed in 0.042415 second(s), 25 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表