机器谱

R312】三轴XYZ平台

作者:机器谱

图文展示3264(1)

图文展示3264(1)

副标题

生成gcode文件
绘制空心字
画图

生成gcode文件

1. 生成gcode坐标文件

      gcode文件中保存的是需要绘制图形的路径信息,这里我们采用开源矢量图形编辑软件 Inkscape并通过Unicorn G-Code插件来生成 gcode坐标文件。

      将软件资料包\Inkscape.rar 压缩文件解压到电脑上任意磁盘,软件内已安装 Unicorn G-Code插件,解压后打开inkscape.exe来启动软件。软件启动后我们便可以进行以下步骤:

① 生成文字的 gcode文件

       三轴XYZ平台绘图仪的绘图区域面积设置为80*80mm,因此就像绘画一样,我们需要先在Inkscape软件内设置一张画布,如下图所示:

点击文件,打开文档属性,对文档尺寸大小进行设置,如下图所示:

设置完成后,软件主界面将会出现一个矩形区域,如下图所示:

      此时我们可以通过键盘上的 + 或者 - 按键进行文档的缩放,将文档尺寸缩放到合适大小后,我们便可以在矩形区域内编辑文字。这里我们以编辑文字“机器时代”为例,如下图操作:

      此时已经完成了文字的编辑工作,然后我们将对文字位置进行调整以及将文字转化为路径并通过Unicorn G-Code插件来生成文字的 gcode文件,如下图所示:

      此时我们已经将文字对象转换为了路径,图片中的每个节点即为gcode文件中存储的坐标,然后我们点击文件-另存为,选择gcode文件类型,即可生成文字的 gcode文件。如下图所示:

② 生成图片的 gcode文件

      通过上面生成文字的 gcode文件练习,我们对 Inkscape软件的操作也有了一定了解,现在我们来生成一张图片的 gcode文件。首先我们需要找一张黑白比较分明的图片(jpg、png等静态格式图片),然后打开图片,选择嵌入,如下图所示:

      图片打开后,可以点击选择变换对象按钮对图片大小进行调整,然后按上述步骤设置文档尺寸大小为 80*80mm,然后进行图片路径的转换,如下图所示:

1

图2

图3

图4

图5

图6

      通过上面的练习,我们已经掌握了如何生成文字以及图片的 gcode文件,后续我们将通过上位机发送 gcode文件给三轴XYZ平台绘图仪进行图形绘制。

2. 资料清单

序号

内容
1

软件资料包


文件下载
【整体打包】-【R312】三轴XYZ平台-生成gcode文件-资料附件.zip
206.62MB下载35次下载
上一页 1 下一页

绘制空心字

1. 功能说明

     本文示例将实现R312三轴XYZ平台绘制“机器时代”空心字的功能。

2. 电子硬件

      在这个示例中,采用了以下硬件,请大家参考:

主控板

Basra主控板(兼容Arduino Uno)

扩展板

Bigfish2.1扩展板

SH-ST步进电机扩展板
电池11.1V动力电池
传感器触碰传感器

其它

笔架×1(自制,可根据文末资料提供的3D文件打印)


/*------------------------------------------------------------------------------------

  版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

           Distributed under MIT license.See file LICENSE for detail or copy at

           https://opensource.org/licenses/MIT

           by 机器谱 2023-03-30 https://www.robotway.com/

  ------------------------------*/

#define EN        8       //步进电机使能端,低电平有效

#define X_DIR     5       //X轴 步进电机方向控制

#define Y_DIR     6       //y轴 步进电机方向控制

#define Z_DIR     7       //z轴 步进电机方向控制

#define X_STP     2       //x轴 步进控制

#define Y_STP     3       //y轴 步进控制

#define Z_STP     4       //z轴 步进控制

boolean DIR;              //boolean类型变量 DIR,控制步进电机方向,true为正向,false为反向,根据接线做调整

int stepper_pulse = 40;   //定义步进电机脉冲发送的时间间隔


#define LINE_BUFFER_LENGTH 512  


const int SENSOR_X = 14;   //定义X,Y,Z轴复位传感器引脚

const int SENSOR_Y = 18;

const int SENSOR_Z = 16;


const int stepsPerRevolution = 3200;   //定义步进电机每圈转动的步数,细分为16


float LEAD = 8;   //定义丝杠导程,即步进电机转动一圈,丝杠前进8mm


struct point {   

  float x;

  float y;

  float z;

};


// Current position of plothead

struct point actuatorPos;


float Xmin = -40;   //定义绘图区域范围

float Xmax = 40;

float Ymin = -40;

float Ymax = 40;


float Xpos = 0;

float Ypos = 0;


boolean verbose = false;


void setup()

{

  Serial.begin(9600);      //开启串口通信,波特率为9600

  pinMode(X_DIR, OUTPUT); pinMode(X_STP, OUTPUT);

  pinMode(Y_DIR, OUTPUT); pinMode(Y_STP, OUTPUT);

  pinMode(Z_DIR, OUTPUT); pinMode(Z_STP, OUTPUT);

  pinMode(EN, OUTPUT);

  digitalWrite(EN, LOW);  

  resetStepper();

  digitalWrite(EN, HIGH);

  delay(1000);

}


void loop()

{           

  delay(200);

  char line[ LINE_BUFFER_LENGTH ];

  char c;

  int lineIndex;

  bool lineIsComment, lineSemiColon;


  lineIndex = 0;

  lineSemiColon = false;

  lineIsComment = false;


  while (1) {


    // 接受来自Grbl的串口数据

    while ( Serial.available()>0 ) {

      c = Serial.read();

      if (( c == '\n') || (c == '\r') ) {             // End of line reached

        if ( lineIndex > 0 ) {                        // Line is complete. Then execute!

          line[ lineIndex ] = '\0';                   // Terminate string

          if (verbose) {

            Serial.print( "Received : ");

            Serial.println( line );

          }

          processIncomingLine( line, lineIndex );

          lineIndex = 0;

        }

        else {

          // Empty or comment line. Skip block.

        }

        lineIsComment = false;

        lineSemiColon = false;

        Serial.println("ok");   

      }

      else {

        if ( (lineIsComment) || (lineSemiColon) ) {   // Throw away all comment characters

          if ( c == ')' )   lineIsComment = false;     // End of comment. Resume line.

        }

        else {

          if ( c <= ' ' ) {                           // Throw away whitepace and control characters

          }

          else if ( c == '/' ) {                    // Block delete not supported. Ignore character.

          }

          else if ( c == '(' ) {                    // Enable comments flag and ignore all characters until ')' or EOL.

            lineIsComment = true;

          }

          else if ( c == ';' ) {

            lineSemiColon = true;

          }

          else if ( lineIndex >= LINE_BUFFER_LENGTH-1 ) {

            Serial.println( "ERROR - lineBuffer overflow" );

            lineIsComment = false;

            lineSemiColon = false;

          }

          else if ( c >= 'a' && c <= 'z' ) {        // Upcase lowercase

            line[ lineIndex++ ] = c-'a'+'A';

          }

          else {

            line[ lineIndex++ ] = c;

          }

        }

      }

    }

  }

}


void processIncomingLine( char* line, int charNB ) {

  int currentIndex = 0;

  char buffer[ 64 ];          // Hope that 64 is enough for 1 parameter

  stepper_pulse = 40;         //设置Z轴抬笔落笔时步进电机脉冲间隔

  struct point newPos;


  newPos.x = 0.0;

  newPos.y = 0.0;


  //   Needs to interpret

  //   G1 for moving

  //   G4 P300 (wait 150ms)

  //   G1 X60 Y30

  //   G1 X30 Y50

  //   M300 S30 (pen down)

  //   M300 S50 (pen up)

  //   Discard anything with a (

  //   Discard any other command!


  while( currentIndex < charNB ) {

    switch ( line[ currentIndex++ ] ) {           // Select command, if any

    case 'U':

      step(Z_DIR, Z_STP, 2000);

      break;

    case 'D':

      step(Z_DIR, Z_STP, -2000);

      break;

    case 'G':

      buffer[0] = line[ currentIndex++ ];          // /!\ Dirty - Only works with 2 digit commands

      //      buffer[1] = line[ currentIndex++ ];

      //      buffer[2] = '\0';

      buffer[1] = '\0';


      switch ( atoi( buffer ) ){                   // Select G command

      case 0:                                      // G00 & G01 - Movement or fast movement. Same here

      case 1:

        // /!\ Dirty - Suppose that X is before Y

        char* indexX = strchr( line+currentIndex, 'X' );    // Get X/Y position in the string (if any)

        char* indexY = strchr( line+currentIndex, 'Y' );

        if ( indexY <= 0 ) {

          newPos.x = atof( indexX + 1);

          newPos.y = actuatorPos.y;

        }

        else if ( indexX <= 0 ) {

          newPos.y = atof( indexY + 1);

          newPos.x = actuatorPos.x;

        }

        else {

          newPos.y = atof( indexY + 1);

          indexY = '\0';

          newPos.x = atof( indexX + 1);

        }

        drawLine(newPos.x, newPos.y );

        //        Serial.println("ok");

        actuatorPos.x = newPos.x;

        actuatorPos.y = newPos.y;

        break;

      }

      break;

    case 'M':

      buffer[0] = line[ currentIndex++ ];     // /!\ Dirty - Only works with 3 digit commands

      buffer[1] = line[ currentIndex++ ];

      buffer[2] = line[ currentIndex++ ];

      buffer[3] = '\0';

      switch ( atoi( buffer ) ){

      case 300:

        {

          char* indexS = strchr( line+currentIndex, 'S' );

          float Spos = atof( indexS + 1);

          //          Serial.println("ok");

          if (Spos == 30) {

            step(Z_DIR, Z_STP, -2000);

          }

          if (Spos == 50) {

            step(Z_DIR, Z_STP, 2000);

          }

          break;

        }

      case 114:                                      // M114 - Repport position

        Serial.print( "Absolute position : X = " );

        Serial.print( actuatorPos.x );

        Serial.print( "   -   Y = " );

        Serial.println( actuatorPos.y );

        break;

      default:

        Serial.print( "Command not recognized : M");

        Serial.println( buffer );

      }

    }

  }

 

}


//直线插补函数,参数为点坐标值

void drawLine(float x1, float y1)

{

  int dx, dy, n, k, i, f, stepInc;

  stepper_pulse = 150;              //设置步进电机写字时脉冲间隔

 

  if (x1 >= Xmax) {

    x1 = Xmax;

  }

  if (x1 <= Xmin) {

    x1 = Xmin;

  }

  if (y1 >= Ymax) {

    y1 = Ymax;

  }

  if (y1 <= Ymin) {

    y1 = Ymin;

  }

 

  x1 = (int)(x1/LEAD*stepsPerRevolution);

  y1 = (int)(y1/LEAD*stepsPerRevolution);

  float x0 = Xpos;

  float y0 = Ypos;

 

  //Serial.println(Xpos);

  //Serial.println(Ypos);

 

  dx = abs(x1-x0);

  dy = abs(y1-y0);

  n = abs(dx+dy);

 

  if(dx==0||dy==0)

  {

    stepInc = 1;

  }

  else

  {

    stepInc = 10;

  }


  if(x1 >= x0)

  {

    k = y1 >= y0 ? 1:4;

  }

  else

  {

    k = y1 >= y0 ? 2:3;

  }

 

  for(i=0,f=0;i<n;i+=stepInc)

  {

    if(f>=0)

    {

      switch(k)

      {

         case 1:

         step(X_DIR, X_STP, stepInc);

         f = f - dy;

         //Serial.println("+x");

         break;

         case 2:

         step(X_DIR, X_STP, -stepInc);

         f = f - dy;

         //Serial.println("-x");

         break;

         case 3:

         step(X_DIR, X_STP, -stepInc);

         f = f - dy;

         //Serial.println("-x");

         break;

         case 4:

         step(X_DIR, X_STP, stepInc);

         f = f - dy;

         //Serial.println("+x");

         break;

         default:break;

      }

    }

    else

    {

      switch(k)

      {

        case 1:

        step(Y_DIR, Y_STP, stepInc);

        f = f + dx;

        //Serial.println("+y");

        break;

        case 2:

        step(Y_DIR, Y_STP, stepInc);

        f = f + dx;

        //Serial.println("+y");

        break;

        case 3:

        step(Y_DIR, Y_STP, -stepInc);

        f = f + dx;

        //Serial.println("-y");

        break;

        case 4:

        step(Y_DIR, Y_STP, -stepInc);

        f = f +dx;

        //Serial.println("-y");

        break;

        default:break;

      }

    }

  }

  Xpos = x1;

  Ypos = y1;

}


/*

//函数:step    功能:控制步进电机方向,步数。

//参数:dirPin对应步进电机的DIR引脚,stepperPin 对应步进电机的step引脚, steps 步进的步数

//无返回值

*/

void step(byte dirPin, byte stepperPin, int steps)

{

  digitalWrite(EN, LOW);

  boolean DIR = steps>0 ? true : false;  

  digitalWrite(dirPin,DIR);

  for(int i=0;i<abs(steps); i++)

  {

    digitalWrite(stepperPin, HIGH);

    delayMicroseconds(stepper_pulse);

    digitalWrite(stepperPin, LOW);

    delayMicroseconds(stepper_pulse);

  }

  digitalWrite(EN, HIGH);

}


//步进电机复位函数

void resetStepper()

{

    stepper_pulse = 40; //设置步进电机复位脉冲间隔

   

    while(digitalRead(SENSOR_Z))

        step(Z_DIR,Z_STP,10);

    step(Z_DIR,Z_STP,-15);

while(digitalRead(SENSOR_X))

        step(X_DIR,X_STP,-10);

    step(X_DIR,X_STP,15);

while(digitalRead(SENSOR_Y))

    step(Y_DIR,Y_STP,10);

    step(Y_DIR,Y_STP,-15);


    //复位笔至平台中间位置,步数根据中间位置距离复位传感器的距离计算

    step(X_DIR, X_STP, 28000);

    step(Y_DIR, Y_STP, -16000);

    step(Z_DIR, Z_STP, -30000);

}

3. 功能实现

      在这里我们采用了一种算法,该算法的思路是:先建立一个平面坐标系,将我们所需要画的图形放置在该坐标系中,这样就可以确定该图形每个顶点的坐标,两个相邻的顶点之间确定一条直线,直线上各点坐标通过插补计算得到,然后画笔依次沿着这些坐标进行移动,完成绘制。所以在这个过程中,我们需要知道如何建立一个图形的坐标系,以及什么是插补计算。插补计算方法可参考 R311】双轴XY平台-绘制斜向多边形

建立坐标系:

     三轴XYZ平台绘图仪,即通过X, Y, Z三轴的步进电机协调控制绘图笔来进行图形的绘制。通过上位机(PC)来发送gcode代码;下位机(三轴XYZ平台绘图仪)通过对接收到的gcode坐标代码进行解析,并通过插补算法来控制各个轴的步进电机进行图形绘制。

3.1硬件连接

    ① 各轴步进电机与SH-ST步进电机扩展板的接线顺序如下(从上至下):

         X:红蓝黑绿

         Y:红蓝黑绿

         Z:黑绿红蓝

② 各个轴的限位传感器(触碰)与Bigfish扩展板的接线如下:

    X:A0

    Y:A4

    Z:A2

3.2 示例程序

编程环境:Arduino 1.8.19

      将参考例程代码(_4_smile.ino)下载到主控板中,烧录完成后打开电源,三轴XYZ平台绘图仪各轴步进电机将进行复位,复位完成后,绘图笔将到达绘图区域中心,本实验中三轴XYZ平台绘图仪绘图面积为80*80mm。

3.3 图形绘制

      接下来我们将通过上位机的processing软件发送生成文字“机器时代”的 gcode文件给三轴XYZ平台绘图仪进行图形绘制。

      首先将 软件资料包\processing-2.0b8.zip 文件解压到电脑上任意磁盘,然后打开processing.exe来启动 Processing 软件,之后按下图所示步骤进行操作:

      此时打开绘图仪电源开关,在英文输入法状态下按键盘P键,选择端口号,等待三轴XYZ平台绘图仪复位完毕,进入接收上位机指令状态;然后英文输入法状态下按键盘G键,选择之前生成的 gcode文件,点击确定,开始发送gcode文件代码,三轴XYZ平台绘图仪开始绘图;三轴XYZ平台绘图仪在绘图过程中,可以按X键来停止发送gcode文件代码。

注意事项:

      ① 关于绘图笔的安装,可以让绘图仪进入工作状态后关闭电源,此时安装绘图笔使其与纸面相接即可。

      ② 程序中步进电机使用的细分数为16细分,无细分时200步/圈,16细分即 3200步/圈。

      ③ 生成gcode坐标文件后,使用windows的笔记本或者Notepad++软件打开gcode文件,然后删除第一行和第二行,如下图所示:

4. 资料清单

序号

内容
1

【R312】-绘制空心字-例程源代码

2

【R312】-绘制空心字-样机3D文件

3
软件资料包


本实验将基于三轴XYZ平台利用processing软件处理gcode文件后,进行绘制文字“机器时代”

文件下载
【整体打包】-【R312】三轴XYZ平台-绘制空心字-资料附件.zip
242.59MB下载5次下载
上一页 1 下一页

画图

1. 功能描述

本文示例将实现R312a样机三轴XYZ平台画图的功能。

2. 结构说明

该机构是由三个X轴Y轴Z轴分布的丝杠平台组合而成。

3. 电子硬件

在这个示例中,我们采用了以下硬件,请大家参考:

主控板

Basra主控板(兼容Arduino Uno)

扩展板

Bigfish2.1扩展板

SH-ST扩展板

传感器

触碰传感器

电池

11.1v动力电池

其它

笔架×1(自制,可根据文末资料提供的3D文件打印)


电路连接:

① 各轴步进电机与SH-ST步进电机扩展板的接线顺序如下(从上至下):

      X:红蓝黑绿

      Y:红蓝黑绿

      Z:黑绿红蓝

② 各个轴的限位传感器(触碰)与Bigfish扩展板的接线如下:

      X:A0

      Y:A4

      Z:A2

4. 功能实现

      在这里我们采用了一种算法,该算法的思路是:先建立一个平面坐标系,将我们所需要画的图形放置在该坐标系中,这样就可以确定该图形每个顶点的坐标,两个相邻的顶点之间确定一条直线,直线上各点坐标通过插补计算得到,然后画笔依次沿着这些坐标进行移动,完成绘制。所以在这个过程中,我们需要知道如何建立一个图形的坐标系,以及什么是插补计算。

      插补计算方法可参考 R311】双轴XY平台-绘制斜向多边形

      建立坐标系的方法可参考 R312】三轴XYZ平台-绘制空心字

4.1示例程序

编程环境:Arduino 1.8.19

功能:实现三轴XYZ平台画图。

      下面提供一个参考程序(_4_smile1.ino),程序下载完成后打开电源,三轴绘图仪各轴步进电机将进行复位,复位完成后,绘图笔将到达绘图区域中心,绘图仪绘图面积为80*80mm。

/*------------------------------------------------------------------------------------

  版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

           Distributed under MIT license.See file LICENSE for detail or copy at

           https://opensource.org/licenses/MIT

           by 机器谱 2024-01-31 https://www.robotway.com/

  ------------------------------*/

#define EN        8       //步进电机使能端,低电平有效

#define X_DIR     5       //X轴 步进电机方向控制

#define Y_DIR     6       //y轴 步进电机方向控制

#define Z_DIR     7       //z轴 步进电机方向控制

#define X_STP     2       //x轴 步进控制

#define Y_STP     3       //y轴 步进控制

#define Z_STP     4       //z轴 步进控制

boolean DIR;              //boolean类型变量 DIR,控制步进电机方向,true为正向,false为反向,根据接线做调整

int stepper_pulse = 40;   //定义步进电机脉冲发送的时间间隔

#define LINE_BUFFER_LENGTH 512  

const int SENSOR_X = 14;   //定义X,Y,Z轴复位传感器引脚

const int SENSOR_Y = 18;

const int SENSOR_Z = 16;

const int stepsPerRevolution = 3200;   //定义步进电机每圈转动的步数,细分为16

float LEAD = 8;   //定义丝杠导程,即步进电机转动一圈,丝杠前进8mm

struct point {   

  float x;

  float y;

  float z;

};

// Current position of plothead

struct point actuatorPos;

float Xmin = -80;   //定义绘图区域范围

float Xmax = 80;

float Ymin = -80;

float Ymax = 80;

float Xpos = 0;

float Ypos = 0;

boolean verbose = false;

void setup()

{

  Serial.begin(9600);      //开启串口通信,波特率为9600

  pinMode(X_DIR, OUTPUT);

  pinMode(X_STP, OUTPUT);

  pinMode(Y_DIR, OUTPUT);

  pinMode(Y_STP, OUTPUT);

  pinMode(Z_DIR, OUTPUT);

  pinMode(Z_STP, OUTPUT);

  pinMode(EN, OUTPUT);

  digitalWrite(EN, LOW);  

  resetStepper();

  digitalWrite(EN, HIGH);

  delay(1000);

}

void loop()

{           

  delay(200);

  char line[ LINE_BUFFER_LENGTH ];

  char c;

  int lineIndex;

  bool lineIsComment, lineSemiColon;

  lineIndex = 0;

  lineSemiColon = false;

  lineIsComment = false;

  while (1) {

    // 接受来自Grbl的串口数据

    while ( Serial.available()>0 ) {

      c = Serial.read();

      if (( c == '\n') || (c == '\r') ) {             // End of line reached

        if ( lineIndex > 0 ) {                        // Line is complete. Then execute!

          line[ lineIndex ] = '\0';                   // Terminate string

          if (verbose) {

            Serial.print( "Received : ");

            Serial.println( line );

          }

          processIncomingLine( line, lineIndex );

          lineIndex = 0;

        }

        else {

          // Empty or comment line. Skip block.

        }

        lineIsComment = false;

        lineSemiColon = false;

        Serial.println("ok");   

      }

      else {

        if ( (lineIsComment) || (lineSemiColon) ) {   // Throw away all comment characters

          if ( c == ')' )   lineIsComment = false;     // End of comment. Resume line.

        }

        else {

          if ( c <= ' ' ) {                           // Throw away whitepace and control characters

          }

          else if ( c == '/' ) {                    // Block delete not supported. Ignore character.

          }

          else if ( c == '(' ) {                    // Enable comments flag and ignore all characters until ')' or EOL.

            lineIsComment = true;

          }

          else if ( c == ';' ) {

            lineSemiColon = true;

          }

          else if ( lineIndex >= LINE_BUFFER_LENGTH-1 ) {

            Serial.println( "ERROR - lineBuffer overflow" );

            lineIsComment = false;

            lineSemiColon = false;

          }

          else if ( c >= 'a' && c <= 'z' ) {        // Upcase lowercase

            line[ lineIndex++ ] = c-'a'+'A';

          }

          else {

            line[ lineIndex++ ] = c;

          }

        }

      }

    }

  }

}

void processIncomingLine( char* line, int charNB ) {

  int currentIndex = 0;

  char buffer[ 64 ];          // Hope that 64 is enough for 1 parameter

  stepper_pulse = 40;         //设置Z轴抬笔落笔时步进电机脉冲间隔

  struct point newPos;

  newPos.x = 0.0;

  newPos.y = 0.0;

  //   Needs to interpret

  //   G1 for moving

  //   G4 P300 (wait 150ms)

  //   G1 X60 Y30

  //   G1 X30 Y50

  //   M300 S30 (pen down)

  //   M300 S50 (pen up)

  //   Discard anything with a (

  //   Discard any other command!

  while( currentIndex < charNB ) {

    switch ( line[ currentIndex++ ] ) {           // Select command, if any

    case 'U':

      step(Z_DIR, Z_STP, 2000);

      break;

    case 'D':

      step(Z_DIR, Z_STP, -2000);

      break;

    case 'G':

      buffer[0] = line[ currentIndex++ ];          // /!\ Dirty - Only works with 2 digit commands

      //      buffer[1] = line[ currentIndex++ ];

      //      buffer[2] = '\0';

      buffer[1] = '\0';

      switch ( atoi( buffer ) ){                   // Select G command

      case 0:                                      // G00 & G01 - Movement or fast movement. Same here

      case 1:

        // /!\ Dirty - Suppose that X is before Y

        char* indexX = strchr( line+currentIndex, 'X' );    // Get X/Y position in the string (if any)

        char* indexY = strchr( line+currentIndex, 'Y' );

        if ( indexY <= 0 ) {

          newPos.x = atof( indexX + 1);

          newPos.y = actuatorPos.y;

        }

        else if ( indexX <= 0 ) {

          newPos.y = atof( indexY + 1);

          newPos.x = actuatorPos.x;

        }

        else {

          newPos.y = atof( indexY + 1);

          indexY = '\0';

          newPos.x = atof( indexX + 1);

        }

        drawLine(newPos.x, newPos.y );

        //        Serial.println("ok");

        actuatorPos.x = newPos.x;

        actuatorPos.y = newPos.y;

        break;

      }

      break;

    case 'M':

      buffer[0] = line[ currentIndex++ ];     // /!\ Dirty - Only works with 3 digit commands

      buffer[1] = line[ currentIndex++ ];

      buffer[2] = line[ currentIndex++ ];

      buffer[3] = '\0';

      switch ( atoi( buffer ) ){

      case 300:

        {

          char* indexS = strchr( line+currentIndex, 'S' );

          float Spos = atof( indexS + 1);

          //          Serial.println("ok");

          if (Spos == 30) {

            step(Z_DIR, Z_STP, 1600);

          }

          if (Spos == 50) {

            step(Z_DIR, Z_STP, -1600);

          }

          break;

        }

      case 114:                                      // M114 - Repport position

        Serial.print( "Absolute position : X = " );

        Serial.print( actuatorPos.x );

        Serial.print( "   -   Y = " );

        Serial.println( actuatorPos.y );

        break;

      default:

        Serial.print( "Command not recognized : M");

        Serial.println( buffer );

      }

    }

  }

}

//直线插补函数,参数为点坐标值

void drawLine(float x1, float y1)

{

  int dx, dy, n, k, i, f, stepInc;

  stepper_pulse = 150;              //设置步进电机写字时脉冲间隔

  if (x1 >= Xmax) {

    x1 = Xmax;

  }

  if (x1 <= Xmin) {

    x1 = Xmin;

  }

  if (y1 >= Ymax) {

    y1 = Ymax;

  }

  if (y1 <= Ymin) {

    y1 = Ymin;

  }

  x1 = (int)(x1/LEAD*stepsPerRevolution);

  y1 = (int)(y1/LEAD*stepsPerRevolution);

  float x0 = Xpos;

  float y0 = Ypos;

  //Serial.println(Xpos);

  //Serial.println(Ypos);

  dx = abs(x1-x0);

  dy = abs(y1-y0);

  n = abs(dx+dy);

  if(dx==0||dy==0)

  {

    stepInc = 1;

  }

  else

  {

    stepInc = 10;

  }

  if(x1 >= x0)

  {

    k = y1 >= y0 ? 1:4;

  }

  else

  {

    k = y1 >= y0 ? 2:3;

  }

  for(i=0,f=0;i<n;i+=stepInc)

  {

    if(f>=0)

    {

      switch(k)

      {

      case 1:

        step(X_DIR, X_STP, stepInc);

        f = f - dy;

        //Serial.println("+x");

        break;

      case 2:

        step(X_DIR, X_STP, -stepInc);

        f = f - dy;

        //Serial.println("-x");

        break;

      case 3:

        step(X_DIR, X_STP, -stepInc);

        f = f - dy;

        //Serial.println("-x");

        break;

      case 4:

        step(X_DIR, X_STP, stepInc);

        f = f - dy;

        //Serial.println("+x");

        break;

      default:

        break;

      }

    }

    else

    {

      switch(k)

      {

      case 1:

        step(Y_DIR, Y_STP, stepInc);

        f = f + dx;

        //Serial.println("+y");

        break;

      case 2:

        step(Y_DIR, Y_STP, stepInc);

        f = f + dx;

        //Serial.println("+y");

        break;

      case 3:

        step(Y_DIR, Y_STP, -stepInc);

        f = f + dx;

        //Serial.println("-y");

        break;

      case 4:

        step(Y_DIR, Y_STP, -stepInc);

        f = f +dx;

        //Serial.println("-y");

        break;

      default:

        break;

      }

    }

  }

  Xpos = x1;

  Ypos = y1;

}

/*

//函数:step    功能:控制步进电机方向,步数。

//参数:dirPin对应步进电机的DIR引脚,stepperPin 对应步进电机的step引脚, steps 步进的步数

//无返回值

*/

void step(byte dirPin, byte stepperPin, long int steps)

{

  digitalWrite(EN, LOW);

  boolean DIR = steps>0 ? true : false;  

  digitalWrite(dirPin,DIR);

  for(int i=0;i<abs(steps); i++)

  {

    digitalWrite(stepperPin, HIGH);

    delayMicroseconds(stepper_pulse);

    digitalWrite(stepperPin, LOW);

    delayMicroseconds(stepper_pulse);

  }

  digitalWrite(EN, HIGH);

}

//步进电机复位函数

void resetStepper()

{

  stepper_pulse = 40; //设置步进电机复位脉冲间隔

  while(digitalRead(SENSOR_Z))

    step(Z_DIR,Z_STP,-10);

  step(Z_DIR,Z_STP,15);

  while(digitalRead(SENSOR_X))

    step(X_DIR,X_STP,-10);

  step(X_DIR,X_STP,15);

  while(digitalRead(SENSOR_Y))

    step(Y_DIR,Y_STP,10);

  step(Y_DIR,Y_STP,-15);

  //复位笔至平台中间位置,步数根据中间位置距离复位传感器的距离计算

  step(X_DIR, X_STP, 40000);

  step(Y_DIR, Y_STP, -45000);

  step(Z_DIR, Z_STP, 38000);

}


4.2 gcode坐标文件生成

       gcode坐标文件生成的方法可参考 R312】三轴XYZ平台-生成gcode文件

4.3图形绘制

       图形绘制的方法可参考R312】三轴XYZ平台-绘制空心字

5. 资料清单

序号

内容
1

  Basra相关原理图引脚图电路文件等

2

【R312】-画图-样机3D文件

3

  软件资料包


文件下载
样机方案-【R312】三轴XYZ平台-画图-资料附件.rar
211.72MB下载0次下载
上一页 1 下一页
© 2022 机器时代(北京)科技有限公司  版权所有
机器谱——机器人共享方案网站
学习  开发  设计  应用