Week 9: Machine Design: PNASH

The group assignment of this week is to actuate and automate our machine and to document the group project and individual contributions.


Presentation Slide



Presentation Video


Click here to access the presentation page


Plan for the Week




Task Splitage



                                                                                                                                   
Member
Task
Pallab ShresthaMechanical Design: Overall
Abhinav AjithEnd Feed Design
Saheen PalayiElectronic Design
Jai HananiProgramming
Alfia MProject Management
Abel TomyShape Optimization of parts
Neveena HencyDocumentation & Planning
Ananthakrishnan P BDocumentation



What should we do this week?


This week is the week where we use our core skills and do team work to make a machine. We brainstormed several ideas for the group project which included: Selective White Board Eraser, Waste Picking Robot, Table Cleaner, Juicer etc. and fe had a good and healthy discussion around what project to do to learn most from the assignment as well as from team members and also finish it on time. Good that we had started this discussion early before the assignment week. Then we divided ourselves according to our strength and agreed on sharing what we learned as we move on which will make effecient use of time. Here is a picture showing our brainstorming session with the help from our instructors.

Group Discussion



Though we had many discussions around assignment, and as recommended by instructors, we selected CNC plotter as our main machine to be designed We selected core xy as the main mechanism. The main reason to select this mechanism was we focused more on learning more than inventing something new. Our machine will designed considering following factors.

  • Functionality.
  • Time for fabrication.
  • Design for cost.
  • Availability of parts.



Inspiration


Since we are from Superfablab Kerala, we were introduced to the machine week based on work done by Pablo Nuñez, Epifanio Lorenzo, Yuichi Tamiya, Apeksha Bochare, Pradnya Shindekar during Bootcamp in our lab. The machine is a X-Y Plotter based on Platonic Gantry Design, it's linear motion is contrained with roller bearings, motion controlled by NEMA 17 stepper motor, laser cut acrylic frame with 3D printed parts. The machine had perfect clearances and accuracy so we tried to test the working of the machine at first and even though it took some time to get used to it but with help of our team members we made it to work. The machine inspired us to settled with tabletop based horizonal CNC machine based on Core XY Mechanism. The image of the machine is given below

CoreXY Plotter




CoreXY Mechanism


Talking about Core XY, First of all Thank you to Ilan E. Moyer for the great documentation from which we could learn a lot. Please refer to this documentation for the detail theory

CoreXY Mechanism





Here the motion of the pen will be:
  • Horizontal when the motors rotate in the same direction.
  • Vertical when the motors rotate in opposite directions.
  • Diagonal if only one motor rotates.


Maths behind Core XY

If we rotate motor A counter-clockwise by an amount ∆A then the pen carriage will move horizontally to the right by an amount ∆X and vertically upwards by an amount ∆Y. The equation for this is:

∆A = ∆X + ∆Y --> 1
If we rotate motor B counter-clockwise by an amount ∆B then the pen carriage will move horizontally to the right by an amount ∆X and vertically down by an amount ∆Y. The equation for this is:

∆B = ∆X - ∆Y --> 2
The reason for the ∆Y sign/direction change is that the two timing-belts are moving in opposite directions... the timing-belt for motor A is being fed towards the pen which lets the pen to move upwards, whereas the timing-belt for motor B drags the pen downwards.

Horizonal Motion:

Rearranging equations (1) and (2) we get:

∆Y = ∆A - ∆X -->3 
∆Y = -∆B + ∆X --> 4

Equating equations (3) and (4) we get:
∆A - ∆X = -∆B + ∆X --> 5

From which:
∆X = (∆A + ∆B)/2 -->6

Translating: the pen moves horizontally when both motors rotate in the same direction

Vertical motion:
Rearranging equations (1) and (2) we get:
∆X = ∆A + ∆Y --> 7
∆X = ∆B - ∆Y -->8

Equating equations (7) and (8) we get:
∆A + ∆Y = ∆B - ∆Y --> 9

From which:
∆Y = (∆A - ∆B)/2 --> 10
Translating: the pen moves vertically when the motors to rotate in opposite directions and Collectively equations (6) and (10) infer diagonal movement if only one motor rotates.


Team Work


We divided the team into five groups:

  • Mechanical Design
  • Fabrication
  • Electronics and programming
  • Material and management
  • Documentation


We Went through various process from designing, fabricating, testing, assembly, and most importantly prototyping a lot of mini parts as per designs. As a team we first discussed will all about how to make it. For the driving system, timing belts with stepper motor was confirmed. Then about the movement we were discussing what to use for the movement were we were searching for the options like

  • Laser cut frames
  • Steel rods sliders
  • Linear rails
  • Metal sections


When we were discussing our instructor Jogin Francis asked why don't you use aluminium extrusion. Then we tried searching for those in the lab but could not find one. Design team with material team went to search for the aluminium extrusion section of size 25mm X 50mm. We confirmed that there was not irregularity over the length and its strength. The reason we chose aluminium extrusion is that it was cheaper and it was locally available, since it was made by extrusions the section would have a dimensional consistency throughout its length and another point to note is that aluminum is a soft metal so common cutting and drilling tools can be used in the material. However, we should take care of it while handling during assembly and machining as concentrated force may damage the surface or whole shape. But it was lightweight and OK for our group project. Along with the help of fabrication team, we figured out the calculated space for stepper motor and cut the parts into 5 pieces 4 for sides and one for x-gantry.

Machine size: 1110mm(x) * 1060mm(y) * 175mm(z)
Bed size: 766mm(x) * 756mm(y) (Updated after designing)

Now we all divided our works and done our part and then met at assembly. Where all the parts assembled and mechanically tested. and boards were installed and then tested.

Mechanical Design: Mechanism: Pallab Shrestha


First thing to do was take exact measurements of the extrusion and then make a parametric extrusion which I can copy for the different sides and gantry.



We had 2 options to choose between

  • Linear rails
  • Make our own sliders


We decided to make our own sliders because linear sliders were expensive and it was unavailable in our lab for the length that we targeted and what we had was shorter ones. So moving on with designing slider first y direction slider was focused. I then followed the following process.

  • Bearing dimension were measured
  • Total of 6 bearings, 3 will be placed vertically constraining z motion and rotation about x direction, 3 will be placed horizontally constraining x movement and rotation about z direction which leaves the y direction movement free as rotaion about y direction will be contrained by the gantry on the other side.
  • As fabrication team was testing the inserts to be used, The gap for inserting the inserts for the hot rod as well.




The main problem for this slider was that while assembly was that the extrusion and the bearing should fit perfectly. IF loose it would giggle and if tight, it would need a lot of force to drive it and while i was thinking about ways to add flextures in it, our instructor Jogin Francis suggested to refer the slider that was used in Instructors bootcamp 2020 in Fablab Kochi. It was great design and so impressed with the simple yet effective design. Then I tried to take a reference of that design and work on ours. While doing so, first thing to do was make couple of prototypes for flextures

Flexture for sliders:

For making the slider first thing to consider was the possibility of surface irregularity and the tolerance of the part that we are about to create. So a flexture component has to be made or there would be a wiggle while movement or if not, it would be very tight assembly. We made a flexture which can flex but also can limit the displacement as it is applied, other forces should not break. version 1: with connector on both sides version 2: with connector on only one side We tried different materials and we found which is accurate for our machine.

  • We tested in acrylic which is cut out using laser cutter.
  • We used PLA (Poly lactic acid) which was 3D Printed from Ultimaker.


We found that using PLA was more accurate for our design because while we tried acrylic it tend break because it was more brittle compared to PLA. The acrylic part broke while we were assembling it with the aluminium extrusion . Then following samples were made.



Learnings

  • Acrylic are brittle and are relatively harder to flex than 3D printed parts.
  • If you have flextures with two arms it is hard to flex as when one arm is compressed one is in tension and becomes similar to having wide arm with compared to flex but stress concentrated highly on the join where is connected to main body. However you can use it according to your design requirement.
  • It is better to have limit for the movement as if moved a lot , it might break the flexure.


After the flextures were finalized, 2 plate design was made where the central bearing of horizontal plate would go through the vertical plate and both will be assembled by m3 nuts. in 4 places.



Similarly, the extrusion for the x-gantry should be included into design as this part was also holding it. then he thought that will clamp it via two brackets with the extrusion sandwiched in middle. Then the design files were sent to the fabrication team and first it was tested.



While the testing was going on, the bracket for clamping in each corners had to be made, housing for motors and along with that, brackets two brackets on the opposite ends had to be designed so as to hold pulleys for timing belts.

  • Bracket for corners: It is a 90 degree bracket which will be fitted by M5 nuts and bolts. total 4 and 2 on each sides.
  • Bracket housing motors: 4 servo motor screws on the top and 4 with two on each side aligning the corner bracket. Both are of different heights due to different levels of the timing belts.
  • Bracket for holding two pulleys of timing belt: Both are complementing stepper motor and placed opposite to it. Each one can fit two pulleys with washers and be clamped to the main frame. Long M5 bolt is taken as shaft inserted from below. It is clampedto the main frame by two M5 bolts and nuts




Then after everything is tested and designed, It was transferred to the fabrication team and was left for print. After everything was printed, I shared the assembly process and along with Abel from the fabrication team, and help from Saheen from electronics team, we assembled the main frame with sliders. Then he came to realize that we did one mistake!!! when the gantry moves, the changing length should be linear which means that the timing belts should be straight, not in an angle. Thats why I added another correction bracket above the corner brackets which you can see below.



Then for the X-direction slide. vertical was modifies as the top part was not needed and the upper horizontal was added on the other side as well constraining the rotation about x direction. Here I communicated with Abhinav Ajith who was handing the end effect for the clamping positions. he left two spots with slots for inserting nuts on the part. Finally, for clamping the timing belts, I added a block of plastic which would be tighened by M3 nuts and bolts. and added corrugated surface below it so that the clamping would be more secure. Similarly for the other side also added another part in between which will support the structure as well as be used to clamp the wires.



Finally, Then the machine had to be tested and handed over to the electronics team, when the legs were installed at last however the design was inspired by the legs of shopbot which can be adjusted with the help of nuts.






Design of End Effector: Abhinav Ajith


So his task for this week is to design an end feed mechanism to hold multiple pens/tools. Since I completed my major in Mechanical Engineering it was obvious that I should handle this interesting part. My friends Abel and Pallab were in charge of the basic frame and gantry mechanism while I had to complete the end feed mechanism. In layaman terms, the end feed mechanism in charge of moving the pen up/down depending upon the GCode from the microprocessor. To make it interesting, I thought of making a dual pen holding mechanism where one pen will touch the ground and other won't touch the ground when activated. The mechanism can easily be done with help of a single servo motor. To start with I had researched about various pen carriage mechanisms which included rail mechanism, magnetic type, spring loaded solenoid type etc.

Trial 1: Dual Rail - Single Pen Carriage Mechanism

This is the most commonly used pen holding mechanism for generic CNC plotters. The mechanism is simple, there are 2 rails were a pen holder will be attached to. A servo arm attached to the base of the carriage pushes the pen holder thereby moving the pen up and down. The rails ensure that there are deflection to the motion of pen and springs ensure that proper reaction force is provided to the holder to keep it at the right position. The image given below shows a typical dual rail single pen carriage mechanism



So without further adeiu, I had tried to design similar mechanism. My only goal was to design and 3D print the mechanism so that I could understand it's motion, the mistakes that I had made and to learn from it. So I had used Fusion 360 to complete and 3D design and familiarized with various parts. Here comes the irony, after I had designed the basic mechanism, I thought of trying out a new design which comprises of 2 pen holders sliding on individual rails controlled by a single servo. The idea was actually put forward by my instructor so I thought why not I could try out this one. In the mean time, I had volunatarily removed the multi tool changing mechanism as I found it to be complex to be completed within a span of 1 week. So here comes the Trial 2: Dual Carriage Mechanism.

Trial 2: Dual Carriage Mechanism

As suggested by my instructor, I tried to design a dual carriage mechanism which hosts 2 pen holders fixed in independent rails. In addition each holder is allowed to freely slide along a gap which restricts the any rotational motion of the slider. A single servo is responsible for the actuation of both pen holders during which one pen holder will be touching the ground plane while other holder won't be. Additional springs maybe provided for better actuation. Since this mechanism is kinda novel my first goal was to design a basic model of the mechanism and print it so that I could learn from my mistakes to make the final model perfect. My fablab had given me the permission to test out new designs by 3D printing it rather than testing it virtually. Similar to the previous one I had designed the dual carriage mechanism in Fusion 360 and the image will be provided below.



After completing the model, I had exported the bodies as STL files and had sliced using Cura to 3D print the second trial prototype. Since this is a trial print and inorder to reduce material wastage, I had provided only 10% infill with 0.8 wall thickness, layer height of 0.3mm and grid pattern. Since the sliders were oriented vertically, I had provided supports for the same The whole print was expected to be finished in 5.5 hrs but in reality it took a lot of time. The main motive of the print was to test the mechanism so I didn't print the pen holders at first inorder to reduce the material. Next step was to install the M3 Threaded Round Insert to the holes for holding the servo motor. Here comes my first mistake, during designing I had gave different values for the position of M3 Screw holes from the center of servo. The mistake was made due to fact that the servo motor shaft is not exactly placed in the middle of the servo motor, but it was placed towards the top of the motor. Anyway, since the dimensions of the slot for the servo motor was perfect, I could easily fix the servo motor with 1 M3 Nut. Later I attached the servo arm and end feed mechanism is 50% completed. The next step is to cut the rod and add the rails to the base.



The next step is to fabricate the individual rails, for this I had savaged a 6.36mm dia steel rod from the lab and had reduced the length to the required amount using an angle cutter. My friend Saheen taught me about the safety aspects while using the cutting machine. Once the rods were cut, they were inserted to the respective slots by press fitting. Due to shrinkage, we had to widen the hole using a drilling machine (6.5mm bit). The process went out to be successful but due to my mistake, I forgot to add a stopper to one side of the slot so that the rail can be constrained.



Based on the lessons learnt from Trial 2, I decided to design the final prototype of the end feed. Due to our commitment to finish the prototype of the machine within 1 week, we even worked in weekends which helped me to refine my idea based on constructive criticizm from various team members. It had also given rise to collabrative design ideas from the team building the basic frame and me who is building the end feed.

Trial 3 (Final): Dual Pen Carriage Mechanism

Abhinav had made the following changes to the final design to accomodate the lessons I had learnt from previous prototypes:

  • Provided fillets to the corners to prevent failure of the base
  • Provided clearance to the holes which host the rails so that the drilling process post print can be prevented
  • Verfied the position of the servo shaft and arranged the slot present in pen holder/slider to prevent the shaft from suprassing the limits
  • Provided clearance for the sliding motion of pen holder for sufficient actuation during the motion
  • Added end stop to one end of hole housing the rail and provided provision for removable closure at other end which can be attached by M3 Nuts
  • Modified position of the servo mount holes so that (D1=D2) the servo motor can be mounted without any play
  • For final prototype, I added 30% infill with support (printed keeping the model vertically) and increased wall thickness to 1.5mm
  • Made a simple pen holder which can host upto 17mm dia pen and can be tightened using M3*30mm nuts with threaded insert
  • Decreased the gap between 2 rails according the dimension of the servo arm
  • Provided a path for servo wires by adding a pocket to the rear side of the model




Hurray, this is the assembled end feed mechanism of our Core XY Plotter which was 3D Printed using Ultimaker 2+.



Attaching End feed to the Gantry Mechanism

Here comes the most interesting part of the whole process, since I had completed the end feed mechanism its now time to attach it to the gantry mechanism. In the mean time I had seen my friends assembling the rest of the mechansim. Since we didn't have enough time left and I had to leave early for the break, my friends attached the end feed mechanism that I had made to the gantry mechanism. My friend Pallab took a lot of effort to modify the gantry mechanism to fit my end feed (like aligning the M3 Holes) and finally it was attached as expected. The below video shows the testing of end feed mechanism without servo actuation. Since the servo for end feed had to be tested by my friend Saheen, we have manually placed the pen in the holder and checked the working of the whole mechanism.



Electronics: Saheen Palayi and Jai Hanani


While the mechanical team was busy we decided to set the firmware with required electronics. 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

  • Arduino MEGA x1
  • Ramps 1.4 Shield
  • A4988 Stepper Drivers x2
  • NEMA17 Stepper Motor x2
  • Servo motor (0-180 deg) x1
  • 12v 5A Power Supply


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. 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. Then we assembled everything.Assembling is very easy just like add-on cards of computers.



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. 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 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.

        
            #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());
            
            }
    

    


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

    
        // 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);
        }



    


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 We already got an basic firmware which is not using same motors and components we use but the g codes is universal . so we decided to edit it we read all the code and understand how it works.The code is given below

    
        #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."); 
          } 
        }




    


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

    
        
        #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);
        }

    


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, Now we 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.



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, 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. According to the corexy-theory We have an equation for the Motor steps from X Y coordinates given by G CODE . To modify the firmware Abel Tomy helps me with the math which was very simpler than I thought 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);
        }

    




Testing the machine


Management: Alfia M



Her role for this week was to ensure the fabrication was done right and ensure the supply of equipments for the team and keep a track record of everything we used from the inventory of the lab. She started off by doing test cuts and prints to check the feasibility of the designs. This included a lot of 3D printing, laser cutting and designing. I also made a sheet to record the components list. Fabrication also involved ensuring getting components not available in the lab from outside. I was helped with this by my friends Ananthu, Abel and also Naveena and Pallab. Once the test cuts, prints and trials were done, we had the actual components printed, cut and put together to form the frame of the structure. when this part was done, each of my team mates, did their roles in electronics, design, fabrication and documentation to get the final structure complete and ready to be used.






Topology/Shape Optimization: Abel Tomy



Mathematical method that optimizes material layout within a given design space, for a given set of loads, boundary conditions and constraints with the goal of maximizing the performance of the system.Saves lot of time in material saving and 3D printing time. He was involved in topology optimisation of various parts.





Documentation and Planning



Neveeena Hency, Ananthakrishnan P B and Abhinav Ajith were involved in the documentation of the whole assignment and it wouldn't be possible wihout their effort.



Click here to download the Design Files


Click here to download the Code