A small CNC

Hi, this is my first post.

I made a small CNC using 2 arduino + 2 motor shield + 3 stepper motor. The drill is a dremel plus extension cord. The work flow is:
1)MecSoft FreeMill reads stl file and out put G-code text file
2)A C# program reads first line of G-code and send to Arduino board A
3)Arduino A reads G-code and tells motor shield A to move motor X and Y
4)Arduino A tells Arduino B to move motor Z through soft serial
5)Arduino A reports to C# program if it reaches destination
6)C# program reads the next line and whole steps repeat

I start with cutting soft materials then gradually switching to harder ones. I am still refining it but right now all the parts together are working well.

Some pictures are here http://makertober.blogspot.com/2010/02/arduino-cnc-mill.html

Very nice! Any chance you could share the code?

Will be glad to post the code after cleaning it up

Never mind cleaning too much, this is brilliant!

Joachim

Part 1

#include <WString.h>
#include <AFMotor.h>
#include <SoftwareSerial.h>

AF_Stepper motorx(48, 2);
AF_Stepper motory(48, 1);

#define rxPin 9
#define txPin 10
#define ledPin 13

SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

String inString = String(50); 
String units = String(2);  
String xstr = String(10);
String ystr = String(10);
String zstr = String(10);

float xstring;
float ystring;
float zstring;

float posx;
float posy;
float posz = min(posz, 0);

float targetx;
float targety;
float targetz;

float linex;
float liney;
float linez;

float DX;
float DY;
float DZ;

float dx;
float dy;
float dz;

float stepx = 341.759; // # of steps per mm
float stepy = 362.834;
float stepz = 121;

boolean command;
boolean zmark;
int type;
byte pinState = 0;
float scale = 1;
int zdirection = 1;

void setup() {
  Serial.begin(4800);
  motorx.setSpeed(60);
  motory.setSpeed(60);
  delay (1000);
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
  mySerial.begin(4800);
  command = false;
}

void AcquireXYZ(){
  if(Serial.available() > 0) {
 
   char inChar = Serial.read(); 
   
     if (inChar == '!'){   
       char firstChar = inString.charAt(0);
       
       if (firstChar == 'G'){ 
       GCodeParse();
       }
       
       else{
       }
       inString = 0;
     }
   else{
       inString.append(inChar); 
     }
  }
}

void GCodeParse(){
 
if (inString.startsWith("G0")){
        type = 0;
}
        
if (inString.startsWith("G1")){
        type = 1;
        if (inString.contains("X") && inString.contains("Y") && inString.contains("Z")){
        int xcharloc = inString.indexOf('X'); //find where the X code starts
        int ycharloc = inString.indexOf('Y'); //find where the Y code starts
        int zcharloc = inString.indexOf('Z'); //find where the Z code starts
       
        xcharloc = xcharloc + 1;
        ycharloc = ycharloc - 1;
        xstr = inString.substring(xcharloc, ycharloc);
        ycharloc = ycharloc + 1;
        
        ycharloc = ycharloc + 1;
        zcharloc = zcharloc - 1;
        ystr = inString.substring(ycharloc, zcharloc);
        zcharloc = zcharloc + 1;

        int zlast = inString.length();
        zcharloc = zcharloc + 1;
        zstr = inString.substring(zcharloc, zlast);
        zcharloc = zcharloc - 1;
     
        xstring = atof(xstr);
        ystring = atof(ystr);
        zstring = atof(zstr);

        targetx = xstring * scale;
        targety = ystring * scale;
        targetz = -1 * zstring * zdirection * scale;
        
        DX = targetx - posx;
        DY = targety - posy;
        DZ = targetz - posz;
        linex = posx;
        liney = posy;
        delay (1000);
        command = true;
        };  
        if (inString.contains("X") && inString.contains("Y") && !inString.contains("Z")){
        int xcharloc = inString.indexOf('X'); //find where the X code starts
        int ycharloc = inString.indexOf('Y'); //find where the Y code starts
              
        xcharloc = xcharloc + 1;// Code for finding what X is in the code
        ycharloc = ycharloc - 1;
        xstr = inString.substring(xcharloc, ycharloc);
        ycharloc = ycharloc + 1;
       
        int ylast = inString.length(); 
        ycharloc = ycharloc + 1;
        ystr = inString.substring(ycharloc, ylast);
        ycharloc = ycharloc - 1;

        xstring = atof(xstr); 
        ystring = atof(ystr); 
        
        targetx = xstring * scale;
        targety = ystring * scale;
        targetz = posz;//posz + DZ;
        
        DX = targetx - posx;
        DY = targety - posy;
        DZ = 0;
        linex = posx;
        liney = posy;
        delay (1000);
        command = true;
        };       
        if (inString.contains("X") && !inString.contains("Y") && inString.contains("Z")){
        int xcharloc = inString.indexOf('X'); 
        int zcharloc = inString.indexOf('Z'); 
       
        xcharloc = xcharloc + 1;
        zcharloc = zcharloc - 1;
        xstr = inString.substring(xcharloc, zcharloc);
        zcharloc = zcharloc + 1;
       
        int zlast = inString.length(); 
        zcharloc = zcharloc + 1;
        zstr = inString.substring(zcharloc, zlast);
        zcharloc = zcharloc - 1;

        xstring = atof(xstr);
        zstring = atof(zstr);

        targetx = xstring * scale;
        targety = posy;
        targetz = -1 * zstring * zdirection * scale;
        
        DX = targetx - posx;
        DY = 0;
        DZ = targetz - posz;
        linex = posx;
        liney = posy;
        delay (1000);
        command = true;
        };
        if (!inString.contains("X") && inString.contains("Y") && inString.contains("Z")){
        
        int ycharloc = inString.indexOf('Y');
        int zcharloc = inString.indexOf('Z');
       
        ycharloc = ycharloc + 1;
        zcharloc = zcharloc - 1;
        ystr = inString.substring(ycharloc, zcharloc);
        zcharloc = zcharloc + 1;

        int zlast = inString.length();
        zcharloc = zcharloc + 1;
        zstr = inString.substring(zcharloc, zlast);
        zcharloc = zcharloc - 1;

     
        ystring = atof(ystr);
        zstring = atof(zstr);

        targetx = posx;
        targety = ystring * scale;
        targetz = -1 * zstring * zdirection * scale;
        
        DX = 0;
        DY = targety - posy; 
        DZ = targetz - posz; 
        linex = posx;
        liney = posy;
        delay (1000);
        command = true;
        };      
        if (!inString.contains("X") && !inString.contains("Y") && inString.contains("Z")){
        
        
        int zcharloc = inString.indexOf('Z'); 
       
        int zlast = inString.length(); 
        zcharloc = zcharloc + 1;
        zstr = inString.substring(zcharloc, zlast);
        zcharloc = zcharloc - 1;
     
        zstring = atof(zstr);

        targetx = posx;
        targety = posy;
        targetz = -1 * zstring * zdirection * scale;
        
        DX = 0;
        DY = 0;
        DZ = targetz - posz;
        linex = posx;
        liney = posy;
        delay (1000);
        command = true;
        };
        if (!inString.contains("X") && inString.contains("Y") && !inString.contains("Z")){
        int ycharloc = inString.indexOf('Y');
        ycharloc = ycharloc + 1;
        int ylast = inString.length();
        ystr = inString.substring(ycharloc, ylast);
        ycharloc = ycharloc - 1;
        ystring = atof(ystr);
        targetx = posx;
        targety = ystring * scale;
        targetz = posz;
        
        DX = 0;
        DY = targety - posy;
        DZ = 0;
        linex = posx;
        liney = posy;
        delay (1000);
        command = true;
        };     
        if (inString.contains("X") && !inString.contains("Y") && !inString.contains("Z")){
        int xcharloc = inString.indexOf('X');
               
        int xlast = inString.length();
        xcharloc = xcharloc + 1;
        xstr = inString.substring(xcharloc, xlast);
        xcharloc = xcharloc - 1;
        xstring = atof(xstr);

        targetx = xstring * scale;
        targety = posy;
        targetz = posz;
        
        DX = targetx - posx;
        DY = 0;
        DZ = 0;
        linex = posx;
        liney = posy;
        delay (1000);
        command = true;
        };
}

}
void plotting(){
  if (type == 1){
  
  if (DX == 0 && DY != 0){
    DrawY();
    posz = targetz;
    Reportz();
  }  
  else if (DX != 0 && DY == 0){
    DrawX();
    posz = targetz;
    Reportz();
  }    
  else if (DX != 0 && DY != 0 && abs(DY) >= abs(DX)){
    DrawYX();
    posz = targetz;
    Reportz();
  }
  else if (DX != 0 && DY != 0 && abs(DX) > abs(DY)){
    DrawXY();
    posz = targetz;
    Reportz();
  }
  else if (DX == 0 && DY == 0){
    posz = targetz;
    Reportz();
    report(); 
    delay (abs(1000*scale));
  }  
 }
   report();
 }

void DrawY(){
  dy = 1 ;
     if (DY > 0) {
       if (posy < targety ) {
        motory.step(dy, BACKWARD, SINGLE);
        posx = posx;
        posy = posy + dy / stepy;
        report();
       }
     }
      else {
        if (posy > targety ){
        motory.step(dy, FORWARD, SINGLE);
        posx = posx;
        posy = posy - dy / stepy;
        report();
      }
    }
}

void DrawX(){
  dx = 1;
      if (DX > 0) {
        if (posx < targetx) {
        motorx.step(dx, BACKWARD, SINGLE);
        posx = posx + dx / stepx;
        posy = posy;
        report();
        }
      }
      else {
        if (posx > targetx){
        motorx.step(dx, FORWARD, SINGLE);
        posx = posx - dx / stepx;
        posy = posy;
        report();
      }
    }
}

Part 2

void DrawXY(){
   //unit on y
      float slope = abs(DX / DY);
      dy = 1;
      if (DY > 0){
        if (DX > 0){
          if (posy < targety){
            motory.step(dy, BACKWARD, SINGLE);
            posy = posy + dy / stepy;
            linex = linex + dy * slope / stepy;
            int dx = (int) ((linex - posx) * stepx);
            motorx.step(dx, BACKWARD, SINGLE);
            posx = posx + dx / stepx;
            report();
          }
        }
        else {
          if (posy < targety){
            motory.step(dy, BACKWARD, SINGLE);
            posy = posy + dy / stepy;
            linex = linex - dy * slope / stepy;
            int dx = (int) (abs(linex - posx) * stepx);
            motorx.step(dx, FORWARD, SINGLE);
            posx = posx - dx / stepx;
            report();
          }
        }
      }
      else{
        if (DX > 0){
          if (posy > targety){
            motory.step(dy, FORWARD, SINGLE);
            posy = posy - dy / stepy;
            linex = linex + dy * slope / stepy;
            int dx = (int) ((linex - posx) * stepx);
            motorx.step(dx, BACKWARD, SINGLE);
            posx = posx + dx / stepx;
            report();
          }
        }
        else {
          if (posy > targety){
            motory.step(dy, FORWARD, SINGLE);
            posy = posy - dy / stepy;
            linex = linex - dy * slope / stepy;
            int dx = (int) (abs(linex - posx) * stepx);
            motorx.step(dx, FORWARD, SINGLE);
            posx = posx - dx / stepx;
            report();
          }
        }
      }
}

void DrawYX(){
  //unit on x
      float slope = abs(DY / DX);
      dx = 1;
      if (DX > 0){
        if (DY > 0){
          if (posx < targetx){
            motorx.step(dx, BACKWARD, SINGLE);
            posx = posx + dx / stepx;
            liney = liney + dx * slope / stepx;
            int dy = (int) ((liney - posy) * stepy);
            motory.step(dy, BACKWARD, SINGLE);
            posy = posy + dy / stepy;
            report();
          }
        }
        else {
          if (posx < targetx){
            motorx.step(dx, BACKWARD, SINGLE);
            posx = posx + dx / stepx;
            liney = liney - dx * slope / stepx;
            int dy = (int) (abs(liney - posy) * stepy);
            motory.step(dy, FORWARD, SINGLE);
            posy = posy - dy / stepy;
            report();
          }
        }
      }
      else{
        if (DY > 0){
          if (posx > targetx){
            motorx.step(dx, FORWARD, SINGLE);
            posx = posx - dx / stepx;
            liney = liney + dx * slope / stepx;
            int dy = (int) ((liney - posy) * stepy);
            motory.step(dy, BACKWARD, SINGLE);
            posy = posy + dy / stepy;
            report();
          }
        }
        else{
          if (posx > targetx){
            motorx.step(dx, FORWARD, SINGLE);
            posx = posx - dx / stepx;
            liney = liney - dx * slope / stepx;
            int dy = (int) (abs(liney - posy) * stepy);
            motory.step(dy, FORWARD, SINGLE);
            posy = posy - dy / stepy;
            report();
          }
        }
      }
}

void report(){
  Serial.print ("X:");
  Serial.println (posx);
  Serial.print("\t");
  Serial.print ("Y:");
  Serial.println (posy); 
  Serial.print("\t");
  Serial.print ("Z:");
  Serial.println (posz); 
  Serial.print ("\n");
}

void CheckArrive(){

  if (abs(targetx-posx) + abs(targety-posy) + abs(targetz-posz)< 0.01 && command == true){
    command = false;
    Serial.print("*");
  }
}

void Reportz(){
  int intposz = (int)(posz * 100);
  mySerial.print("@");
  mySerial.print (intposz);
  mySerial.print("#");
}

void loop() {
  
  AcquireXYZ();
  if (command == true){
    plotting();
  }
  CheckArrive();
}

I'm looking for something like this for my 2 axis cnc, I'm struggling with the program to comunicate between arduino and my pc, any chances you could upload your C program too? :)

very nice! any estimation on accuracy yet? and what materials do you think you can manage? Id say with adjusting the speeds, feed rates and using cutting fluid it'll be quite the versatile setup! More pics of what you make! :)

Tested it and works cool, any plan on implementing G2 and G3 commands?

On a related note http://revision3.com/tbhs/cncmachine

wow!!! That's amazing work! I will be doing something similar soon :D