Arduino Mini CNC Plotter aus CD/DVD Laufwerken
Arduino Mini CNC Plotter aus CD/DVD Laufwerken
CNC-Maschinen (Computerized Numerical Control) sind Werkzeugmaschinen, die durch den Einsatz moderner Steuerungstechnik in der Lage sind, Werkstücke mit hoher Präzision auch für komplexe Formen automatisch herzustellen.
Aufbau
Für den Aufbau des Arduino Mini CNC Plotters aus CD/DVD Laufwerken benötigen wir:
- 1 x Micro Servo 9G
- 1 x Arduino Uno
- 2 x L293D Stepper Motor Treiber
- 2 x CD oder DVD Laufwerke (gebraucht oder neu)
- 4 x M6 Schrauben (6cm lang)
- 4 x M6 Muttern
- 4 x Holzschrauben (3cm lang)
- 1 x Steckboard
- 1 x Päckchen Steckboardkabel
- Zwei Holzbretter (15cm x 15 cm x 1,5 cm)
In diesem Projekt zeige ich, wie du dir ganz einfach deinen eigenen kostengünstigen Arduino Mini-CNC-Plotter baust! Für die X- und Y-Achse verwenden wir zwei Schrittmotoren und Schienen von alten DVD- oder CD-Laufwerken. Für die Z-Achse verwenden wir einen kleinen Servomotor, der den Stift nach oben und unten bewegt.
Der erste Schritt, um mit dem Bau dieser Mini CNC-Maschine zu beginnen, ist das Zerlegen der DVD / CD-Laufwerke.
Nun, da wir beide Schrittmotoren haben, müssen wir im nächsten Schritt einige Kabel an die Schrittmotoren des CD oder DVD Laufwerkes löten.
Jetzt müssen wir die richtige Kombination für die Ansteuerung finden, um diese richtig verwenden zu können. Nimm einen Multimeter mit Krokodilklemmen und setze es auf die Durchgangsfunktion. Normalerweise schließen das erste und das zweite Kabel den Stromkreis – jetzt sollte ein Piepton ertönen – dies bedeutet, dass wir die erste Phase des Schrittmotors gefunden haben. Die anderen beiden Kabel sind für die zweite Phase des Schrittmotors zuständig. In meinem Fall verwendet einer der Schrittmotoren das rote und das braune Kabel für die erste Phase und das gelbe und orange Kabel für die zweite Phase.
Für die Befestigung der Schrittmotoren habe ich mir zwei Holzplatten, in der Größe 15 cm x 15 cm x 1,5 cm (Höhe x Breite x Tiefe), zugeschnitten. Lege einen Schrittmotor (mit Schienen) auf eines der Holzstücke und markiere die Aussparungen mit einem Stift, um anschließend die Löcher für die Schrauben zu Bohren. Für den Schrittmotor der oben ist und später den Stift hält, habe ich 6 mm große Löcher gebohrt, um den Schrittmotor später mit M6 Schrauben festziehen zu können. Für den unteren Schrittmotor habe ich nur vier kleine Löcher angebohrt, da hier das Sichern mit normalen Holzschrauben vollkommend ausreicht. Die beiden Holzbretter habe ich anschließend mit zwei Winkeln, wie es auf dem Bild zu sehen ist, fixiert.
Jetzt befestigen wir die Schrittmotoren, mit deren Schienen, auf unseren Holzbrettern. Hierfür habe ich mir Abstandhalter gedruckt, um sie einfacher auf einer Ebene ausrichten zu können. Die Abstandshalter kannst du dir hier downloaden: Abstandhalter
Jetzt kommt schwierigste Teil unserer Konstruktion. Du benötigst eine flache Oberfläche, um deinen Servomotor und die Stifthalterung befestigen zu können. Der Stift muss sich mithilfe des Servomotors auf und ab bewegen können. Schau dir das folgende Bild an, um es besser zu verstehen. Ich habe mich für einen Schienenführung, die ich mir aus einem Metallbaukasten gebaut habe, entschieden, da ich möglichst wenig Spiel, für eine bessere Qualität beim Plotten, erzielen wollte. Falls du diese Möglichkeit nicht besitzt ist deine Fantasie gefragt. Ansonsten kannst du dir auch fertige Stifthalter, bei Thingiverse, ausdrucken. Klicke hier!
Für das Plotterbett habe ich mir eine Metallplatte, in den Maßen 9 x 9 cm, stanzen lassen. Auf der Rückseite habe ich eine M4 Schraube geschweißt um diese an dem Schlitten befestigen zu können. Die Schraube habe ich durch die Aussparung des Lasers, den ich vorher entfernt habe, gesteckt, so dass die Metallplatte fest auf dem Schlitten befestigt werden konnte.
Arduino Mini CNC – Schaltung
Nun, da wir mit unserer Konstruktion fertig sind, ist es Zeit, die Schaltung zu bauen und die Schrittmotoren (X- und Y-Achse) zu testen. Beachte das Bild mit Schaltplan der Steckplatine. Die Verkabelung der Schrittmotoren ist etwas kniffelig, aber im nächsten Schritt findest du einen Testcode für die X- und Y-Achsen, um diese zu überprüfen. Wenn ein Steppermotor nicht ordnungsgemäß funktioniert musst du die richtige Kombination der Kabel finden, indem du die Kabel gegebenfalls umsteckst.
Für die Inbetriebnahme des Mini CNC Plotters brauchen wir eine zusätzliche 5 V Versorgungsspannung, da die 5 Volt eines USB-Anschlusses nicht genügend Strom liefert, um die Schrittmotoren zu versorgen.
Test Code für die X- und Y-Achse
Um die X- und Y-Achse deiner Schrittmotoren zu testen, spiele folgende Codes, nacheinander, auf deinen Arduino Uno, auf.
X-Achse: Der Schrittmotor für die X-Achse muss sich von vorne nach hinten bewegen (siehe Abbildung mit dem schwarzen Pfeil).
Y-Achse: Der Schrittmotor für die Y-Achsen muss sich von links nach rechts bewegen (roter Pfeil).
Wenn sich die Schrittmotoren richtig bewegen, bedeutet das, dass die Verkabelung der Schrittmotoren korrekt ist! Wenn nicht, versuche die Kabel zu tauschen.
Test Code für die X-Achse
[sourcecode language=“plain“]
#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() {
}
[/sourcecode]
Test Code für die Y-Achse
[sourcecode language=“plain“]
#include <Stepper.h>
const int stepsPerRevolution = 20;
// Connection pins:
Stepper myStepperY(stepsPerRevolution, 2,3,4,5);
void setup() {
// Set speed:
myStepperY.setSpeed(100);
// max 250 steps for dvd/cd stepper motor
myStepperY.step(160);
delay(100);
}
void loop() {
}
[/sourcecode]
CNC Code
/* x
Mini CNC Plotter firmware, based in TinyCNC https://github.com/MakerBlock/TinyCNC-Sketches
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 CNC Plotter here (german, sorry): http://www.makerblog.at/2015/02/projekt-mini-cnc-plotter-aus-alten-cddvd-laufwerken/
*/
#include <Servo.h>
#include <Stepper.h>
#define LINE_BUFFER_LENGTH 512
// Servo position for Up and Down
const int penZUp = 50;
const int penZDown = 90;
// Servo on PWM pin 6
const int penServoPin = 6;
// Should be right for DVD steppers, but is not too important here
const int stepsPerRevolution = 20;
// create servo object to control a servo
Servo penServo;
// 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, 8,9,10,11);
/* 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.0;
float StepsPerMillimeterY = 6.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;
// 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 );
penServo.attach(penServoPin);
penServo.write(penZUp);
delay(200);
// Decrease if necessary
myStepperX.setSpeed(250);
myStepperY.setSpeed(250);
// 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 == 50) { penDown(); } if (Spos == 30) { 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() {
penServo.write(penZUp);
delay(LineDelay);
Zpos=Zmax;
if (verbose) {
Serial.println("Pen up!");
}
}
// Lowers pen
void penDown() {
penServo.write(penZDown);
delay(LineDelay);
Zpos=Zmin;
if (verbose) {
Serial.println("Pen down.");
}
}
[/sourcecode]
Ansteuerung des Mini CNC Plotters über GCTRL
Nun können wir unser erstes Bild ausdrucken! Dazu verwenden wir das Verarbeitungsprogramm gctrl. Dieses Programm sendet Bilder, im G-Code Format, an den CNC-Plotter.
- Um den COM-Port unseres Arduinos einzustellen, drücken wir „P“.
- Ist dieses geschehen, drücken wir „G“ um ein Bild, im G-Code Format, auswählen zu können. Hier findest du ein Beispielbild zum Plotten: Download
Druckergebnis
G-Code Dateien mit Inkscape selber erstellen
Um G-Code Dateien selber erstellen zu können benötigen wir eine ältere Version von Inkscape. Bei der neusten Version ist es bei mir immer zu Fehlermeldungen gekommen. Dowload Inkscape!
Ist Inkscape 0.48 gedownloadet und installiert brauchen wir die Erweiterung Inkscape Unicorn, um G-Code Dateien speichern zu können. Download Inkscape Unicorn!
Wir entpacken die Datei und gehen bis in das Verzeichnis „scr“. Dort kopieren wir den Ordner „unicorn“ + die Dateien „.gitignore“, „unicorn.inx“ und „unicorn.py“ und fügen diese in den Ordner „Inkscape\share\extensions“ ein.
Als nächstes öffnen wir Inkscap und stellen unter Datei -> Dokumenteneigenschaften folgende Parameter ein:
Die Grafiken, die wir erstellen, müssen sich im oberen rechten Bildbereich befinden und dürfen nicht größer als 4 x 4 cm sein.
Druckbaren Text erstellen
Wollen wir einen Text erstellen gehen wir auf die linke Sidebar und wählen das Symbol „A|“ aus. Danach klicken in das Dokument, an der Stelle, wo wir unseren Text plazieren wollen und schreiben unseren Text. Mit dem Pfeilwerkzeug auf der linken Seite markieren wir diesen, gehen oben ins Menü auf Pfad und wählen den Punkt „Objekte in Pfad umwandeln“ aus.
Jetzt können wir den Text, den unser Mini CNC Plotter abbilden soll, unter Datei -> Speichern unter, sichern. Aber bevor wir dieses tun, stellen wir unter Dateityp noch „Makerbot Unicorn G-Code (*.gcode)“ ein.
Druckbare Grafik erstellen
Um eine Grafik zu erstellen, den unser Mini CNC Plotter abbilden soll, ziehen wir einfach unser Bild, das geplottet werden soll vom Desktop in unser Dokument und skalieren es auf eine Größe von 4 x 4 cm. Danach markieren wir die Grafik mit dem Pfeilwerkzeug auf der linken Seite und wälen unter Pfad im Menü den Punkt Bitmap vektorisieren aus. Hier kann man aus „Entlag eines Helligkeitswerts“, „Kantenerkennung“ oder „Fabquantisierung“ wählen. Hier müsst ihr ausprobieren, was für eure Grafik die beste Einstellung ist.
Hast du eine Grafik vektorisiert liegen die Orginalgrafik und das Vektorbild genau übereinander, so dass man oft nicht sieht, dass etwas vektorisiert wurde. Dafür wählst du einfach das Pfeilwerkzeug auf der linken Seite aus, markierst die Grafik und ziehst diese vom Vektorbild runter. Bevor ihr die Grafik im G-Code speichert, müsst ihr die Orginalgrafik herauslöschen. Das Speichern geschieht so wie ihr es oben, unter dem Punt „Druckbaren Text erstellen“, gelernt habt.
Ich hoffe, dir hat dieses Tutorial gefallen und würde mich über eine Bewertung oben auf der Seite oder über ein Like auf meiner Facebook Fanpage freuen. Falls du Probleme, Fragen oder Anregungen hast, kannst du mich jeder Zeit, unter dem Punkt Kontakt, erreichen. Ich wünsche dir viel Spass und ein gutes Gelingen mit diesem Tutorial.
The C code posted on the site has an error.
Please send the C code file by mail.
I beg you.
Thank you for your feedback. I have fixed the issue and added download buttons for the codes.