Fab Lab

Mexico City

Mechanical and Machine Design (Group Assignment)

Objective:

  • 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

 

This week is collaborative effort with all our fellow students of the Node.

In this case, we as Ciudad de México FabLab, as a team, decided to try designing a time lapse rail for a Smart phone, whether is an iPhone or Android, and integrate  a myriad of printed, cutted and existent pieces.

The main background is based on a typical rail with an automated system.

Research:

The original design, is a time-lapse rail with a timing belt as a dolly that moves along an axis, and the camera is attached to an articulated monopod; this raw model was developed in SOLIDWORKS®, as a simple short rail, translated from STEP to Rhino and IGES files, for compatibility.

Main specifications are:

  • Nema 17 External 48mm Stack 0.4A Lead 2mm/0.07874" Length 300mm
  • Nema 17 Bipolar 1.8deg 45Ncm (64oz.in) 1.68A 2.8V 42x42x48mm 4 Wires
  • Single wall corrugated cardboard sheet available in brown, recycled and virgin papers, from SG to 55 ECT.
  • ABS 3d.printer filament (Acrylonitrile-co-butadiene-co-styrene Polyethylene terephthalate Polycarbonate)
  • Horizontal bearing 1/4"
  • Timing belt 1/2" for printed dolly
  • Socket head allen screw various diameters
  • Stainless steel Rod, 3/8" 2ft long

Process of designing and development

 

 

 

Original model:

First iteration, sharing to a different platforms, from STEP to DXF, 3DM and IGS

First change, the Smart phone monopod with an external structure to fasten properly with clamps.

 

 

 

https://www.thingiverse.com/thing:2498739

 

First change, the Smart phone monopod with an external structure to fasten properly with clamps.

 

 

 

https://www.thingiverse.com/thing:2498739

Now the model looks slimmer and more elegant

Here, we are determining the envelope and applying physics principles to the bars, integrating the liitle stepper motor along the axis and the dolly.

Finally, a group revision... what if the dolly became a single 3d-printed box

How to avoid unexpected vibrations when moving...

And how to make it a lot more stable while moving

Then we manage to discuss what if the rods got a little bit more apart, to give way for the stepper motor to fit in the dolly, and secure the bearing along the rod.

Finally, the model evolved to a more static piece, using the main axis, setting in the beginning of the box all electronics.

A second prototype to see how it might work with this assembly

Now, we are working on the Code, based in this one:

 

 

 

https://create.arduino.cc/projecthub/cripps/arduino-hackhd-time-lapse-dolly-94f53e

 

 

 

/Time-lapse dolly/

 

 

 

#include <Keypad.h>

 

#define STEPS 4096

 

 

 

const byte ROWS = 4; //four rows

 

const byte COLS = 3; //three columns

 

const byte LCDpin = 13;

 

const byte camTX = 18, camRX = 19; //pins to communicate with the camera

 

char keys[ROWS][COLS] = {

 

  {'1','2','3'},

 

  {'4','5','6'},

 

  {'7','8','9'},

 

  {'*','0','#'}

 

};

 

byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad

 

byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad

 

 

 

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

 

 

 

//variables to store and verify user input

 

String filmDur = 0, sbf = 0, deg = 0;

 

boolean answerGiven = 0, userVerified = 0, inputValid = 0;

 

 

 

//stepper motors setup

 

const byte stepperSpeed = 10; //the higher the number the slower the stepper

 

const byte translate[4] = {9,10,11,12}; // pins for the translating stepper

 

const byte rotate[4] = {14,15,16,17}; // pins for rotating stepper

 

const boolean stepperSeq[8][4] = { //step sequence to move the motors

 

 

 

  {1,0,0,1},

 

  {1,0,0,0},

 

  {1,1,0,0},

 

  {0,1,0,0},

 

  {0,1,1,0},

 

  {0,0,1,0},

 

  {0,0,1,1},

 

  {0,0,0,1}

 

};

 

 

 

void setup(){

 

  pinMode(camTX, OUTPUT);

 

  digitalWrite(camTX, HIGH); //Make sure the camera button is not grounded

 

  pinMode(camRX, INPUT);

 

 

 

  //set up stepper motors for translation and rotation

 

  setupStepper(translate);

 

  setupStepper(rotate);

 

 

 

 

 

 

 

  pinMode(LCDpin,OUTPUT);

 

  Serial.begin(19200);

 

  resetLCD(LCDpin); //power on LCD

 

 

 

  Serial.println("Welcome to the  time-lapse dolly");

 

  delay(2000);

 

  standbyMode(camTX); //i only had to power on the camera here because

 

                    //otherwise the battery turned itself off due to lack of current being drawn

 

  while(digitalRead(camRX) == LOW){

 

    ; //wait until camera verifies it is in standby mode

 

  }

 

}

 

 

 

void loop(){

 

  do  {

 

      Serial.println("                                \n\n");

 

      Serial.print("Duration of filming in hours: ");

 

      filmDur = getData(2); //wait for input of 2 chars in length

 

      do {

 

        Serial.println("                                \n\n");

 

        Serial.print("How many secondsbetween shots:");

 

        sbf = getData(2);

 

        if(sbf.toInt() < 10){

 

          Serial.println("                                \n\n");

 

          Serial.print("Minimum 15 seconds between shots");

 

          delay(3000);

 

        }

 

        else {

 

          inputValid = 1;

 

        }

 

      } while(inputValid == 0);

 

 

 

      Serial.println("                                  \n\n");

 

      Serial.print("How many degreesof rotation:");

 

      deg = getData(3);

 

      Serial.println("                                  \n\n");

 

      Serial.print("OK! the sequencewill go for.... ");

 

      delay(2000);

 

      Serial.println("                                \n\n");

 

      Serial.print(filmDur);

 

      Serial.print(" hours");

 

      delay(2000);

 

      Serial.println("                                \n\n");

 

      Serial.print("There will  be  ...             ");

 

      delay(2000);

 

      Serial.println("                                \n\n\n\n");

 

      Serial.print(sbf);

 

      Serial.print(" seconds      between frames");

 

      delay(2000);

 

      Serial.println("                                \n");

 

      Serial.print("And the camera  will rotate ");

 

      delay(2000);

 

      Serial.println("                                \n\n\n");

 

      Serial.print(deg);

 

      Serial.print(" degrees");

 

      delay(2000);

 

      Serial.println("                                \n\n");

 

      Serial.print("Is this OK?     * = YES # = NO  ");

 

 

 

      answerGiven = 0; //reset boolean in case it isn't the first time through

 

      do {

 

        char key = keypad.getKey();

 

        if(key == '*'){ //if YES, mark input as verified by the user

 

        userVerified = 1;

 

        answerGiven = 1;

 

        }

 

        if(key == '#'){ //if NO, clear entries and start from the top

 

          filmDur = 0;

 

          sbf = 0;

 

          deg = 0;

 

          inputValid = 0;

 

          answerGiven = 1;

 

        }

 

      } while(answerGiven == 0); //wait for a valid answer

 

 

 

 

 

 

 

  } while (userVerified == 0); //if input is verified then continue

 

 

 

  //begin time-lapse photography

 

    Serial.println("                                \n\n");

 

    Serial.print("Initiating      sequence...\n");

 

    //calculate total frames in sequence

 

    int totalFrames =  filmDur.toInt() * 60 * 60  / sbf.toInt();

 

    //calculate increment for the translation stepper

 

    int incrementT = round(5 * STEPS / (float)totalFrames);

 

 

 

    //calculate increment for the rotation stepper

 

    float ratio = (float) deg.toInt() / 360;

 

    int incrementR = round(STEPS * ratio / totalFrames);

 

 

 

    //get out of standby mode before actually beginning photography

 

    standbyMode(camTX);

 

    while(digitalRead(camRX) == HIGH){

 

      ;

 

    }

 

 

 

    int i, nextStepT = 0, nextStepR = 0;

 

    for(i = 1; i <= totalFrames; i++){

 

 

 

      unsigned long time = millis(); //get time at beggining of iteration

 

      shoot(camTX); //take a picture

 

      Serial.println("                                \n\n");

 

      //calculate and display the percentage completion and hours remaining

 

      int percentage = i / (float)totalFrames * 100;

 

      Serial.print(percentage);

 

      Serial.print("% complete");

 

      Serial.println("\n");

 

      int hrsLeft = round( (float)filmDur.toInt() * ( (100 - (float)percentage) / 100 ));

 

      Serial.print( hrsLeft );

 

      Serial.print(" hours left");

 

      nextStepT = stepper(translate, incrementT, 1, nextStepT); //translate

 

      nextStepR = stepper(rotate, incrementR, 1, nextStepR);  //rotate

 

      //subtract the time elapsed since the beggining of the iteration from

 

      //the desired delay between frames, and then delay that resulting time

 

      while(digitalRead(camRX) == HIGH){

 

        ; //wait for picture to save before moving on

 

      }

 

      while( ( millis() - time ) < ( sbf.toInt() * 1000 ) ){

 

        ;

 

      }

 

    }

 

    Serial.print("done");

 

    while(1){

 

      ;

 

    }

 

 

 

}

 

 

 

void resetLCD(byte pin) {

 

 

 

  digitalWrite(pin,LOW);

 

  delay(500);

 

  digitalWrite(pin,HIGH);

 

  delay(2000); //LCD needs time to self-test

 

}

 

 

 

void standbyMode(byte pin){

 

  digitalWrite(pin, LOW);

 

  delay(2000);

 

  digitalWrite(pin, HIGH);

 

}

 

 

 

void shoot(byte pin){

 

  digitalWrite(pin, LOW);

 

  delay(200);

 

  digitalWrite(pin, HIGH);

 

}

 

 

 

String getData(int len){

 

  //function that returns a string entered on the keypad of max length "len"

 

  String data = 0;

 

  while(data.length() < len) {

 

     char key = keypad.getKey();

 

     if (key){

 

        if(key == '#' || key == '*'){

 

          ; //do not accept non-numeric characters

 

        } else {

 

            data += key; //concatenate character to input string

 

            Serial.print(key); //print character

 

        }

 

     }

 

   }

 

   delay(500); //allow time so user can actually see his/her input before moving on

 

  return data;

 

}

 

 

 

void setupStepper(const byte type[]){

 

  //set all stepper pins to output

 

  int i = 0;

 

  for(i=0; i<4; i++){

 

      pinMode(type[i], OUTPUT);

 

  }

 

}

 

 

 

 

 

int stepper (const byte type[], int iterations, boolean dir, int lastStep){

 

  int d = 0;

 

  if(dir){ //dir = 1 means clockwise

 

   while(iterations){

 

     for(d = 0; d < 4; d ++){

 

      digitalWrite(type[d], stepperSeq[lastStep][d]);

 

     }

 

     lastStep++;

 

     if(lastStep > 7){

 

       lastStep = 0;

 

     }

 

 

 

     iterations--;

 

     delay(stepperSpeed);

 

   }

 

  }

 

 

 

  else { //dir = 0 means counterclockwise

 

   while(iterations){

 

    for(d = 0; d < 4; d++){

 

      digitalWrite(type[d], stepperSeq[lastStep][d]);

 

    }

 

    lastStep--;

 

    if( lastStep < 0 ){

 

     lastStep = 7;

 

    }

 

    iterations--;

 

    delay(stepperSpeed);

 

   }

 

  }

 

 

 

  return lastStep;

 

}

 

 

Copyright Fab Lab

Ciudad de México 2020