In this article, we are going to explain to you how to create a mini CNC plot using an Arduino Uno board. You can use it for various purposes. For example, you can code this to create your logo. This is a simple design and you can do it very easily. Let's go to the article.


CNC Plotter
CNC Plotter



You need some components to make this

Apparatus


1.ARDUINO UNO BOARD 


ARDUINO UNO BORD
ARDUINO UNO BORD




2.MOTOR DRIVE (L293D)


MOTOR DRIVE
MOTOR DRIVE





3.SERVO MOTOR 


SERVO MOTOR
SERVO MOTOR




4.JUMPING CABLE 
JUMPING CABLE
JUMPING CABLE 



5.DVD ROM(2 DVD ROM STEPPER MOTOR )


  • You can find a DVD from an old computer


Connection diagram




Connection diagram
Connection diagram




You can test the motor using this code before you work with the motor. You can check
1. Make sure the motor is properly connected
2. Whether or not the motor axis rotates well

Motor test


#include<Servo.h>
Servo name;
#include <AFMotor.h>


void setup() {
    AF_Stepper motor(200, 2);
    
Serial.begin(9600); // set up Serial library at 9600 bps
 name.attach(10);
Serial.println("Stepper test!");
motor.setSpeed(100); // 10 rpm
motor.step(500, FORWARD, SINGLE);
motor.release();
name.write(150);
delay(1000);
}
void loop() {
  const int stepsPerRevolution = 300;
AF_Stepper myStepperY(stepsPerRevolution,1);
AF_Stepper myStepperX(stepsPerRevolution, 1);
   


Main code




#include <AFMotor.h>
#include <Servo.h>
#define LINE_BUFFER_LENGTH 512

char STEP = MICROSTEP;

//Servo position dor up down
const int penZup = 90;
const int penZdown = 50;

//servo on PWM pin 10
const int penServoPin = 10;

//should be right for dvd steppers , but is not too important here
const int stepsPerRevolution = 100;

//creat servo object to control a servo
Servo penServo;

//initiate steppers for x-and y-axis using this ardiuno pins for the l293d H-bridge
AF_Stepper myStepperY(stepsPerRevolution, 2);
AF_Stepper myStepperX(stepsPerRevolution, 1);


/* Structure , globle variables  */
struct point {
  float x;
  float y;
  float z;
};

//current position of plothead structy
struct point actuatorPos;

//Drawing settings, should be OK
float Steplnc = 1;
int stepDelay = 1;
int LineDelay = 2;
int penDelay = 50;


//Motor steps to go 1 milimeter
//use test sketch to go 100 steps.  measure the length of line
//calculate steps per mm. Enter hear
float StepsPerMillimeterX = 100.0;
float StepsPerMillimeterY = 100.0;

//Drawing robot limits , in mm
//Ok to start with. could go up to 50 mm if calibrated well
float Xmin = 0;
float Xmax = 40;
float Ymin = 0;
float Ymax = 40;
float Zmin = 0;
float Zmax = 1;

float Xpos = Xmin;
float Ypos = Ymin;
float Zpos = Zmax;

//set to true to get debug output
boolean verbose = false;

//need to intrupt
//g1 for moving
//g4 p300(wait 150ms)
//M300 S30(per down)
//M300 S50(per up)
//discard anything with a(
//discard any other cammand!


void setup() {
  Serial.begin(9600);

  penServo.attach(penServoPin);
  penServo.write(penZup);
  delay(100);

  //Decrease if necessary
  myStepperX.setSpeed(600);
  myStepperY.setSpeed(600);

  //set & move to initial default position
  //TBD


  //Notification
  Serial.println("Mini CNC Plotter alive and kicking");
  Serial.print("X range is from");
  Serial.print("Xmin");
  Serial.print("to");
  Serial.print("X max");
  Serial.println("mm");
  Serial.print("Y range is from");
  Serial.print("Ymin");
  Serial.print("to");
  Serial.print("Y max");
  Serial.println("mm");
}

void loop() {
  delay(100);
  char line[LINE_BUFFER_LENGTH];
  char c;
  int lineindex;
  bool linelsComment, lineSemiColon;
  lineindex = 0;
  lineSemiColon = false;
  linelsComment = false;

  while (1) {
    //Serial reception-Mostly from grbl, add semicolon support
    while (Serial.available() > 0) {
      c = Serial.read();
      if ((c == '\n') || (c == '\r')) {
        //end of the line reach
        if (lineindex > 0) {
          //line is complet 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
        }
        lineSemiColon = false;
        linelsComment = false;
        Serial.println("ok");
      }
      else {
        if ((linelsComment) || (lineSemiColon)) {
          // throw away all comment characters
          if (c == ')') linelsComment = false;
          //end comment . resume line.
        }
        else {
          if (c <= ' ') {
            //throw away whitepace and control characters
          }
          else if (c == '/') {
            //block delete not supported. ignore cheracter.
          }
          else if (c == '(') {
            //enable comments flag and ignor all charcters until ' 0' or EOL.
            linelsComment = true;
          }
          else if (c == ';') {
            lineSemiColon = true;
          }
          else if (lineindex >= LINE_BUFFER_LENGTH - 1) {
            Serial.println("ERROR-line Buffer overflow");
            lineSemiColon = false;
            linelsComment = 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 ffor 1 parameter
  struct point newPos;

  newPos.x = 0.0;
  newPos.y = 0.0;

  //Need to interpret
  //G1 for moving
  //G4P300(wait 150ms)
  //G1 x1 x60 y30
  //G1 x30 50
  //M300 S30(pen down)
  //M300 S50(pen up)
  //Discard anyting with a (
  //Discard any other command

  while (currentIndex < charNB) {
    switch (line[currentIndex++]) {
      //Select command, if any
      case 'U':
        penUp();
        break;
      case 'D':
        penDown();
        break;
      case 'G':
        buffer[0] = line[currentIndex++];
        // \!/ Dirty-Only work 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 befor Y
            char*indexX = strchr(line + currentIndex, 'X');
            //Get 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.print("ok");
            actuatorPos.x = newPos.x;
            actuatorPos.y = newPos.y;
            break;
        }
        break;
      case 'M':
        buffer[0] = line[currentIndex++];
        // /!\ Dirt - 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) {
                penDown();
              }
              if (Spos == 50) {
                penUp();
              }
              break;

            }
          case 114:
            //M114 Repport possition
            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) {
  if (verbose) {
    Serial.print("fx1,fy1:");
    Serial.print(x1);
    Serial.print(",");
    Serial.print(y1);
    Serial.print("");
  }

  //Bring instction within limits
  if (x1 >= Xmax) {
    x1 = Xmax;
  }
  if (x1 <= Xmin) {
    x1 = Xmin;
  }
  if (y1 >= Ymax) {
    y1 = Ymax;
  }
  if (y1 <= Ymin) {
    y1 = Ymin;
  }
  if (verbose) {
    Serial.print("Xpos,Ypos:");
    Serial.print(Xpos);
    Serial.print(",");
    Serial.print(Ypos);
    Serial.println("");
  }
  if (verbose) {
    Serial.print("x1,y1");
    Serial.print(x1);
    Serial.print(",");
    Serial.print(y1);
    Serial.println("");
  }
  //convert cordinates to steps
  x1 = (int)(x1 * StepsPerMillimeterX);
  y1 = (int)(y1 * StepsPerMillimeterY);
  float x0 = Xpos;
  float y0 = Ypos;

  //Let's find out the change for the coordinate
  long dx = abs(x1 - 10);
  long dy = abs(y1 - y0);
  int sx = x0 < x1 ? Steplnc : - Steplnc;
  int sy = y0 < y1 ? Steplnc : - Steplnc;

  long i;
  long over = 0;

  if (dx > dy) {
    for (i = 0; i < dx; ++i) {
      myStepperX.onestep(sx, STEP);
      over += dy;
      if (over >= dx) {
        over -= dx;
        myStepperY.onestep(sy, STEP);
      }
      delay(stepDelay);
    }
  }
  else {
    for (i = 0; i < dy; ++i) {
      myStepperX.onestep(sx, STEP);
      over += dx;
      if (over >= dy) {
        over -= dy;
        myStepperX.onestep(sx, STEP);
      }
      delay(stepDelay);
    }
  }
  if (verbose) {
    Serial.print("dx,dy");
    Serial.print(dx);
    Serial.print(",");
    Serial.print(dy);
    Serial.println("");
  }

  if (verbose) {
    Serial.print("Going to ('')");
    Serial.print(x0);
    Serial.print(",");
    Serial.print(y0);
    Serial.println(")");
  }
  // Delay befor any next lines are submitted
  delay(LineDelay);
  // update the positions
  Xpos = x1;
  Ypos = y1;
}



// Raises pen
void penUp() {
  penServo.write(penZup);
  delay(penDelay);
  Zpos = Zmax;
  digitalWrite(15, LOW);
  digitalWrite(16, HIGH);
  if (verbose) {
    Serial.println("Pen Up!");
  }

}
//Lower pen
void penDown() {
  penServo.write(penZdown);
  delay(penDelay);
  Zpos = Zmin;
  digitalWrite(15, HIGH);
  digitalWrite(16, LOW);
  if (verbose) {
    Serial.println("Pen down!");
  }
}