Advertisement
Guest User

Untitled

a guest
May 24th, 2016
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.27 KB | None | 0 0
  1. /*
  2.  Mini CNC Plotter firmware, based in TinyCNC https://github.com/MakerBlock/TinyCNC-Sketches
  3.  Send GCODE to this Sketch using gctrl.pde https://github.com/damellis/gctrl
  4.  Convert SVG to GCODE with MakerBot Unicorn plugin for Inkscape available here https://github.com/martymcguire/inkscape-unicorn
  5.  
  6.  More information about the Mini CNC Plotter here (german, sorry): http://www.makerblog.at/2015/02/projekt-mini-cnc-plotter-aus-alten-cddvd-laufwerken/
  7.   */
  8.  
  9. #include <Servo.h>
  10. #include <Stepper.h>
  11.  
  12. #define LINE_BUFFER_LENGTH 512
  13.  
  14. // Servo position for Up and Down
  15. const int penZUp = 80;
  16. const int penZDown = 40;
  17.  
  18. // Servo on PWM pin 6
  19. const int penServoPin = 6;
  20.  
  21. // Should be right for DVD steppers, but is not too important here
  22. const int stepsPerRevolution = 20;
  23.  
  24. // create servo object to control a servo
  25. Servo penServo;  
  26.  
  27. // Initialize steppers for X- and Y-axis using this Arduino pins for the L293D H-bridge
  28. Stepper myStepperY(stepsPerRevolution, 2,3,4,5);            
  29. Stepper myStepperX(stepsPerRevolution, 8,9,10,11);  
  30.  
  31. /* Structures, global variables    */
  32. struct point {
  33.   float x;
  34.   float y;
  35.   float z;
  36. };
  37.  
  38. // Current position of plothead
  39. struct point actuatorPos;
  40.  
  41. //  Drawing settings, should be OK
  42. float StepInc = 1;
  43. int StepDelay = 0;
  44. int LineDelay = 50;
  45. int penDelay = 50;
  46.  
  47. // Motor steps to go 1 millimeter.
  48. // Use test sketch to go 100 steps. Measure the length of line.
  49. // Calculate steps per mm. Enter here.
  50. float StepsPerMillimeterX = 6.0;
  51. float StepsPerMillimeterY = 6.0;
  52.  
  53. // Drawing robot limits, in mm
  54. // OK to start with. Could go up to 50 mm if calibrated well.
  55. float Xmin = 0;
  56. float Xmax = 40;
  57. float Ymin = 0;
  58. float Ymax = 40;
  59. float Zmin = 0;
  60. float Zmax = 1;
  61.  
  62. float Xpos = Xmin;
  63. float Ypos = Ymin;
  64. float Zpos = Zmax;
  65.  
  66. // Set to true to get debug output.
  67. boolean verbose = false;
  68.  
  69. //  Needs to interpret
  70. //  G1 for moving
  71. //  G4 P300 (wait 150ms)
  72. //  M300 S30 (pen down)
  73. //  M300 S50 (pen up)
  74. //  Discard anything with a (
  75. //  Discard any other command!
  76.  
  77. /**********************
  78.  * void setup() - Initialisations
  79.  ***********************/
  80. void setup() {
  81.   //  Setup
  82.   Serial.begin( 9600 );
  83.  
  84.   penServo.attach(penServoPin);
  85.   penServo.write(penZUp);
  86.   delay(200);
  87.  
  88.   // Decrease if necessary
  89.   myStepperX.setSpeed(250);
  90.   myStepperY.setSpeed(250);  
  91.  
  92.   //  Set & move to initial default position
  93.   // TBD
  94.  
  95.   //  Notifications!!!
  96.   Serial.println("Mini CNC Plotter alive and kicking!");
  97.   Serial.print("X range is from ");
  98.   Serial.print(Xmin);
  99.   Serial.print(" to ");
  100.   Serial.print(Xmax);
  101.   Serial.println(" mm.");
  102.   Serial.print("Y range is from ");
  103.   Serial.print(Ymin);
  104.   Serial.print(" to ");
  105.   Serial.print(Ymax);
  106.   Serial.println(" mm.");
  107. }
  108.  
  109. /**********************
  110.  * void loop() - Main loop
  111.  ***********************/
  112. void loop()
  113. {
  114.   delay(200);
  115.   char line[ LINE_BUFFER_LENGTH ];
  116.   char c;
  117.   int lineIndex;
  118.   bool lineIsComment, lineSemiColon;
  119.  
  120.   lineIndex = 0;
  121.   lineSemiColon = false;
  122.   lineIsComment = false;
  123.  
  124.   while (1) {
  125.  
  126.     // Serial reception - Mostly from Grbl, added semicolon support
  127.     while ( Serial.available()>0 ) {
  128.       c = Serial.read();
  129.       if (( c == '\n') || (c == '\r') ) {             // End of line reached
  130.         if ( lineIndex > 0 ) {                        // Line is complete. Then execute!
  131.           line[ lineIndex ] = '\0';                   // Terminate string
  132.           if (verbose) {
  133.             Serial.print( "Received : ");
  134.             Serial.println( line );
  135.           }
  136.           processIncomingLine( line, lineIndex );
  137.           lineIndex = 0;
  138.         }
  139.         else {
  140.           // Empty or comment line. Skip block.
  141.         }
  142.         lineIsComment = false;
  143.         lineSemiColon = false;
  144.         Serial.println("ok");    
  145.       }
  146.       else {
  147.         if ( (lineIsComment) || (lineSemiColon) ) {   // Throw away all comment characters
  148.           if ( c == ')' )  lineIsComment = false;     // End of comment. Resume line.
  149.         }
  150.         else {
  151.           if ( c <= ' ' ) {                           // Throw away whitepace and control characters
  152.           }
  153.           else if ( c == '/' ) {                    // Block delete not supported. Ignore character.
  154.           }
  155.           else if ( c == '(' ) {                    // Enable comments flag and ignore all characters until ')' or EOL.
  156.             lineIsComment = true;
  157.           }
  158.           else if ( c == ';' ) {
  159.             lineSemiColon = true;
  160.           }
  161.           else if ( lineIndex >= LINE_BUFFER_LENGTH-1 ) {
  162.             Serial.println( "ERROR - lineBuffer overflow" );
  163.             lineIsComment = false;
  164.             lineSemiColon = false;
  165.           }
  166.           else if ( c >= 'a' && c <= 'z' ) {        // Upcase lowercase
  167.             line[ lineIndex++ ] = c-'a'+'A';
  168.           }
  169.           else {
  170.             line[ lineIndex++ ] = c;
  171.           }
  172.         }
  173.       }
  174.     }
  175.   }
  176. }
  177.  
  178. void processIncomingLine( char* line, int charNB ) {
  179.   int currentIndex = 0;
  180.   char buffer[ 64 ];                                 // Hope that 64 is enough for 1 parameter
  181.   struct point newPos;
  182.  
  183.   newPos.x = 0.0;
  184.   newPos.y = 0.0;
  185.  
  186.   //  Needs to interpret
  187.   //  G1 for moving
  188.   //  G4 P300 (wait 150ms)
  189.   //  G1 X60 Y30
  190.   //  G1 X30 Y50
  191.   //  M300 S30 (pen down)
  192.   //  M300 S50 (pen up)
  193.   //  Discard anything with a (
  194.   //  Discard any other command!
  195.  
  196.   while( currentIndex < charNB ) {
  197.     switch ( line[ currentIndex++ ] ) {              // Select command, if any
  198.     case 'U':
  199.       penUp();
  200.       break;
  201.     case 'D':
  202.       penDown();
  203.       break;
  204.     case 'G':
  205.       buffer[0] = line[ currentIndex++ ];          // /!\ Dirty - Only works with 2 digit commands
  206.       //      buffer[1] = line[ currentIndex++ ];
  207.       //      buffer[2] = '\0';
  208.       buffer[1] = '\0';
  209.  
  210.       switch ( atoi( buffer ) ){                   // Select G command
  211.       case 0:                                   // G00 & G01 - Movement or fast movement. Same here
  212.       case 1:
  213.         // /!\ Dirty - Suppose that X is before Y
  214.         char* indexX = strchr( line+currentIndex, 'X' );  // Get X/Y position in the string (if any)
  215.         char* indexY = strchr( line+currentIndex, 'Y' );
  216.         if ( indexY <= 0 ) {
  217.           newPos.x = atof( indexX + 1);
  218.           newPos.y = actuatorPos.y;
  219.         }
  220.         else if ( indexX <= 0 ) {
  221.           newPos.y = atof( indexY + 1);
  222.           newPos.x = actuatorPos.x;
  223.         }
  224.         else {
  225.           newPos.y = atof( indexY + 1);
  226.           indexY = '\0';
  227.           newPos.x = atof( indexX + 1);
  228.         }
  229.         drawLine(newPos.x, newPos.y );
  230.         //        Serial.println("ok");
  231.         actuatorPos.x = newPos.x;
  232.         actuatorPos.y = newPos.y;
  233.         break;
  234.       }
  235.       break;
  236.     case 'M':
  237.       buffer[0] = line[ currentIndex++ ];        // /!\ Dirty - Only works with 3 digit commands
  238.       buffer[1] = line[ currentIndex++ ];
  239.       buffer[2] = line[ currentIndex++ ];
  240.       buffer[3] = '\0';
  241.       switch ( atoi( buffer ) ){
  242.       case 300:
  243.         {
  244.           char* indexS = strchr( line+currentIndex, 'S' );
  245.           float Spos = atof( indexS + 1);
  246.           //          Serial.println("ok");
  247.           if (Spos == 30) {
  248.             penDown();
  249.           }
  250.           if (Spos == 50) {
  251.             penUp();
  252.           }
  253.           break;
  254.         }
  255.       case 114:                                // M114 - Repport position
  256.         Serial.print( "Absolute position : X = " );
  257.         Serial.print( actuatorPos.x );
  258.         Serial.print( "  -  Y = " );
  259.         Serial.println( actuatorPos.y );
  260.         break;
  261.       default:
  262.         Serial.print( "Command not recognized : M");
  263.         Serial.println( buffer );
  264.       }
  265.     }
  266.   }
  267.  
  268.  
  269.  
  270. }
  271.  
  272.  
  273. /*********************************
  274.  * Draw a line from (x0;y0) to (x1;y1).
  275.  * Bresenham algo from https://www.marginallyclever.com/blog/2013/08/how-to-build-an-2-axis-arduino-cnc-gcode-interpreter/
  276.  * int (x1;y1) : Starting coordinates
  277.  * int (x2;y2) : Ending coordinates
  278.  **********************************/
  279. void drawLine(float x1, float y1) {
  280.  
  281.   if (verbose)
  282.   {
  283.     Serial.print("fx1, fy1: ");
  284.     Serial.print(x1);
  285.     Serial.print(",");
  286.     Serial.print(y1);
  287.     Serial.println("");
  288.   }  
  289.  
  290.   //  Bring instructions within limits
  291.   if (x1 >= Xmax) {
  292.     x1 = Xmax;
  293.   }
  294.   if (x1 <= Xmin) {
  295.     x1 = Xmin;
  296.   }
  297.   if (y1 >= Ymax) {
  298.     y1 = Ymax;
  299.   }
  300.   if (y1 <= Ymin) {
  301.     y1 = Ymin;
  302.   }
  303.  
  304.   if (verbose)
  305.   {
  306.     Serial.print("Xpos, Ypos: ");
  307.     Serial.print(Xpos);
  308.     Serial.print(",");
  309.     Serial.print(Ypos);
  310.     Serial.println("");
  311.   }
  312.  
  313.   if (verbose)
  314.   {
  315.     Serial.print("x1, y1: ");
  316.     Serial.print(x1);
  317.     Serial.print(",");
  318.     Serial.print(y1);
  319.     Serial.println("");
  320.   }
  321.  
  322.   //  Convert coordinates to steps
  323.   x1 = (int)(x1*StepsPerMillimeterX);
  324.   y1 = (int)(y1*StepsPerMillimeterY);
  325.   float x0 = Xpos;
  326.   float y0 = Ypos;
  327.  
  328.   //  Let's find out the change for the coordinates
  329.   long dx = abs(x1-x0);
  330.   long dy = abs(y1-y0);
  331.   int sx = x0<x1 ? StepInc : -StepInc;
  332.   int sy = y0<y1 ? StepInc : -StepInc;
  333.  
  334.   long i;
  335.   long over = 0;
  336.  
  337.   if (dx > dy) {
  338.     for (i=0; i<dx; ++i) {
  339.       myStepperX.step(sx);
  340.       over+=dy;
  341.       if (over>=dx) {
  342.         over-=dx;
  343.         myStepperY.step(sy);
  344.       }
  345.       delay(StepDelay);
  346.     }
  347.   }
  348.   else {
  349.     for (i=0; i<dy; ++i) {
  350.       myStepperY.step(sy);
  351.       over+=dx;
  352.       if (over>=dy) {
  353.         over-=dy;
  354.         myStepperX.step(sx);
  355.       }
  356.       delay(StepDelay);
  357.     }    
  358.   }
  359.  
  360.   if (verbose)
  361.   {
  362.     Serial.print("dx, dy:");
  363.     Serial.print(dx);
  364.     Serial.print(",");
  365.     Serial.print(dy);
  366.     Serial.println("");
  367.   }
  368.  
  369.   if (verbose)
  370.   {
  371.     Serial.print("Going to (");
  372.     Serial.print(x0);
  373.     Serial.print(",");
  374.     Serial.print(y0);
  375.     Serial.println(")");
  376.   }
  377.  
  378.   //  Delay before any next lines are submitted
  379.   delay(LineDelay);
  380.   //  Update the positions
  381.   Xpos = x1;
  382.   Ypos = y1;
  383. }
  384.  
  385. //  Raises pen
  386. void penUp() {
  387.   penServo.write(penZUp);
  388.   delay(LineDelay);
  389.   Zpos=Zmax;
  390.   if (verbose) {
  391.     Serial.println("Pen up!");
  392.   }
  393. }
  394. //  Lowers pen
  395. void penDown() {
  396.   penServo.write(penZDown);
  397.   delay(LineDelay);
  398.   Zpos=Zmin;
  399.   if (verbose) {
  400.     Serial.println("Pen down.");
  401.   }
  402. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement