IR Tracker

From Mech
Revision as of 16:55, 19 March 2008 by AliceZhao (talk | contribs) (→‎Code)
Jump to navigationJump to search

"Spot" the IR Tracker

IR Tracker Header.jpg

Team Members

Left to right: Matt, Mark and Alice
  • Mark Straccia (Mechanical Engineering, Class of 2009)
  • Matt Turpin (Mechanical Engineering, Class of 2009)
  • Alice Zhao (Electrical Engineering, Class of 2008)


Overview

The goal of this project was to create a device that would follow a moving infrared light. The IR Tracker does this by continuously detecting the position of an infrared emitter in two axises, and then tracking the emitter with a laser.


The IR Tracker follows two major steps: (1) Identify the position of the IR emitter (2) Rotate the device to align itself with the IR emitter.


  1. The IR Tracker finds the location of the maximum infrared intensity in both the x-axis and y-axis. Two encoders continuously record the position of the IR emitter based on intensity levels detected by two IT detectors.
  2. Given the information about the location of the IR emitter, the device rotates itself in two dimensions to adjusts its plane to be normal to the IR emitter. At this point, the laser should point to the IR emitter.


We will discuss the mechanical design, electrical design, PIC code, resulting project and our team reflections.

Mechanical Design

The primary components used in this circuit are:

  • 2 Pitman Motors
  • 2 RC Servos
  • 1 Turntable (6031K17, McMaster-Carr, $2.20, readily available)
  • 1 Cylindrical Bearing
  • 1 Laser
  • Mirror
  • Plexiglas


Mechanical Design.jpg


  • Detecting Component:
    • On the main plane of the device, two encoders are placed perpendicular to each other (able to track on two axises). Mirrors are placed on the output shafts of the two encoders at 45 degree angles. Two infrared detectors are placed in line with the encoders. While the encoders are constantly spinning, the mirrors detect light from the IR emitter and bounce the light to the IR detectors.
Detecting Component.jpg


  • Rotating Component:
    • Below the main plane of the device, two servos are used to rotate the entire device to align the main plane to be normal to the emitter. The main plane is attached to a block of Plexiglas that surrounds a cylindrical bearing. This bearing allows the main plane to rotate along the y-axis. This block of Plexiglas is mounted on a turntable which allows the main plane to rotate along the x-axis.
Rotating Component.jpg

Electrical Design

The primary components used in this circuit are:

  • 1 PIC (18F4520)
  • 2 IR Detector / Emitter Pairs
  • 2 Hall Sensors & Small Magnets
  • 1 H-Bridge (L298)
  • 1 Inverting Schmidt Trigger (74HC14)


Circuit Diagram.jpg


  • PIC
    • The PIC is the central controller of the IR Tracker.
  • IR Detector / Emitter Pairs
    • The IR Detector detects the intensity of IR light coming from the IR Emitter. Over each revolution of the encoder's output shaft, the location of the maximum IR intensity is recorded. This information is given to the PIC to determine the servo's next position.


IR Detector Emitter.jpg


  • Hall Sensors
    • The Hall Sensors are used as a position marker for the encoders. They are located just below the output shafts of the encoders. A small magnet is placed on the side of the output shafts. As both encoder shafts spin, the Hall Sensor detects the location of the magnet. The purpose of the Hall Sensors is to use this information to sync the rotations of the two encoder shafts.


Hall Sensors.jpg


  • H-Bridge
    • The H-Bridge is an intermediate component between the PIC and the servo motors. It allows the servo motors to run forwards and backwards.
  • Inverting Schmidt Trigger
    • The Schmidt Trigger acts as an intermediate between both the PIC to the motors and the PIC to the Hall Sensors. It helps filter out noisy signals.

Code

See full code here

Here is a general outline of the code:

  1. Move device to starting position (x=0,y=0)
  2. Spin encoder shafts
  3. Sync rotations of the two encoder shafts
  4. Determine location of the maximum IR intensity detected
  5. Convert encoder position to servo position
  6. Rotate the main plane to the new servo position


The code consists of several functions which are described in detail below.


Initial Setup


#include <18f4520.h>
#device high_ints=TRUE
#fuses HS,NOLVP,NOWDT,NOPROTECT
#device icd=true
#use delay(clock=20000000)


//Test Variables
int ii;

//Position Variables
signed int32 PositionCountX = 0;
signed int32 PositionCountY = 0;

//Hall Correction Variables
signed int16 MagnetPlacementX = -600;
signed int16 MagnetPlacementY = 370;

//Servo Variables - in terms of servo counts (400-2700)
int16 ServoCurrent[2] = {1550,1550};
int16 ServoNextX = 1550;
int16 ServoNextY = 1550;
int16 ServoTargetX = 1550;
int16 ServoTargetY = 1550;
int32 AnglePositionX = 1550;
int32 AnglePositionY = 1550;

//Average Moment Variables
int32 AverageAngleX = 0;
int32 AverageAngleY = 0;

//Servo Rate
int16 ServoMove = 1;
int SlowServoX = 0;
int SlowServoY = 0;

//Servo Counting Variable
int RCcount = 0;

//Sensing and Summing IR Variables
int32 MomentX = 0;
int32 MomentY = 0;
int32 MomentCountX = 0;
int32 MomentCountY = 0;

runsetup()


void runsetup()
{
 
   setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1);       //External input from quadrature encoder 0
   setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);          //External input from quadrature encoder 1
   setup_timer_2(T2_DIV_BY_4, 255, 5);                //Servo incrememnting timer at 1 kHz
   setup_timer_3(T3_INTERNAL | T3_DIV_BY_4);          //Servo reseting timer
 
   enable_interrupts(INT_TIMER2);                     //Enable ISR2 for servo
   enable_interrupts(INT_TIMER3);                     //Enable ISR3 for servo
   enable_interrupts(INT_EXT);                        //Enable Interrupt for Hall sensor X
   enable_interrupts(INT_EXT1);                       //Enable Interrupt for Hall sensor Y
   enable_interrupts(global);
 
   setup_ccp1(ccp_pwm);                               //Setup PWM1
   setup_ccp2(ccp_pwm);                               //Setup PWM2
 
   set_timer0(0);                                     //Clear starting point of counters
   set_timer1(0);
 
   set_PWM1_duty(0);                                  //Motors off for startup
   set_PWM2_duty(0);
 
   for(ii=0;ii<3;ii++)                                //Start up flashing lights
   {
      output_d(0x55);
      delay_ms(100);
      output_d(0);
      delay_ms(100);
   }

   set_PWM1_duty(1023);                               //Motors start at full velocity
   set_PWM2_duty(1023);
}

encodersave()


void encodersave()                                    //Counters will return the number of pulses to the inputs.
{ 
   PositionCountX = get_timer0();                     //Relative position of the X encoder
   delay_us(10);
 
 
   PositionCountY = get_timer1();                     //Relative position of the Y encoder
   delay_us(10);
}

positioncount()


void positioncount()                                  //Gives visual information about where in the rotation the mirrors are
{
   //output_d(PositionCountY>>6);
   if (PositionCountX >4875)
   {
      output_high(pin_D3);
   }
   else if(PositionCountX>0)
   {
      output_low(pin_D3);
   }
   if (PositionCountY > 4875)
   {
      output_high(pin_D4);
   }
   else if(PositionCountY>0)
   {
      output_low(pin_D4);
   }
}

ircheck()


void ircheck()                                        //Check to see where in the rotation
{
   if(PositionCountX<4875)                            //First half of rotation, facing up
   {
      if(input(PIN_C6)==0)                            //If IR detector is detecting encoded signal
      {
         output_high(PIN_D5);                         //Gives visual representation
         MomentX+=PositionCountX;                     //Increase moment count by position
         MomentCountX+=1;                             //Increase count of moments
       
      }
      else
      {
         output_low(PIN_D5);                          //Clear B5 if mirror is facing down
      }
   }
   else if((PositionCountX>=4875)&&(MomentCountX>5)) //Runs when this function is called and IR detector
   {
      AverageAngleX = (MomentX/MomentCountX);         //Average the moment to give the center of IR in terms of motor encoder counts
      //output_d(AverageAngleX>>6);
      if (((AverageAngleX)>650)&&((AverageAngleX)<4800))
      {
         AnglePositionX = 3647-23*AverageAngleX/34;   //Convert motor encoder counts to servo values
       
       
         if (ServoCurrent[0] + AnglePositionX < 1950) //Less than 90 degress
         {
            ServoTargetX = 400;
         }
         else if (ServoCurrent[0] + AnglePositionX> 4250) //Greater than 450 degrees
         {
            ServoTargetX = 2700;
         }
         else                                         //between 90 and 450 degrees
         {
            ServoTargetX = AnglePositionX + ServoCurrent[0] - 1550;
         }
      }
      MomentX = 0;                                    //reset moment variables
      MomentCountX = 0;
   }
 
   if(PositionCountY<4875)
   {
      if(input(PIN_C5)==0)
      {
         output_high(PIN_D6);
         MomentY+=PositionCountY;   
         MomentCountY+=1;
       
      }
      else
      {
         output_low(PIN_D6);
      }
   }
   else if((PositionCountY>=4875)&&(MomentCountY>5))
   {
      AverageAngleY = (MomentY/MomentCountY);
      //output_d(AverageAngleY>>6);
      if (((AverageAngleY)>650)&&((AverageAngleY)<4800))
      {
         AnglePositionY = 3647-23*AverageAngleY/34;
       
         // find target location in terms of servo counts
         if (ServoCurrent[1] + AnglePositionY < 1950) //less than 90 degress
         {
            ServoTargetY = 400;
         }
         else if (ServoCurrent[1] + AnglePositionY> 4250) // greater 450 deg
         {
            ServoTargetY = 2700;
         }
         else
         {
            ServoTargetY = AnglePositionY + ServoCurrent[1] - 1550;
         }
      }
      MomentY = 0;
      MomentCountY = 0;
   }
}

servotrack()




Results

Our final design:


Final Design.jpg


"See Spot Run": Click here to see a movie of our final project.

Reflections

Overall, our team is very satisfied with our end result.

  • Objectives Met:
    • Ability to locate the position of an IR emitter on two axises.
    • Ability to rotate to align its plane to be normal to an IR emitter.
    • Ability to continuously track an IR signal.
  • Problems Encountered:
    • (Mechanical) Initially, the device had very shaky movements. We added additional screws to make the device more stable.
    • (Electrical) We added Schmidt Triggers to clean up the noisy signals from the servo motors to the PICs.
    • (Code) Originally coded to track direction of change of the IR emitter and supposed to move accordingly. We encountered a lot of noise. We changed the code to find the exact position of the IR emitter instead.
  • Future Work:
    • More powerful servos and a more accurately calculated counterweight would help smooth the movement of the device.
    • A more sensitive IR detector could track lower intensities of IR light in a room, instead of specifically an IR emitter.
    • With more precise measurements of the relationship between the encoder and servo values, the IR Tracker could more accurately determine the position of an IR signal.