chqiyi 发表于 2013-6-19 01:51:00

控制步进电机加工,这才是我学习ARDUINO的唯一原因
rick_hou大侠能指点详细一些吗?
谢谢

bh7jec 发表于 2013-6-20 12:29:19

我也在关注这个,希望能够详细讲讲,帖点代码出来

rick_hou 发表于 2013-6-23 23:00:58

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

rick_hou 发表于 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码

rick_hou 发表于 2013-6-24 21:59:19

万马奔腾 发表于 2013-6-24 21:52 static/image/common/back.gif
期待你的arduino识别g码

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

rick_hou 发表于 2013-6-24 21:59:52

万马奔腾 发表于 2013-6-24 21:52 static/image/common/back.gif
期待你的arduino识别g码

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

wwlzq5 发表于 2013-8-13 17:53:46

mark 一下,两轴电机控制

wsy0315 发表于 2013-11-9 21:16:30

万马奔腾 发表于 2013-6-24 21:52 static/image/common/back.gif
期待你的arduino识别g码

已经能识别G代码了啊 度娘一下gabl吧

wsy0315 发表于 2013-11-9 21:18:43

rick_hou 发表于 2013-6-18 10:47 static/image/common/back.gif
前后折腾了大约有半个月,现在已经用上了,准备再做些调整。

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

rick_hou 发表于 2013-11-10 22:11:39

wsy0315 发表于 2013-11-9 21:18 static/image/common/back.gif
我玩arduino的目的也是控制机械加工,但是我想控制等离子切割,毕竟成品太贵了啊

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

honyfox 发表于 2014-4-8 21:55:08

存档备用~~~~~

河山 发表于 2014-4-19 20:33:20

我觉得要是搞Gcode的话还是用专业的板子比较好,arduino更适合做些简单的控制。

maleficia 发表于 2014-6-6 20:33:25

脉冲产生函数没看懂~~~~

阴霾の微笑 发表于 2014-8-3 13:23:31

谢谢楼主共享资料,请问楼主有没有什么资料可以把xy变成联动的?
页: 1 [2] 3 4
查看完整版本: arduino产生脉冲控制工业用的步进电机?