Beruflich Dokumente
Kultur Dokumente
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.
Rotating Component
1.2.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. 1.3.Electrical
Design
Primary Components
1.1
PIC (18F4520)
2. 2 IR Detector / Emitter Pairs 3. 2 Hall Sensors & Small Magnets 4.2 5.1 MOSFETs Inverting Schmidt Trigger (74HC14)
IR Tracker
IR Tracker Schematic (includes original H-Bridge in design --> use MOSFETs instead)
<J IR Detector
maximum IR intensity is recorded. This information is given to the PIC to determine the servo's next position.
: Hall Sensors
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.
PIC
The PIC is the central controller of the IR Tracker.
MOSFETs
The MOSFETs are used as intermediate components between the PIC and the servo motors. It allows the Pittman motors to run in one direction. Inverting Schmidt Trigger The Schmidt Trigger acts as an intermediate between both the PIC to the encoders on the motors and the PIC to the Hall Sensors. It helps filter out noisy signals and invert signals to be readable for the PIC.
Code See full code here Outline of Code Here is a general outline of what the IR Tracker does:
Spin encoder shafts Record current position of the servo Determine location of the maximum IR intensity detected Convert encoder position to servo position Rotate the main plane to the new servo position Sync rotations of the two encoder shafts Repeat steps 2-6 main() This is the main function of our code: void main() { runsetup(); while (TRUE) { encodersave(); positioncount(); ircheck(); equalize(); } } The five functions it encompasses are described in detail below. runsetup() The interrupts for both servos and Hall sensors are set, and motors begin to spin at full velocity. This function is only called once at the beginning of the main function. void runsetup()
//External input //External input //Servo //Servo reseting { setup_timer_0(RTCC_EXT_L_TO_H | RTCC_DIV_1); from quadrature encoder 0 setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1); from quadrature encoder 1 setup timer 2(T2 DIV BY 4, 255, 5); incrememnting timer at 1 kHz setup_timer_3(T3_INTERNAL | T3_DIV_BY_4); timer enable interrupts(INT TIMER2); servo enable interrupts(INT TIMER3); servo //Enable ISR3 for //Enable ISR2 for
enable_interrupts(INT_EXT); Interrupt for Hall sensor X //Enable //Enable //Setup PWM1 //Setup PWM2 //Clear starting //Motors off for //Start up enable_interrupts(INT_EXT1); Interrupt for Hall sensor Y enable interrupts(global); setup ccp1(ccp pwm); setup ccp2(ccp pwm); set timer0(0); point of counters set timer1(0); set PWM1 duty(0); startup set PWM2 duty(0); for(ii=0;ii<3;ii++) flashing lights { output d(0x55); delay ms(100); output d(0); delay ms(100); //Motors start at } set PWM1 duty(1023); full velocity set PWM2 duty(1023); }
encodersave() //Counters will //Relative //Relative This records the current servo positions in the both the x and y direction. void encodersave() return the number of pulses to the inputs. { PositionCountX = get timer0(); position of the X encoder delay us(10); PositionCountY = get timer1(); position of the Y encoder delay us(10); } positioncount() This uses LEDs to represent where in the rotation the mirrors are, with one LED for each axis. The LEDs are on for half of the rotation and off for the other half. void positioncount() //Gives visual
if (PositionCountX >4875) output high(pin D3); lse if(PositionCountX>0) output low(pin D3); f (PositionCountY > 4875) output high(pin D4); lse if(PositionCountY>0) output low(pin D4); ircheck() //Check to see //First half of //If IR detector //Gives visual //Increase moment //Increase count //Clear B5 if This finds the location of maximum infrared light in both the x-axis and yaxis. This information is originally collected as an encoder position count value, is converted into an angle in degrees and is then converted again into servo position count value, so that the servo can move to the appropriate location. void ircheck() where in the rotation { if(PositionCountX<4875) rotation, facing up { if(input(PIN C6)==0) is detecting encoded signal { output high(PIN D5); representation MomentX+=PositionCountX; count by position MomentCountX+=1; of moments } else { output low(PIN D5); mirror is facing down } } else if((PositionCountX>=4875)&&(MomentCountX>5)) //Runs when this
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; variables MomentCountX = 0; } if(PositionCountY<4875) { if(input(PIN_C5)==0) { output high(PIN D6); MomentY+=PositionCountY; //reset moment
MomentCountY+=1; } else { output low(PIN D6); } } else if((PositionCountY>=4875)&&(MomentCountY>5)) { AverageAngleY = (MomentY/MomentCountY); 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; } } equalize() This syncs the speed and direction of the rotation of the two encoder motors. void equalize() //puts motors in
phase with each other { if(PositionCountX>PositionCountY) { set PWM1 duty(850); set PWM2 duty(1023); } else if (PositionCountX<PositionCountY) { set PWM2 duty(850); set PWM1 duty(1023); } } servotrack() While this function isn't in the main function, it is called in one of the interrupts. Its purpose is to slowly move the servos from their current
location to its destination. void servotrack() //Slowly adjusts the pulsing of the servo to place the plan in the appropriate location { if(((SlowServoX>15)&&(abs(ServoTargetX-ServoCurrent[0])>5))|| ((SlowServoX>8)&&(abs(ServoTargetX-ServoCurrent[0])>125)) ||((SlowServoX>3)&&(abs(ServoTargetX-ServoCurrent[0])>450))|| SlowServoX>100) //Can be used to slow down motion of Servos { if (ServoCurrent[0] < ServoTargetX - ServoMove) { ServoNextX = ServoCurrent[0] + ServoMove; ServoCurrent[0] = ServoNextX; } else if (ServoCurrent[0] > ServoTargetX + ServoMove) { ServoNextX = ServoCurrent[0] - ServoMove; ServoCurrent[0] = ServoNextX; lse ServoCurrent[0] = ServoTargetX; } SlowServoX=0; } if(((SlowServoY>15)&&(abs(ServoTargetY-ServoCurrent[1])>5))|| ((SlowServoY>8)&&(abs(ServoTargetY-ServoCurrent[1])>125)) ||((SlowServoY>3)&&(abs(ServoTargetY-ServoCurrent[1])>450))|| SlowServoY>100) {
if (ServoCurrent[1] < ServoTargetY - ServoMove) { ServoNextY = ServoCurrent[1] + ServoMove; ServoCurrent[1] = ServoNextY; } else if (ServoCurrent[1] > ServoTargetY + ServoMove) { ServoNextY = ServoCurrent[1] - ServoMove; ServoCurrent[1] = ServoNextY; } else { ServoCurrent[1] = ServoTargetY; } SlowServoY=0; } SlowServoX++; SlowServoY++; } Results Final Design
Video "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 Ability Ability to locate the position of an IR emitter on two axises. to rotate to align its plane to be normal to an IR emitter. 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. (Electrical) The L298N H-bridge ended up heating up the entire circuit. In our final design, we chose to use MOSFETS in their place. 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.