Mechanical Design and Machine Design

Mechanical Design and Machine Design

By Saheen Palayi | 30 March 2021 | FAB Academy 2021

week 9 Group assignment is to design a machine that includes mechanism+actuation+automation - build the mechanical parts and operate it manually - document the group project and your individual contribution - actuate and automate your machine - document the group project and your individual contribution

Idea

After a long discussion which lasted almost two days we finlay decided to do a dual pen core x-y plotter cnc machine. I worked with many cnc project before core x-y is new to me but the still has many similar components that I have known . we spitted the whole project works for the 8 members team like Mechanical deign , FAbrication ,electronics,Firmware+UI .etc... I was in charge of the Electronics and the Firmware+UI for the firmware and the UI, Hanani B joined to with me



 machine-week

The above picture shows how it will be connected to the computer after everything done. the first two,G code executer Graphical Interface and the cnc controller are my individual part that I'm contributing to the group project

So from this above diagram the controller which controls the motors of the mechanical assembly is connected to the Computer via a serial communication port.There will be a User interface software which talk to the machine through the serial port by using some special codes that both the machine controller and the software understand , that is called G-Code. So the software will send the g code to the controller board and the controller will drive the motors accordingly

Research

While the mechanical team was busy we decided to set the firmware with required electronics .I made a functional block diagram and explained to the whole team what I'm about to do


 machine-week

The above picture shows the functional block diagram of electronics components that we are using in this group project. The cnc controller that we Used is an arduino Board.Because its easy to set up lot of tutorials available and lot of firmwares too .the electronics is pretty simple. everything available in the lab as modular modules.

Components Required

Those are the required components for setting up the controller unit of the cnc But in FAB LAB Kerala we don't have all of them in the lab.so we decided to go with what the lab can provide. Instead of the Arduino UNO with CNC Shield lab has Arduino MEGA with Ramps Shield.It's ok any way its more than requires the Ramps Shield mainly used as 3D Printer's Control board.It can support 5 stepper driver .We only need two

We collected above components from the lab and tested by running a basic stepper arduino code and we found out the all A4988 driver available in the lab is not working


 machine-week

These are cheap chinese clone A4988 modules mostly fried out already.the chances of frying these type of stepper motor during projects are high luckily Fablab kochi has another type of stepper motor driver called DRV8825


 machine-week

Then we assembled everything.Assembling is very easy just like add-on cards of computers


 machine-week

The machine that we are building wasn't ready for electronics because it was not made that time so we desired to use an older mechanical x,y machine built by some visiters from other fab lab.


 machine-week

this machine was made based on the design by Jake Read. Nicely done design we found this mechanical part from our Fablab without the controller. Our first mission is to understand the firmware and if possible build one our own


 machine-week

We hooked up the x and y stepper motors to the control board and tested with a stepper motor library example called AcceleStepper I worked with this library before very easy to use with arduino.we used the lab power supply as the power source set to 12v and the motor driver programed as 1/16 micro stepping using the on board jumper of the Ramps shield



From the test we understand it moves each axis individually x,y or -x,-y directions.u can sse that from above video.but we want synchronized motion of both axis

CODE :-

                #include < AccelStepper.h>

                    #define dirPin A1
                    #define dirPin2 A7
                    
                    #define stepPin A0
                    #define stepPin2 A6
                    
                    #define motorInterfaceType 1
                    AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
                    AccelStepper stepper2 = AccelStepper(motorInterfaceType, stepPin2, dirPin2);
                    
                    int rslu = 0.1;
                    void setup() {
                      Serial.begin(9600);
                      pinMode(A2,OUTPUT);
                      pinMode(38,OUTPUT);
                     stepper.setMaxSpeed(4000);
                      stepper.setAcceleration(5000);
                      stepper.setCurrentPosition(0);
                       stepper2.setMaxSpeed(4000);
                      stepper2.setAcceleration(5000);
                      stepper2.setCurrentPosition(0);
                     digitalWrite(38,LOW);
                     digitalWrite(A2,LOW);
                    }
                    
                    void loop() {
                    mov(53000);
                    mov2(20000);
                    mov(-53000);
                    mov2(-20000)
                    
                    }
                    void mov (long int l)
                    {
                      stepper.setCurrentPosition(0);
                      long int stp =  l;
                      //  stepper.setSpeed(5000);
                    
                      stepper.moveTo(stp);
                      stepper.runToPosition();
                      Serial.println(stp);
                      Serial.println(stepper.currentPosition());
                    
                    }
                    void mov2 (long int l)
                    {
                      stepper2.setCurrentPosition(0);
                      long int stp =  l;
                      //  stepper.setSpeed(5000);
                    
                      stepper2.moveTo(stp);
                      stepper2.runToPosition();
                      Serial.println(stp);
                      Serial.println(stepper2.currentPosition());
                    
                    }
            
Enter fullscreen mode Exit fullscreen mode

Using AcceleStepper library some one modified for multisteppers to work them synchronously.and it can support upto 10 motors ata a time so we found the code on arduino examples and modified for us and tested it out



This time it worked as we expected,It calculate both distance and time to reach then shortest one will go at lower speed largest distance will be higher than the other axis.The code is given below

CODE :-

                    // MultiStepper.pde
                    // -*- mode: C++ -*-
                    // Use MultiStepper class to manage multiple steppers and make them all move to 
                    // the same position at the same time for linear 2d (or 3d) motion.
                    
                    #include < AccelStepper.h>
                    #include < MultiStepper.h>
                    
                    // EG X-Y position bed driven by 2 steppers
                    // Alas its not possible to build an array of these with different pins for each :-(
                    AccelStepper stepper1(AccelStepper::DRIVER, A0,A1);
                    AccelStepper stepper2(AccelStepper::DRIVER, A6,A7);
                    
                    // Up to 10 steppers can be handled as a group by MultiStepper
                    MultiStepper steppers;
                      long positions[2]; // Array of desired stepper positions
                    
                    void setup() {
                      Serial.begin(9600);
                     pinMode(A2,OUTPUT);
                      pinMode(38,OUTPUT);
                      // Configure each stepper
                     stepper1.setMaxSpeed(40000);
                      stepper1.setAcceleration(5000);
                      stepper1.setCurrentPosition(0);
                       stepper2.setMaxSpeed(40000);
                      stepper2.setAcceleration(5000);
                      stepper2.setCurrentPosition(0);
                    
                      // Then give them to MultiStepper to manage
                      steppers.addStepper(stepper1);
                      steppers.addStepper(stepper2);
                      digitalWrite(38,LOW);
                     digitalWrite(A2,LOW);
                    }
                    
                    void loop() {
                      mov(10000,10000);
                       mov(-10000,10000);
                        mov(-10000,-10000);
                         mov(10000,-10000);
                     
                    }
                    void mov(long x,long y){
                      positions[0] = x+y;
                      positions[1] = x-y;
                      steppers.moveTo(positions);
                      steppers.runSpeedToPosition(); // Blocks until all are in position
                    //    stepper2.setCurrentPosition(0);
                    //      stepper1.setCurrentPosition(0);
                    }
            
Enter fullscreen mode Exit fullscreen mode

The Firmware


After the testing we tried to understand how the whole cnc firmware works to make one our own . we get that 'It only drives the motors according to the g code instruction which is given by serial ports'. so we need a program which can receive the serial data and identify the g code then drive the motors to the co-ordinate given line by line in the g code


 machine-week

The above diagram is a flow chart of working structure of the firmware which we understand .we already got an basic firmware which is not using same motors and components we use but the g code is universal . so we decided to edit it we read all the code and understand how it works.The code is given below

Basic Firmware CODE :-

                    #include < Servo.h>
                        #include < Stepper.h>
                        
                        #define LINE_BUFFER_LENGTH 512
                        
                        const int penZUp = 40;
                        const int penZDown = 80;
                        
                        const int penServoPin = 6;
                        
                        const int stepsPerRevolution = 60; 
                        
                        Servo penServo;  
                        
                        Stepper myStepperY(stepsPerRevolution, 5,3,4,2);            
                        Stepper myStepperX(stepsPerRevolution, 11,9,10,8);  
                        
                        struct point { 
                          float x; 
                          float y; 
                          float z; 
                        };
                        
                        struct point actuatorPos;
                        
                        float StepInc = 1;
                        int StepDelay = 0;
                        int LineDelay = 50;
                        int penDelay = 50;
                        
                        float StepsPerMillimeterX = 100.0;
                        float StepsPerMillimeterY = 100.0;
                        
                        float Xmin = 0;
                        float Xmax = 100;
                        float Ymin = 0;
                        float Ymax = 100;
                        float Zmin = 0;
                        float Zmax = 1;
                        
                        float Xpos = Xmin;
                        float Ypos = Ymin;
                        float Zpos = Zmax; 
                        
                        boolean verbose = false;
                        
                        void setup() {
                          Serial.begin( 9600 );
                          
                          penServo.attach(penServoPin);
                          penServo.write(penZUp);
                          delay(200);
                        
                          myStepperX.setSpeed(200);
                          myStepperY.setSpeed(200);  
                        
                          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() 
                        {
                          delay(200);
                          char line[ LINE_BUFFER_LENGTH ];
                          char c;
                          int lineIndex;
                          bool lineIsComment, lineSemiColon;
                        
                          lineIndex = 0;
                          lineSemiColon = false;
                          lineIsComment = false;
                        
                          while (1) {
                        
                            while ( Serial.available()>0 ) {
                              c = Serial.read();
                              if (( c == '\n') || (c == '\r') ) {             
                                if ( lineIndex > 0 ) {                        
                                  line[ lineIndex ] = '\0';                   
                                  if (verbose) { 
                                    Serial.print( "Received : "); 
                                    Serial.println( line ); 
                                  }
                                  processIncomingLine( line, lineIndex );
                                  lineIndex = 0;
                                } 
                                else { 
                                  
                                }
                                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 );
                              }
                            }
                          }
                        
                        
                        
                        }
                        
                        
                        
                        void drawLine(float x1, float y1) {
                        
                          if (verbose)
                          {
                            Serial.print("fx1, fy1: ");
                            Serial.print(x1);
                            Serial.print(",");
                            Serial.print(y1);
                            Serial.println("");
                          }  
                        
                          
                          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) {
                                over-=dx;
                                myStepperY.step(sy);
                              }
                              delay(StepDelay);
                            }
                          }
                          else {
                            for (i=0; i=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(LineDelay);
                          
                          Xpos = x1;
                          Ypos = y1;
                        }
                        
                        
                        void penUp() { 
                          penServo.write(penZUp); 
                          delay(LineDelay); 
                          Zpos=Zmax; 
                          if (verbose) { 
                            Serial.println("Pen up!"); 
                          } 
                        }
                        void penDown() { 
                          penServo.write(penZDown); 
                          delay(LineDelay); 
                          Zpos=Zmin; 
                          if (verbose) { 
                            Serial.println("Pen down."); 
                          } 
                        }
                
Enter fullscreen mode Exit fullscreen mode

We found the motor coordinates function in the code replaced with ours which made by using 'AcceleStepper.h' library


Edited Firmware CODE :-

                    #include < Servo.h>
                        //#include < Stepper.h>
                        #include < AccelStepper.h>
                        #include < MultiStepper.h>
                        AccelStepper stepper1(AccelStepper::DRIVER, A0,A1);
                        AccelStepper stepper2(AccelStepper::DRIVER, A6,A7);
                        MultiStepper steppers;
                        
                        #define LINE_BUFFER_LENGTH 512
                        
                        const int penZUp = 40;
                        const int penZDown = 80;
                        
                        const int penServoPin = 6;
                        
                        const int stepsPerRevolution = 60; 
                        
                        Servo penServo;  
                        //
                        //Stepper myStepperY(stepsPerRevolution, 5,3,4,2);            
                        //Stepper myStepperX(stepsPerRevolution, 11,9,10,8);  
                        
                        struct point { 
                          float x; 
                          float y; 
                          float z; 
                        };
                        
                        struct point actuatorPos;
                        
                        float StepInc = 1;
                        int StepDelay = 0;
                        int LineDelay = 50;
                        int penDelay = 50;
                        
                        float StepsPerMillimeterX = 160.0;
                        float StepsPerMillimeterY = 160.0;
                        
                        float Xmin = 0;
                        float Xmax = 100;
                        float Ymin = 0;
                        float Ymax = 100;
                        float Zmin = 0;
                        float Zmax = 1;
                        
                        float Xpos = Xmin;
                        float Ypos = Ymin;
                        float Zpos = Zmax; 
                        
                        boolean verbose = true;
                          long positions[2]; // Array of desired stepper positions
                        
                        void setup() {
                          Serial.begin( 9600 );
                        
                        
                           pinMode(A2,OUTPUT);
                          pinMode(38,OUTPUT);
                          // Configure each stepper
                         stepper1.setMaxSpeed(4000);
                          stepper1.setAcceleration(5000);
                          stepper1.setCurrentPosition(0);
                           stepper2.setMaxSpeed(4000);
                          stepper2.setAcceleration(5000);
                          stepper2.setCurrentPosition(0);
                          steppers.addStepper(stepper1);
                          steppers.addStepper(stepper2);
                          digitalWrite(38,LOW);
                         digitalWrite(A2,LOW);
                          
                          penServo.attach(penServoPin);
                          penServo.write(penZUp);
                          delay(200);
                        
                        //  myStepperX.setSpeed(200);
                        //  myStepperY.setSpeed(200);  
                        
                          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() 
                        {
                          delay(200);
                          char line[ LINE_BUFFER_LENGTH ];
                          char c;
                          int lineIndex;
                          bool lineIsComment, lineSemiColon;
                        
                          lineIndex = 0;
                          lineSemiColon = false;
                          lineIsComment = false;
                        
                          while (1) {
                        
                            while ( Serial.available()>0 ) {
                              c = Serial.read();
                              if (( c == '\n') || (c == '\r') ) {             
                                if ( lineIndex > 0 ) {                        
                                  line[ lineIndex ] = '\0';                   
                                  if (verbose) { 
                                    Serial.print( "Received : "); 
                                    Serial.println( line ); 
                                  }
                                  processIncomingLine( line, lineIndex );
                                  lineIndex = 0;
                                } 
                                else { 
                                  
                                }
                                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 );
                              }
                            }
                          }
                        
                        
                        
                        }
                        
                        
                        
                        void drawLine(float x1, float y1) {
                        
                          if (verbose)
                          {
                            Serial.print("fx1, fy1: ");
                            Serial.print(x1);
                            Serial.print(",");
                            Serial.print(y1);
                            Serial.println("");
                          }  
                        
                          
                          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);
                        
                          
                            
                          mov(x1,y1);// sending the co-ordinates 
                          
                          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) {
                        //      Serial.print("x:");
                        //      Serial.println(sx);
                        //      myStepperX.step(sx);
                              over+=dy;
                              if (over>=dx) {
                                over-=dx;
                        //        Serial.print("y:");
                        //      Serial.println(sy);
                        //        myStepperY.step(sy);
                              }
                              delay(StepDelay);
                            }
                          }
                          else {
                            for (i=0; i< dy; ++i) {
                        //      Serial.print("y:");
                        //      Serial.println(sy);
                        //      myStepperY.step(sy);
                              over+=dx;
                              if (over>=dy) {
                                over-=dy;
                        //        Serial.print("x:");
                        //      Serial.println(sx);
                        //        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(LineDelay);
                          
                          Xpos = x1;
                          Ypos = y1;
                        }
                        
                        
                        void penUp() { 
                          penServo.write(penZUp); 
                          delay(LineDelay); 
                          Zpos=Zmax; 
                          if (verbose) { 
                            Serial.println("Pen up!"); 
                          } 
                        }
                        void penDown() { 
                          penServo.write(penZDown); 
                          delay(LineDelay); 
                          Zpos=Zmin; 
                          if (verbose) { 
                            Serial.println("Pen down."); 
                          } 
                        }
                        
                        
                        void mov(long x,long y){
                          positions[0] = x;
                          positions[1] = y;
                          steppers.moveTo(positions);
                          steppers.runSpeedToPosition(); // Blocks until all are in position
                        //    stepper2.setCurrentPosition(0);
                        //      stepper1.setCurrentPosition(0);
                        }
                
Enter fullscreen mode Exit fullscreen mode

The above code was mde for the normal x-y cartesian plotter that we are experimenting.then we tested it out. The machine doesn't have any End effector mechanism so I taped a pencel on it


 machine-week

Now I need a g code executer ,I've done cnc plotter project before so I have g code executer software in my PC Also have some examples g code on my pc


 machine-week

This executer is built on an open source platform called Processing .I place a pice of paper under the cnc and homed manually to a corner were x is 0 and y is 0. Then plugged to computer and connected to the executer Software and turned ON the main power.It starts draw the gcode file have some problems with end effector.but its ok for testing


 machine-week

After a long trials got something meaningful on the paper. I was given Gcode file of a Poop emoji draws well so the Firmware was a success!.now we have to create the firmware to the core x-y machine that we are making

Core XY Kinematics

The core XY mechanism is different from other type of mechanism like cartesian both motors required to control each individual axis if we only rotate one motor the head will go + or - diagonally

If we rotate the motor at same direction it moves alongside x axis ,but if the motors in opposite direction the head will move alongside y axis.We found more about the Core XY from the corexy.com website


 machine-week

According to the corexy-theory We have an equation for the Motor steps from X Y coordinates given by G CODE . You can see the maths from the above picture.To modify the firmware Abel Tomy helps me with the math which was very simpler than I thought


          Motor A Steps = X+Y // from ΔA=Δx+ΔY
          Motor B Steps = X-Y // from ΔB=ΔX-ΔY
                

According to the match I modified the Firmware for the core xy mechanism

Edited Firmware CODE :-

                  #include < Servo.h>
                      //#include < Stepper.h>
                      #include < AccelStepper.h>
                      #include < MultiStepper.h>
                      AccelStepper stepper1(AccelStepper::DRIVER, A0,A1);
                      AccelStepper stepper2(AccelStepper::DRIVER, A6,A7);
                      MultiStepper steppers;
                      
                      #define LINE_BUFFER_LENGTH 512
                      
                      const int penZUp = 40;
                      const int penZDown = 80;
                      
                      const int penServoPin = 6;
                      
                      const int stepsPerRevolution = 60; 
                      
                      Servo penServo;  
                      //
                      //Stepper myStepperY(stepsPerRevolution, 5,3,4,2);            
                      //Stepper myStepperX(stepsPerRevolution, 11,9,10,8);  
                      
                      struct point { 
                        float x; 
                        float y; 
                        float z; 
                      };
                      
                      struct point actuatorPos;
                      
                      float StepInc = 1;
                      int StepDelay = 0;
                      int LineDelay = 50;
                      int penDelay = 50;
                      
                      float StepsPerMillimeterX = 160.0;
                      float StepsPerMillimeterY = 160.0;
                      
                      float Xmin = 0;
                      float Xmax = 100;
                      float Ymin = 0;
                      float Ymax = 100;
                      float Zmin = 0;
                      float Zmax = 1;
                      
                      float Xpos = Xmin;
                      float Ypos = Ymin;
                      float Zpos = Zmax; 
                      
                      boolean verbose = true;
                        long positions[2]; // Array of desired stepper positions
                      
                      void setup() {
                        Serial.begin( 9600 );
                      
                      
                         pinMode(A2,OUTPUT);
                        pinMode(38,OUTPUT);
                        // Configure each stepper
                       stepper1.setMaxSpeed(4000);
                        stepper1.setAcceleration(5000);
                        stepper1.setCurrentPosition(0);
                         stepper2.setMaxSpeed(4000);
                        stepper2.setAcceleration(5000);
                        stepper2.setCurrentPosition(0);
                        steppers.addStepper(stepper1);
                        steppers.addStepper(stepper2);
                        digitalWrite(38,LOW);
                       digitalWrite(A2,LOW);
                        
                        penServo.attach(penServoPin);
                        penServo.write(penZUp);
                        delay(200);
                      
                      //  myStepperX.setSpeed(200);
                      //  myStepperY.setSpeed(200);  
                      
                        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() 
                      {
                        delay(200);
                        char line[ LINE_BUFFER_LENGTH ];
                        char c;
                        int lineIndex;
                        bool lineIsComment, lineSemiColon;
                      
                        lineIndex = 0;
                        lineSemiColon = false;
                        lineIsComment = false;
                      
                        while (1) {
                      
                          while ( Serial.available()>0 ) {
                            c = Serial.read();
                            if (( c == '\n') || (c == '\r') ) {             
                              if ( lineIndex > 0 ) {                        
                                line[ lineIndex ] = '\0';                   
                                if (verbose) { 
                                  Serial.print( "Received : "); 
                                  Serial.println( line ); 
                                }
                                processIncomingLine( line, lineIndex );
                                lineIndex = 0;
                              } 
                              else { 
                                
                              }
                              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 );
                            }
                          }
                        }
                      
                      
                      
                      }
                      
                      
                      
                      void drawLine(float x1, float y1) {
                      
                        if (verbose)
                        {
                          Serial.print("fx1, fy1: ");
                          Serial.print(x1);
                          Serial.print(",");
                          Serial.print(y1);
                          Serial.println("");
                        }  
                      
                        
                        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);
                      
                        
                          
                        mov(x1,y1);// sending the co-ordinates 
                        
                        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) {
                      //      Serial.print("x:");
                      //      Serial.println(sx);
                      //      myStepperX.step(sx);
                            over+=dy;
                            if (over>=dx) {
                              over-=dx;
                      //        Serial.print("y:");
                      //      Serial.println(sy);
                      //        myStepperY.step(sy);
                            }
                            delay(StepDelay);
                          }
                        }
                        else {
                          for (i=0; i< dy; ++i) {
                      //      Serial.print("y:");
                      //      Serial.println(sy);
                      //      myStepperY.step(sy);
                            over+=dx;
                            if (over>=dy) {
                              over-=dy;
                      //        Serial.print("x:");
                      //      Serial.println(sx);
                      //        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(LineDelay);
                        
                        Xpos = x1;
                        Ypos = y1;
                      }
                      
                      
                      void penUp() { 
                        penServo.write(penZUp); 
                        delay(LineDelay); 
                        Zpos=Zmax; 
                        if (verbose) { 
                          Serial.println("Pen up!"); 
                        } 
                      }
                      void penDown() { 
                        penServo.write(penZDown); 
                        delay(LineDelay); 
                        Zpos=Zmin; 
                        if (verbose) { 
                          Serial.println("Pen down."); 
                        } 
                      }
                      
                      
                      void mov(long x,long y){
                        positions[0] = x+y;// from ΔA=Δx+ΔY
                        positions[1] = x-y;// from ΔB=ΔX-ΔY
                        steppers.moveTo(positions);
                        steppers.runSpeedToPosition(); // Blocks until all are in position
                      //    stepper2.setCurrentPosition(0);
                      //      stepper1.setCurrentPosition(0);
                      }
              
Enter fullscreen mode Exit fullscreen mode

The mechanical team almost finishing the machine and not done completely.so we can't test the firmware that we made for it


End Effector

The end effector mechanism was designed by Abhinav Ajithit has 2 pen holders controlled by one single servo motor

Back to Top Back to top