Mini Arduino Plotter Without a Servo Motor

18,864

266

53

Published

Introduction: Mini Arduino Plotter Without a Servo Motor

About: i am a Mechatronics engineering student from Tunisia i love robotics and all kinds of projects ,from time to time i make tutorials and share some projects am making.you can find me on instructables.com or my...

In this project I will show you how to turn two old DVD-drives into a mini plotter.this project is simple and easy to do and makes a good practice if you want to make a real CNC machine(this is why i started this project to prepare my self for a bigger CNC),you get to drive stepper motors and convert vector files to gcode..

this plotter is diffrent from the others because i used the cd tray mechnism for the z axis instead of a servo motor to lower the cost of the project hope you like it

let's get started :

Parts and tools:

2 - DVD-drives

3 - L293 H-bridges IC

1- Arduino uno

1 - Breadboard

- Some wires

- hot glue or something similar

- small pieces of plastic

- USB cable (i power the circuit from the pc)

1 - screw driver

i filmed all the steps on my youtube channel so check them out for more information :

Tunisian Maker : https://www.youtube.com/channel/UCsFmFKMpUdyIiE55W3KsTzw

Step 1: Gathering the Parts We Need From the DVD-drives

in this step we will begin by disassembling the DVD-drives to get the stepper motors and the carriages of the laser that reads the disk it's simple grab a screwdriver open the metal case and keep it it'll be the main body of our plotter also we will need the plastic mechanism of the DVD tray for our Z-axis this is how it looks :

this video is for step 2 and 3 also :

Step 2: Wiring the Stepper Motors

This is a tricky part cause the stepper motors are tiny and you need to take your time and be careful not to damage the motor cause i did and this is why:(IMPORTANT)

the stepper motor wires are attached in place with the plastic connector itself so if you remove the old connector the wire get loose and its hard to recover them after so you need to wire the new ones on top of the old one

each stepper motor needs 4 wires cut the four wires to the same length put a tip of solder on top then solder them to the stepper motor.

Step 3: Assembling the Plotter

the base of our plotter is the metal case itself i attached it with screws and bolts but you can use hot glue.

i mounted the X and Y axis perpendicular to each other with hot glue i didn't measure anything but it worked fine

for the Z axis i glued a piece of plastic to its back and glued it to the carriage of the Y axis

Step 4: Wiring the Circuit

get your breadboard put the 3 L293 IC first and wire the wires around them the last step would be wiring the motors

the drawings show it all.now before wiring the motors we need to find out the two pairs of coils i used my multimeter to find out the connected wires and connected each pair on a side of the IC

For the z axis it has a built in dc motor wich connects on a side of the third IC.

connect the arduino:

X axis 2,3,4,5

Y axis 6, 7,8,9

Z axis 10 11 but you can change it in the code if you want

this is the video :

Step 5: Testing the Connections and the Stepper Motors

its a simple arduino sketch using the fuctions of the stepper library like so:

For the X axis

#include <Stepper.h>

const int stepsPerRevolution = 20; //Connection pins: Stepper myStepperX(stepsPerRevolution, 8,9,10,11); void setup() { //Set speed: myStepperX.setSpeed(100); //max 250 steps for dvd/cd stepper motors myStepperX.step(160); delay(100); } void loop() {

}

For the Y axis

#include <Stepper.h>

const int stepsPerRevolution = 20; //Connection pins: Stepper myStepperX(stepsPerRevolution, 6,7,8,9); void setup() { //Set speed: myStepperX.setSpeed(100); //max 250 steps for dvd/cd stepper motors myStepperX.step(160); delay(100); } void loop() {

}

For the Z axis :

void setup() {
// Setup Serial.begin( 9600 ); pinMode(10, OUTPUT); pinMode(11, OUTPUT); delay(200);}

// Raises pen
void penUp() { digitalWrite(I1 , LOW);

digitalWrite(I2 , HIGH);

delay(200);

digitalWrite(I2 , LOW);

digitalWrite(I1 , LOW);

Serial.println("Pen up!"); }

// Lowers pen void penDown() {

digitalWrite(I2 , LOW);

digitalWrite(I1 , HIGH);

delay(200);

digitalWrite(I2 , LOW);

digitalWrite(I1 , LOW);

Serial.println("Pen down."); }

void loop() {

penUp();

penDown();

}

Step 6: Make G-code and Start Plotting

you need inkscape version 0.48.5 or it wont work and the plugin unicorn gcode plugin and the rest of the software with all the links is included are ready download

2 People Made This Project!

Recommendations

  • Clocks Contest

    Clocks Contest
  • Make it Move Contest

    Make it Move Contest
  • Oil Contest

    Oil Contest
user

We have a be nice policy.
Please be positive and constructive.

Tips

Questions

53 Comments

Hi, very nice instructable! I had an idea for a variation on this. Has anyone tried using the geared drive open/close mechanism in an xy plotter like this one? Maybe replace the dc motor that has the small pulley for the belt on it with the stepper motor from the laser slide? Could give you a little bit bigger drawing area. Just a thought.... Thanks!

Hello sir I have seen the wiring video I noted a voltage regulator Ic and two capacitors please tell us which capacitors and which is the voltage regulator Ic

sir, can u upload the code for testing the circuit..im a bigginner with arduino and stepper...

6 replies

check step 5 for testing the steppers individualy and the up and down movement

my z axis is not working thats y i askd u...thanks alot :)

sir,i tested it with 2cd drive stepper motors,it works...bt i want to make a cnc machine with dimensions 31x50cm and i had 2- mitsumi m35sp-8nb steppers+1 cd drive motor for z axis..what all changes i have to do in the coding?..

http://www.mitsumi.co.jp/latest/Catalog/pdf/motor_m35sp_8_e.pdf

for x and y i think the circuit can handle it and no code change is needed for z axis you want to replace it with a stepper motor th code you need i already wrote in the comments below =)

sir,it is not working, the stepper is not rotates smoothly...it turns a around20-30degree and stops then takes a next 20-30degree step then stops in an blink of eye...

can u helpme?

for x and y i think the circuit can handle it and no code change is needed for z axis you want to replace it with a stepper motor th code you need i already wrote in the comments below =)

I need help.can i used the Dc motor in place of stepper...!

1 reply

of course not you need 2 stepper motors and 1 dc motor

Hey TunMaker, I was wondering if you could do the same thing but having 3 stepper motors. Instead of having a DC Motor on the Z-Axis, you would have another stepper motor. Do you think it would work? and would the Arduino have enough ports to utilize the 3 Stepper motors?

5 replies

Definitely it works ...i made it using the code Mr.Tunmaker provided

as he told you the code is below in the comments try it and tell me how it works

yes the comments just below were about that the code we used for 3 stepper motors did not test it but it should work the others told me it did here try it nad read the comments below you'll know what am talking about

[code]

/*

Send GCODE to this Sketch using gctrl.pde https://github.com/damellis/gctrl

Convert SVG to GCODE with MakerBot Unicorn plugin for Inkscape available here https://github.com/martymcguire/inkscape-unicorn

More information about the Mini Arduino Plotter at tunisian maker youtube channel

https://www.youtube.com/channel/UCsFmFKMpUdyIiE55W3KsTzw

*/

#include <Stepper.h>

#define LINE_BUFFER_LENGTH 512

// Should be right for DVD steppers, but is not too important here

const int stepsPerRevolution = 20;

// create servo object to control a servo

// Initialize steppers for X- and Y-axis using this Arduino pins for the L293D H-bridge

Stepper myStepperY(stepsPerRevolution, 2,3,4,5);

Stepper myStepperX(stepsPerRevolution, 6,7,8,9);

Stepper myStepperZ(stepsPerRevolution, 10,11,12,13);

/* Structures, global variables */

struct point {

float x;

float y;

float z;

};

// Current position of plothead

struct point actuatorPos;

// Drawing settings, should be OK

float StepInc = 1;

int StepDelay = 0;

int LineDelay = 50;

int penDelay = 50;

// Motor steps to go 1 millimeter.

// Use test sketch to go 100 steps. Measure the length of line.

// Calculate steps per mm. Enter here.

float StepsPerMillimeterX = 6;

float StepsPerMillimeterY = 6;

// 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 = 30;

float Xpos = Xmin;

float Ypos = Ymin;

float Zpos = Zmax;

// Set to true to get debug output.

boolean verbose = false;

// Needs to interpret

// G1 for moving

// G4 P300 (wait 150ms)

// M300 S30 (pen down)

// M300 S50 (pen up)

// Discard anything with a (

// Discard any other command!

/**********************

* void setup() - Initialisations

***********************/

void setup() {

// Setup

Serial.begin( 9600 );

// Decrease if necessary

myStepperX.setSpeed(60);

myStepperY.setSpeed(60);

myStepperZ.setSpeed(50);

// Set & move to initial default position

// TBD

// Notifications!!!

Serial.println("Mini CNC Plotter alive and kicking!");

Serial.print("X range is from ");

Serial.print(Xmin);

Serial.print(" to ");

Serial.print(Xmax);

Serial.println(" mm.");

Serial.print("Y range is from ");

Serial.print(Ymin);

Serial.print(" to ");

Serial.print(Ymax);

Serial.println(" mm.");

}

/**********************

* void loop() - Main loop

***********************/

void loop()

{

delay(200);

char line[ LINE_BUFFER_LENGTH ];

char c;

int lineIndex;

bool lineIsComment, lineSemiColon;

lineIndex = 0;

lineSemiColon = false;

lineIsComment = false;

while (1) {

// Serial reception - Mostly from Grbl, added semicolon support

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

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':

penUp();

break;

case 'D':

penDown();

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) {

penDown();

}

if (Spos == 50) {

penUp();

}

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 );

}

}

}

}

/*********************************

* Draw a line from (x0;y0) to (x1;y1).

* Bresenham algo from https://www.marginallyclever.com/blog/2013/08/how-to-build-an-2-axis-arduino-cnc-gcode-interpreter/

* int (x1;y1) : Starting coordinates

* int (x2;y2) : Ending coordinates

**********************************/

void drawLine(float x1, float y1) {

if (verbose)

{

Serial.print("fx1, fy1: ");

Serial.print(x1);

Serial.print(",");

Serial.print(y1);

Serial.println("");

}

// Bring instructions 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 coordinates to steps

x1 = (int)(x1*StepsPerMillimeterX);

y1 = (int)(y1*StepsPerMillimeterY);

float x0 = Xpos;

float y0 = Ypos;

// Let's find out the change for the coordinates

long dx = abs(x1-x0);

long dy = abs(y1-y0);

int sx = x0<x1 ? StepInc : -StepInc;

int sy = y0<y1 ? StepInc : -StepInc;

long i;

long over = 0;

if (dx > dy) {

for (i=0; i<dx; ++i) {

myStepperX.step(sx);

over+=dy;

if (over>=dx) {

over-=dx;

myStepperY.step(sy);

}

delay(StepDelay);

}

}

else {

for (i=0; i<dy; ++i) {

myStepperY.step(sy);

over+=dx;

if (over>=dy) {

over-=dy;

myStepperX.step(sx);

}

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 before any next lines are submitted

delay(LineDelay);

// Update the positions

Xpos = x1;

Ypos = y1;

}

// Raises pen

void penUp() {

myStepperZ.step(stepsPerRevolution);

Zpos=Zmax;

if (verbose) {

Serial.println("Pen up!");

}

}

// Lowers pen

void penDown() {

myStepperZ.step(-stepsPerRevolution);

Zpos=Zmin;

if (verbose) {

Serial.println("Pen down.");

}

}

[/code

Tyvm I will try this setup out. And report back if it works. :D

Sorry for the trouble .... I did solve the problem .. current was less so motors were not getting proper voltage ...just attached a parallel supply to arduino and noweverything working well andgood .Thanks for your support and help ...I hope i can come up again in future for any other coding or hardware problem.

1 reply

it would be nice if u can just text me ur mail so that i can send u the video of it for more clarification