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


 machine-week

here is a picture taken by Abhinav during our Brain storming discussion you can see that I'm over exited in the picture.

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 design and not done completely.so we can't test the firmware that we made for it


 machine-week

I joined them to help to see what I can do. Here is the picture that shows everyone busy this week (Taken by Alfia)


End Effector

The end effector mechanism was designed by Abhinav Ajith. It has 2 pen holders controlled by one single servo motor positioning each angle for controlling each Pen up and Down motion.



I was helping him to Prototype the End effector Then we assembled together .Check Abhinav's Machine Design week Documentation for more details. Then we tested It's operation by running a servo Example code using the Arduino platform.

CNC Shield

All of my group was busy in the week for completing the Mechanical design so its all in progress as an electronics guy in the Team What I could have done is to do the electronics parallel .We already finished the minimum electronics hardware setup to run the machine any way so I've got time to build a CNC PCB for our Machine.


 machine-week

I built this block diagram to get a better understanding about what we are gonna make. We are decided to build a CNC Shield on the top of the arduino UNO to interface those two stepper motor drivers and the servo. Building entire CNC PCB is little difficult and we don't have time for that.


 machine-week

So I build the schematic and the board in fusion 360 . the reffrence of the Motor driver circuit was taken from the Ramp 1.4 3D Printer shield schematic diagram.


 machine-week

Here is the final design of the board looks like . I do have small problem to make it happen, It's one sided so the motor driver will be sitting on a adapter which should be soldered from the bottom side of the board. I've decided to use the revetting techniques to solve the problem.


 machine-week

I milled the board out using the Modella Milling machine from our lab and also did the through holes for the rivets after some adjustments in the design.


 machine-week

These are the Punches used for rivetting in our lab. The small one is a kind of pointy center punch that helps to make a flanch forming curve on the rivet. And the big one is a flat type punch helps to finish the flanch that formed using the pointy center punch.


 machine-week

we use the tweezer to put the rivets in place then used the punches to complete the riveting process. My group mate pallab shresthahelps me to rivet the board .


 machine-week

Here is the puture of the board after we finishing the revetiing process. yea right that's a lot of rivets hope it's works


 machine-week

Then I grabed the componnets from inventory room and soldered everything in place. You can see the male and female heder pins are not SMD and the picture also shows why the revets are used in this design.


 machine-week

So,The CNC sheild is all set to test as next step we have to complete the Mechanical assemply of our core xy machine.

Mechanical Assembly

We almosted finished the Electronics hardware and firmware, And the mechanical team completed the design and testing now its time for the production and assembly.


 machine-week

During the assembly we faced some issues of missiglignment becouse we dont have any drill press to drill streight and perpendicular hole . but with some skills and instructors help we re assembled the missalgned fram in to a proper alignment.


 machine-week

We also works at night at the lab to finish the mechanical assembly. It was totally new and awesome experiance working in a team.


 machine-week

Here is the picture of the machine after the mechanical asssembly all done. Also attached two motors and the end effector servo in it. For more about mechanical Design , testing and assembly see Pallab's and Abel's Mchine week documentation



We check the actuations by moving with our hand with out any electronics attached. we can feel ther movement during this test also its better to understand if any truble in the movement.

corexy - Testing

So far the week is almost over and everyboady wants to go back to home becouse of the break happening during machine weeks. Tht's why we decided to go a test ploting without proper electronics assembly.


 machine-week

we set-up a simple electronics hardware just to power those motor this way we can test the CoreXY mechanism.we didnt use the sheild we build during the session instead we chose the ramp sheild in-order to avoid any Electrical error if there is any.



After some effort of few hours we managed to draw a Square as our machine's first baby step. the code used for drawing the square isnt a Gcode based firmware.Instead we created a coustome code to draw the square and testing the coreXY equation. we did not connect the pen up and dow servo at this time.


 machine-week

Then we implemented the coreXY firm ware that we made before and drew the poop emoji. see the above picture. It was so small to our machine and it's messy becouse of there is no pen up and down motion.



here is the video of our machine and us trying to draw a lamborgini image on the table . Turns out it was a half success.

Machine week Review

I wasn't at the lab while we are having the wmachine week review .So Pallab and Abel joined from the LAB to show and expline our eforts.



Here is the video snipet of our machine week review we named our machine P- NASH .Unmute for the sound . For the orginal see this vimeo link

References


Downloads

Back to Top Back to top