Self-Adjusting Lifting Mechanism

(The Mini-Crane)

BY Minerva Pillai, Sam Bou, Cliffton Chin, Judy Liao, Jose Rodriguez

Figure 1: Diagram of Gravity Compensation Mechanism

Introduction and Theory

In industry today, current designs of body appendages and construction equipment require the use of a heavy counter-weight or parallelogram linking mechanism to counter the moments of lifting.  The inertia of these counter-weights increases the power consumption and costs of using these machines.  These issues are very serious in today’s energy conscientious society. 

 

In a paper written by Toshia Morita and his three colleagues, “A Novel Mechanism Design for Gravity Compensation,” a unique design is proposed where torque is cancelled about a joint without the use of counter-weights.  This theory is expanded upon by the use of a spring to handle varying loads.  A working aluminum prototype at 1/25 scale is created that proves that a device of this nature is not only viable, but can be made inexpensively and extremely compact.

 

Its principals rely on the use of a spring to counter the moment created by the weight G.  By satisfying the equation below, the system remains in static equilibrium.

 

                                                                (1)

 

where k is the spring constant, G is the weight of the mass, and l, p and h are length dimensions. Equation 1 is not a function of angle θ, meaning that as long as the equation is satisfied, the system remains in static equilibrium at all angles (refer to figure 1). 

Spring 07

Hardware

Function

Major Obstacles

Conclusion

Reference

The device consists of three major hardware components: the standing bar, the lifting arm, and a knob. The C-shaped standing bar supports the entire device.  Weted through.

 

The arm is connected by a pin to the standing bar.  The arm is a hollow aluminum rod cut vertically through its axis such that a spring can rest inside it.  The tension cable connects the T-shaped piece to the spring after wrapping around a pulley.

Currently, a knob is used to move the T-shape to maintain static equilibrium when variable weights are placed on the system.

 

For future modification using force sensor:  The force sensor has a small sensing area of 8mm diameter.  To concentrate the weight from the load onto the 8mm diameter sensing area, we designed a pinching mechanism that grips the force sensor in its jaws with a force equal to the weights placed on the rotating arm (see Figure 3)

When the machine turns on, the T-shaped piece moves down until it hits a switch.  The switch informs the DSP that the T-shaped piece is at its starting position.  Weights are added to the hook.  Then, the knob can be manually turned to the correct height for the corresponding weight for static equilibrium (equation 1).  To watch the machine at work, please go to the following link:

Currently the T-shape moves up and down by the use of a knob.  In future models, a force senor can be use to calculate the weight and automatically change the location of the T-shape (refer to hardware section).

 

Currently, our design changes the height h to cancel the moment of differing weights.  During the height adjustment phase, the device is not in static equilibrium and the load-bearing arm moves.  Future improvements to the design should take into account the transitional time when h is changing, and provide a locking mechanism that provides support during transition period to prevent drastic changes in θ.  Another solution would be to have a stronger motor with a faster response time.

 

Our device only uses power during the height adjustment phase and can be modified to run off a portable power supply.  The compact nature of our device, as well as its ability to balance moment without the use of heavy counter-weights, makes it a very economical and viable replacement for lifting equipment today.  In the future, this design can be adjusted to be a wearable apparatus, finding its place in the military, the prosthetics industry, and beyond.

1. Morita, Toshia, Fumiyoshi Kuribara, Yuki Shiozawa, and Shigeki Sugano. "A Novel Mechanism Design for Gravity Compensation." Advanced Intelligent Mechatronics. (2003): 163-68.

 

2. FlexiForce Sensors User Manual. South Boston: Tekscan, Inc., 2004.

Code

/* include header files */

#include        "f2407_c.h"             /* Defines register names and addresses */

#include        "funlib.h"              /* Defines global variables and prototypes for function library */

#include        <math.h>                /* Enables the DSP to do certain math functions */

 

/*  define symbolic constants */

#define         pwmperiod  2000         /*Note: pwmperiod is the same as T1PR 20KHz assymmetric PWM with a 40MHz CPUCLK */

#define         PI          3.14159

#define         g          9.81     /* m/s^2*/

 

/*Deign Constants*/

#define                                      k                                                 513 /*N/m*/

#define                                      l                                                  .55 /*m*/

#define                                      p                                                 .145 /*m*/

#define                                      m_int                        2 /*kg*/

#define                                      h_int                         0.1516 /*m*/

#define                                      c_r                                              .2825 /*center of mass of rod [m]*/

#define                                      m_r                                            .180 /*weight of rod [kg]*/

#define                                      tolerance                 0.01/*Ideal case 0.000038*/              

void main(void)

{

                 /* DECLARATIONS */                 

                

                 /*Define Variable*/

                 static double h_setpoint = h_int;

                 static double h_current = h_int;

    static double h_next = h_int;

                 static double m_current = 0;

                 static double m_old = 0;

                 static double V_in = 0;/*Voltage from Force Sensor*/

                 static double clocktimeprev = 0;

                 static double time_start = 0;

                 static double time_new = 0;

                 static double time_old = 0;

                 static double test_err = 0;  

                 static int hi=0;   

                 static double h_mid=0;

 

                 /* initialized local variables */

    static int adc0 = 0;

    static int pwmduty1 = 100;

    static int pwmduty = 100;

    static int limitswitch = 0;

                 static int qepcount = 10000;

                 static int qepcount_old = 10 ;

                 static double err = 0;

                 static double a[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* changed a[] to a[10]*/

                 static double sum=0;      

                 static double count_height = 302362.2;/*Count/m */    

                 static int j = 1;

                 static int i = 1;

                 /* initialize basic registers and functions of DSP */

    initGen(); 

    /* initalize ADC */

    initADC();

                 /* initalize IOPC have the wire from the IOPC 0 to the DIR pin of the H-Bridge */

                 /* THis will allow us to change the direction of the motor based on wether the (I am calling it a pin)*/

                 /* pin moves up or down*/

    initIO(IOPC,0, OUTPUT);

                 /*intitialize push button input */

                 initIO(IOPC,1, INPUT);

                 /* initalize qep in pins 2 and 4 to run encoder*/            

                

                 initPWM(1, 2000);

    /* start clock using timer 3 with no prescaler */

    initClock(3,0);

                

                 while((limitswitch = getIO(IOPC,1)) == 0) /*while push button is not hit*/

                 {

                                  setIO(IOPC, 0, 0);

                                  setPWM(1, 2000);

                 }

                 setPWM(1,0); /*stop motor*/

                 initQEP(2,1000); /*set encoder value to 0*/

    qepcount = getQEP(2);

                                 

                 /* enter infinite while loop */

                 while(1)

    {

                                  updateClock();

                                  /* I am assuming that the input from the force sensor is coming into the ADC1. */

        /*adc0 = getADC(1);   /* reads ADC1 into adc0 */

 

                                  /*Makes the input from the adc into a voltage again  I am not sure about the next line. I emailed Bram about this and will reedit it later*/

                                  /*V_in = 5* (double)adc0/1023;

                                  m_current = 0.3927*V_in+.1995; /*equation from "calibration"*/

                

                                  /***NOTE: Take out time out error part of code during testing**/

        m_current = 3.6;

                  

                                  if ((m_current - m_old) > 0.3)

                                  {

                                                   time_start = clocktime;

                                  }

                                 

                                  h_setpoint = g*(m_r*c_r + m_current*l)/(p*k);      

                                  if (h_current>=.22 && h_current<=.225 && h_setpoint<.22 && h_setpoint>.225)

                                  {

                                                   initQEP(2,1000);

                                                   qepcount = getQEP(2); 

                                                   hi=1;

                                                   h_mid=h_current;

                                  }

                                                   qepcount = getQEP(2); 

                                                   hi=1;

                                                   h_mid=h_current;

                                  }   */

 

                                  else if (h_current<.20)

                                  {

                                   hi=0;   

                                  }                       

                                  qepcount = getQEP(2);

                                  if (hi==0)

                                  {

                                   h_current = (getQEP(2)-1000)/count_height + h_int;

                                  }

                                  else if ((hi==1) && (h_current>h_mid))

                                  {

                                   h_current = (getQEP(2)-1000)/count_height +h_mid;

                                  }

                                  else if ((hi==1) && (h_current<=h_mid))

                                  {

                                   h_current = h_mid-(getQEP(2)-1000)/count_height;

                                  }

       

        /*Dt = clocktime - Dt;*/

        err = h_setpoint-h_current;

        time_new = clocktime;

 

                    if(abs(err) > tolerance || abs(time_start-clocktime) < 120 )

                                                   {              

                                                                    if (err > 0 )

                                                                    {

                                                                                     setIO(IOPC, 0, 1);

                                                                    }

                                                                    else

                                                                    {                     

                                                                                     setIO(IOPC, 0, 0);

                                                                    }  

                                                                   

                                                                    if (abs(err) > 0.02)

                                                                    {

                                                                        pwmduty1= err * 2000/.224; /* took of parenthesis on err */

                                                                    }

                                                                    else 

                                                                    {   /*     

                                                                        if (i<10)

                                                                        {

                                                                                     i=i++;

                                                                        }

                                                                        else

                                                                        {

                                                                                     i=1;

                                                                        }

                                                                        a[i]=err;

                                                                                     for (j = 0; j < 10; j++)

                                                                                                      sum += a[j];

                                                                                     }

                                                                                     */

                                                                                     test_err = sqrt(err*err);

                                                                                     pwmduty1 = test_err * 2000/.125; /*+ 2000 * sum * (time_new - time_old)/(.224 * 2) + ((h_setpoint - h_next) - err)/(time_new - time_old)* .1; */

                                                                    }

               

                                                       if(pwmduty1 >= 900 )

                                                       {

                                                                                     pwmduty = pwmduty1;

                                                                    }

                                                                    else

                                                                    {

                                                                                     pwmduty = 900; /*Motor Constraint*/

                                                                    }  

                                                                    setPWM(1, (int)pwmduty); /*P Controller*/

                                 qepcount_old = getQEP(2);

                                                   }

                                  else

                                                   {

                                                                    setPWM(1,0);

                                                   }

        h_next = getQEP(2)/count_height + h_int;

                                  m_old = m_current;

                                  time_old = clocktime;

                 }              

                

}

http://video.google.com/videoplay?docid=-2775659962861535853&hl=en