Components and supplies
Stepper Motor
Servos (Tower Pro MG996R)
Arduino UNO
Jumper wires (generic)
Project description
Code
SOFTWARE
c_cpp
1#include <Stepper.h> 2#include <Servo.h> 3#define LINE_BUFFER_LENGTH 512 4 5const int penZUp = 40; 6const int penZDown = 80; 7 8const int penServoPin = 6; 9 10 11const int stepsPerRevolution = 60; 12 13Servo penServo; 14 15Stepper myStepperY(stepsPerRevolution, 5,3,4,2); 16Stepper myStepperX(stepsPerRevolution, 11,9,10,8); 17 18struct point { 19 float x; 20 float y; 21 float z; 22}; 23 24struct point actuatorPos; 25 26float StepInc = 1; 27int StepDelay = 0; 28int LineDelay = 50; 29int penDelay = 50; 30 31float StepsPerMillimeterX = 100.0; 32float StepsPerMillimeterY = 100.0; 33 34float Xmin = 0; 35float Xmax = 100; 36float Ymin = 0; 37float Ymax = 100; 38float Zmin = 0; 39float Zmax = 1; 40 41float Xpos = Xmin; 42float Ypos = Ymin; 43float Zpos = Zmax; 44 45boolean verbose = false; 46 47void setup() { 48 Serial.begin( 9600 ); 49 50 penServo.attach(penServoPin); 51 penServo.write(penZUp); 52 delay(200); 53 54 myStepperX.setSpeed(200); 55 myStepperY.setSpeed(200); 56 57 Serial.println("Mini CNC Plotter alive and kicking!"); 58 Serial.print("X range is from "); 59 Serial.print(Xmin); 60 Serial.print(" to "); 61 Serial.print(Xmax); 62 Serial.println(" mm."); 63 Serial.print("Y range is from "); 64 Serial.print(Ymin); 65 Serial.print(" to "); 66 Serial.print(Ymax); 67 Serial.println(" mm."); 68} 69 70void loop() 71{ 72 delay(200); 73 char line[ LINE_BUFFER_LENGTH ]; 74 char c; 75 int lineIndex; 76 bool lineIsComment, lineSemiColon; 77 78 lineIndex = 0; 79 lineSemiColon = false; 80 lineIsComment = false; 81 82 while (1) { 83 84 while ( Serial.available()>0 ) { 85 c = Serial.read(); 86 if (( c == '\n') || (c == '\r') ) { 87 if ( lineIndex > 0 ) { 88 line[ lineIndex ] = '\\0'; 89 if (verbose) { 90 Serial.print( "Received : "); 91 Serial.println( line ); 92 } 93 processIncomingLine( line, lineIndex ); 94 lineIndex = 0; 95 } 96 else { 97 98 } 99 lineIsComment = false; 100 lineSemiColon = false; 101 Serial.println("ok"); 102 } 103 else { 104 if ( (lineIsComment) || (lineSemiColon) ) { // Throw away all comment characters 105 if ( c == ')' ) lineIsComment = false; // End of comment. Resume line. 106 } 107 else { 108 if ( c <= ' ' ) { // Throw away whitepace and control characters 109 } 110 else if ( c == '/' ) { // Block delete not supported. Ignore character. 111 } 112 else if ( c == '(' ) { // Enable comments flag and ignore all characters until ')' or EOL. 113 lineIsComment = true; 114 } 115 else if ( c == ';' ) { 116 lineSemiColon = true; 117 } 118 else if ( lineIndex >= LINE_BUFFER_LENGTH-1 ) { 119 Serial.println( "ERROR - lineBuffer overflow" ); 120 lineIsComment = false; 121 lineSemiColon = false; 122 } 123 else if ( c >= 'a' && c <= 'z' ) { // Upcase lowercase 124 line[ lineIndex++ ] = c-'a'+'A'; 125 } 126 else { 127 line[ lineIndex++ ] = c; 128 } 129 } 130 } 131 } 132 } 133} 134 135void processIncomingLine( char* line, int charNB ) { 136 int currentIndex = 0; 137 char buffer[ 64 ]; // Hope that 64 is enough for 1 parameter 138 struct point newPos; 139 140 newPos.x = 0.0; 141 newPos.y = 0.0; 142 143 // Needs to interpret 144 // G1 for moving 145 // G4 P300 (wait 150ms) 146 // G1 X60 Y30 147 // G1 X30 Y50 148 // M300 S30 (pen down) 149 // M300 S50 (pen up) 150 // Discard anything with a ( 151 // Discard any other command! 152 153 while( currentIndex < charNB ) { 154 switch ( line[ currentIndex++ ] ) { // Select command, if any 155 case 'U': 156 penUp(); 157 break; 158 case 'D': 159 penDown(); 160 break; 161 case 'G': 162 buffer[0] = line[ currentIndex++ ]; // /!\Dirty - Only works with 2 digit commands 163 // buffer[1] = line[ currentIndex++ ]; 164 // buffer[2] = '\\0'; 165 buffer[1] = '\\0'; 166 167 switch ( atoi( buffer ) ){ // Select G command 168 case 0: // G00 & G01 - Movement or fast movement. Same here 169 case 1: 170 // /!\Dirty - Suppose that X is before Y 171 char* indexX = strchr( line+currentIndex, 'X' ); // Get X/Y position in the string (if any) 172 char* indexY = strchr( line+currentIndex, 'Y' ); 173 if ( indexY <= 0 ) { 174 newPos.x = atof( indexX + 1); 175 newPos.y = actuatorPos.y; 176 } 177 else if ( indexX <= 0 ) { 178 newPos.y = atof( indexY + 1); 179 newPos.x = actuatorPos.x; 180 } 181 else { 182 newPos.y = atof( indexY + 1); 183 indexY = '\\0'; 184 newPos.x = atof( indexX + 1); 185 } 186 drawLine(newPos.x, newPos.y ); 187 // Serial.println("ok"); 188 actuatorPos.x = newPos.x; 189 actuatorPos.y = newPos.y; 190 break; 191 } 192 break; 193 case 'M': 194 buffer[0] = line[ currentIndex++ ]; // /!\Dirty - Only works with 3 digit commands 195 buffer[1] = line[ currentIndex++ ]; 196 buffer[2] = line[ currentIndex++ ]; 197 buffer[3] = '\\0'; 198 switch ( atoi( buffer ) ){ 199 case 300: 200 { 201 char* indexS = strchr( line+currentIndex, 'S' ); 202 float Spos = atof( indexS + 1); 203 // Serial.println("ok"); 204 if (Spos == 30) { 205 penDown(); 206 } 207 if (Spos == 50) { 208 penUp(); 209 } 210 break; 211 } 212 case 114: // M114 - Repport position 213 Serial.print( "Absolute position : X = " ); 214 Serial.print( actuatorPos.x ); 215 Serial.print( " - Y = " ); 216 Serial.println( actuatorPos.y ); 217 break; 218 default: 219 Serial.print( "Command not recognized : M"); 220 Serial.println( buffer ); 221 } 222 } 223 } 224 225 226 227} 228 229 230 231void drawLine(float x1, float y1) { 232 233 if (verbose) 234 { 235 Serial.print("fx1, fy1: "); 236 Serial.print(x1); 237 Serial.print(","); 238 Serial.print(y1); 239 Serial.println(""); 240 } 241 242 243 if (x1 >= Xmax) { 244 x1 = Xmax; 245 } 246 if (x1 <= Xmin) { 247 x1 = Xmin; 248 } 249 if (y1 >= Ymax) { 250 y1 = Ymax; 251 } 252 if (y1 <= Ymin) { 253 y1 = Ymin; 254 } 255 256 if (verbose) 257 { 258 Serial.print("Xpos, Ypos: "); 259 Serial.print(Xpos); 260 Serial.print(","); 261 Serial.print(Ypos); 262 Serial.println(""); 263 } 264 265 if (verbose) 266 { 267 Serial.print("x1, y1: "); 268 Serial.print(x1); 269 Serial.print(","); 270 Serial.print(y1); 271 Serial.println(""); 272 } 273 274 // Convert coordinates to steps 275 x1 = (int)(x1*StepsPerMillimeterX); 276 y1 = (int)(y1*StepsPerMillimeterY); 277 float x0 = Xpos; 278 float y0 = Ypos; 279 280 // Let's find out the change for the coordinates 281 long dx = abs(x1-x0); 282 long dy = abs(y1-y0); 283 int sx = x0<x1 ? StepInc : -StepInc; 284 int sy = y0<y1 ? StepInc : -StepInc; 285 286 long i; 287 long over = 0; 288 289 if (dx > dy) { 290 for (i=0; i<dx; ++i) { 291 myStepperX.step(sx); 292 over+=dy; 293 if (over>=dx) { 294 over-=dx; 295 myStepperY.step(sy); 296 } 297 delay(StepDelay); 298 } 299 } 300 else { 301 for (i=0; i<dy; ++i) { 302 myStepperY.step(sy); 303 over+=dx; 304 if (over>=dy) { 305 over-=dy; 306 myStepperX.step(sx); 307 } 308 delay(StepDelay); 309 } 310 } 311 312 if (verbose) 313 { 314 Serial.print("dx, dy:"); 315 Serial.print(dx); 316 Serial.print(","); 317 Serial.print(dy); 318 Serial.println(""); 319 } 320 321 if (verbose) 322 { 323 Serial.print("Going to ("); 324 Serial.print(x0); 325 Serial.print(","); 326 Serial.print(y0); 327 Serial.println(")"); 328 } 329 330 331 delay(LineDelay); 332 333 Xpos = x1; 334 Ypos = y1; 335} 336 337 338void penUp() { 339 penServo.write(penZUp); 340 delay(LineDelay); 341 Zpos=Zmax; 342 if (verbose) { 343 Serial.println("Pen up!"); 344 } 345} 346void penDown() { 347 penServo.write(penZDown); 348 delay(LineDelay); 349 Zpos=Zmin; 350 if (verbose) { 351 Serial.println("Pen down."); 352 } 353}
SOFTWARE
c_cpp
1#include <Stepper.h> 2#include <Servo.h> 3#define LINE_BUFFER_LENGTH 4 512 5 6const int penZUp = 40; 7const int penZDown = 80; 8 9const int penServoPin 10 = 6; 11 12 13const int stepsPerRevolution = 60; 14 15Servo penServo; 16 17Stepper 18 myStepperY(stepsPerRevolution, 5,3,4,2); 19Stepper myStepperX(stepsPerRevolution, 20 11,9,10,8); 21 22struct point { 23 float x; 24 float y; 25 float z; 26 27}; 28 29struct point actuatorPos; 30 31float StepInc = 1; 32int StepDelay 33 = 0; 34int LineDelay = 50; 35int penDelay = 50; 36 37float StepsPerMillimeterX 38 = 100.0; 39float StepsPerMillimeterY = 100.0; 40 41float Xmin = 0; 42float Xmax 43 = 100; 44float Ymin = 0; 45float Ymax = 100; 46float Zmin = 0; 47float Zmax 48 = 1; 49 50float Xpos = Xmin; 51float Ypos = Ymin; 52float Zpos = Zmax; 53 54boolean 55 verbose = false; 56 57void setup() { 58 Serial.begin( 9600 ); 59 60 penServo.attach(penServoPin); 61 62 penServo.write(penZUp); 63 delay(200); 64 65 myStepperX.setSpeed(200); 66 67 myStepperY.setSpeed(200); 68 69 Serial.println("Mini CNC Plotter alive and 70 kicking!"); 71 Serial.print("X range is from "); 72 Serial.print(Xmin); 73 74 Serial.print(" to "); 75 Serial.print(Xmax); 76 Serial.println(" 77 mm."); 78 Serial.print("Y range is from "); 79 Serial.print(Ymin); 80 81 Serial.print(" to "); 82 Serial.print(Ymax); 83 Serial.println(" mm."); 84 85} 86 87void loop() 88{ 89 delay(200); 90 char line[ LINE_BUFFER_LENGTH 91 ]; 92 char c; 93 int lineIndex; 94 bool lineIsComment, lineSemiColon; 95 96 97 lineIndex = 0; 98 lineSemiColon = false; 99 lineIsComment = false; 100 101 102 while (1) { 103 104 while ( Serial.available()>0 ) { 105 c = Serial.read(); 106 107 if (( c == '\ 108') || (c == '\ ') ) { 109 if ( lineIndex 110 > 0 ) { 111 line[ lineIndex ] = '\\0'; 112 113 if (verbose) { 114 Serial.print( "Received : "); 115 Serial.println( 116 line ); 117 } 118 processIncomingLine( line, lineIndex ); 119 120 lineIndex = 0; 121 } 122 else { 123 124 } 125 126 lineIsComment = false; 127 lineSemiColon = false; 128 Serial.println("ok"); 129 130 } 131 else { 132 if ( (lineIsComment) || (lineSemiColon) 133 ) { // Throw away all comment characters 134 if ( c == ')' ) lineIsComment 135 = false; // End of comment. Resume line. 136 } 137 else { 138 139 if ( c <= ' ' ) { // Throw away whitepace and 140 control characters 141 } 142 else if ( c == '/' ) { // 143 Block delete not supported. Ignore character. 144 } 145 else 146 if ( c == '(' ) { // Enable comments flag and ignore all characters 147 until ')' or EOL. 148 lineIsComment = true; 149 } 150 else 151 if ( c == ';' ) { 152 lineSemiColon = true; 153 } 154 else 155 if ( lineIndex >= LINE_BUFFER_LENGTH-1 ) { 156 Serial.println( "ERROR 157 - lineBuffer overflow" ); 158 lineIsComment = false; 159 lineSemiColon 160 = false; 161 } 162 else if ( c >= 'a' && c <= 'z' ) { // 163 Upcase lowercase 164 line[ lineIndex++ ] = c-'a'+'A'; 165 } 166 167 else { 168 line[ lineIndex++ ] = c; 169 } 170 171 } 172 } 173 } 174 } 175} 176 177void processIncomingLine( char* 178 line, int charNB ) { 179 int currentIndex = 0; 180 char buffer[ 64 ]; // 181 Hope that 64 is enough for 1 parameter 182 struct point newPos; 183 184 newPos.x 185 = 0.0; 186 newPos.y = 0.0; 187 188 // Needs to interpret 189 // G1 for moving 190 191 // G4 P300 (wait 150ms) 192 // G1 X60 Y30 193 // G1 X30 Y50 194 // M300 195 S30 (pen down) 196 // M300 S50 (pen up) 197 // Discard anything with a ( 198 199 // Discard any other command! 200 201 while( currentIndex < charNB ) { 202 switch 203 ( line[ currentIndex++ ] ) { // Select command, if any 204 case 205 'U': 206 penUp(); 207 break; 208 case 'D': 209 penDown(); 210 211 break; 212 case 'G': 213 buffer[0] = line[ currentIndex++ ]; // 214 /!\Dirty - Only works with 2 digit commands 215 // buffer[1] = line[ 216 currentIndex++ ]; 217 // buffer[2] = '\\0'; 218 buffer[1] = '\\0'; 219 220 221 switch ( atoi( buffer ) ){ // Select G command 222 case 223 0: // G00 & G01 - Movement or fast movement. Same 224 here 225 case 1: 226 // /!\Dirty - Suppose that X is before Y 227 228 char* indexX = strchr( line+currentIndex, 'X' ); // Get X/Y position in 229 the string (if any) 230 char* indexY = strchr( line+currentIndex, 'Y' ); 231 232 if ( indexY <= 0 ) { 233 newPos.x = atof( indexX + 1); 234 newPos.y 235 = actuatorPos.y; 236 } 237 else if ( indexX <= 0 ) { 238 newPos.y 239 = atof( indexY + 1); 240 newPos.x = actuatorPos.x; 241 } 242 else 243 { 244 newPos.y = atof( indexY + 1); 245 indexY = '\\0'; 246 newPos.x 247 = atof( indexX + 1); 248 } 249 drawLine(newPos.x, newPos.y ); 250 251 // Serial.println("ok"); 252 actuatorPos.x = newPos.x; 253 254 actuatorPos.y = newPos.y; 255 break; 256 } 257 break; 258 259 case 'M': 260 buffer[0] = line[ currentIndex++ ]; // /!\Dirty 261 - Only works with 3 digit commands 262 buffer[1] = line[ currentIndex++ ]; 263 264 buffer[2] = line[ currentIndex++ ]; 265 buffer[3] = '\\0'; 266 switch 267 ( atoi( buffer ) ){ 268 case 300: 269 { 270 char* indexS = 271 strchr( line+currentIndex, 'S' ); 272 float Spos = atof( indexS + 1); 273 274 // Serial.println("ok"); 275 if (Spos == 30) { 276 277 penDown(); 278 } 279 if (Spos == 50) { 280 penUp(); 281 282 } 283 break; 284 } 285 case 114: // 286 M114 - Repport position 287 Serial.print( "Absolute position : X = " ); 288 289 Serial.print( actuatorPos.x ); 290 Serial.print( " - Y = " ); 291 292 Serial.println( actuatorPos.y ); 293 break; 294 default: 295 296 Serial.print( "Command not recognized : M"); 297 Serial.println( 298 buffer ); 299 } 300 } 301 } 302 303 304 305} 306 307 308 309void drawLine(float 310 x1, float y1) { 311 312 if (verbose) 313 { 314 Serial.print("fx1, fy1: "); 315 316 Serial.print(x1); 317 Serial.print(","); 318 Serial.print(y1); 319 Serial.println(""); 320 321 } 322 323 324 if (x1 >= Xmax) { 325 x1 = Xmax; 326 } 327 if (x1 <= 328 Xmin) { 329 x1 = Xmin; 330 } 331 if (y1 >= Ymax) { 332 y1 = Ymax; 333 334 } 335 if (y1 <= Ymin) { 336 y1 = Ymin; 337 } 338 339 if (verbose) 340 341 { 342 Serial.print("Xpos, Ypos: "); 343 Serial.print(Xpos); 344 Serial.print(","); 345 346 Serial.print(Ypos); 347 Serial.println(""); 348 } 349 350 if (verbose) 351 352 { 353 Serial.print("x1, y1: "); 354 Serial.print(x1); 355 Serial.print(","); 356 357 Serial.print(y1); 358 Serial.println(""); 359 } 360 361 // Convert coordinates 362 to steps 363 x1 = (int)(x1*StepsPerMillimeterX); 364 y1 = (int)(y1*StepsPerMillimeterY); 365 366 float x0 = Xpos; 367 float y0 = Ypos; 368 369 // Let's find out the change 370 for the coordinates 371 long dx = abs(x1-x0); 372 long dy = abs(y1-y0); 373 int 374 sx = x0<x1 ? StepInc : -StepInc; 375 int sy = y0<y1 ? StepInc : -StepInc; 376 377 378 long i; 379 long over = 0; 380 381 if (dx > dy) { 382 for (i=0; i<dx; ++i) 383 { 384 myStepperX.step(sx); 385 over+=dy; 386 if (over>=dx) { 387 388 over-=dx; 389 myStepperY.step(sy); 390 } 391 delay(StepDelay); 392 393 } 394 } 395 else { 396 for (i=0; i<dy; ++i) { 397 myStepperY.step(sy); 398 399 over+=dx; 400 if (over>=dy) { 401 over-=dy; 402 myStepperX.step(sx); 403 404 } 405 delay(StepDelay); 406 } 407 } 408 409 if (verbose) 410 411 { 412 Serial.print("dx, dy:"); 413 Serial.print(dx); 414 Serial.print(","); 415 416 Serial.print(dy); 417 Serial.println(""); 418 } 419 420 if (verbose) 421 422 { 423 Serial.print("Going to ("); 424 Serial.print(x0); 425 Serial.print(","); 426 427 Serial.print(y0); 428 Serial.println(")"); 429 } 430 431 432 delay(LineDelay); 433 434 435 Xpos = x1; 436 Ypos = y1; 437} 438 439 440void penUp() { 441 penServo.write(penZUp); 442 443 delay(LineDelay); 444 Zpos=Zmax; 445 if (verbose) { 446 Serial.println("Pen 447 up!"); 448 } 449} 450void penDown() { 451 penServo.write(penZDown); 452 delay(LineDelay); 453 454 Zpos=Zmin; 455 if (verbose) { 456 Serial.println("Pen down."); 457 458 } 459}
Downloadable files
SHEMATIC
SHEMATIC
Comments
Only logged in users can leave comments
Niko123
0 Followers
•0 Projects
Table of contents
Intro
10
0