|
Re: Optical Sensors Used as Encoders?
We used the red light narrow beam optical sensors as wheel counters last year with good success, and tried this years "broad beam" IR banner sensors but found them to be less attractive. As a result, we used last year's sensors. It turns out that Banner QS18VN6LV, is not available
from an approved electronics source, while the same sensor with polarized light QS18VN6LP is available. I have posted a question to FIRST to learn if the "V" sensor will be considered equivalent for wheel counter use. Lacking that, we will buy and swap in the "legal" sensors in on the practice day of the competition. Hopefully, we won't have to waste the $122 and the half hour of time...
We used retro-reflective tape on the inside rim of the kit supplied wheel. Pieces of tape about 1/8 inch wide and half an inch long are pasted on the wheel rim at 5 degree intervals. We count transitions, giving us a 2.5 degree resolution. The sensor looks at the wheel through the kit frame tubing, through a slot about 1/8 inch wide, with the inside painted flat black. The sensor is set half way between the "no signal" point in the "-" adjustment direction and the the "+" limit which still produces a signal as the wheel is turned. You can find suitable tape in last years kit of parts, and at most hardware stores. Another source is 3M reflective tape used for boating safety, it has a pattern on it that is perfect for cutting strips about 1/8 inch wide by hand. Last year we put the relfective tape on the output
shaft of the drill motor, but did not get as much resolution as we got this year off the back side of the wheel. We checked with FIRST with regard to using retro-reflective tape to support wheel counters in the QandA and it is explicitly approved for this purpose.
The sensors are polled in the "fast loop" using the code below. Each time a light-dark, or dark-light, transition is seen the wheel counter for the corresponding wheel is incremented. The additional code tracks the minimum run length of ones or zeros, so that you can make sure that the RC computer is not missing any transitions when you turn up the speed. It also tracks any "glitches" that might confuse the counter code, if they happen. We found that maximum freewheel speed was easily accomodated with the drills set in low gear. About half maximum free wheel speed was accomodated in high gear. If you want to handle higher speed in high gear you need to sacrifice your measurement resolution and go with wider relfective strips spaced at larger intervals. It could be that there is no issue at all when the robot is driving itself on the carpet, as the wheels might not get going as fast as when running with the wheels off the ground. Your mileage will vary with your gear ratio.
Why such fine resoution, you might ask. You can measure a turn quite accurately with it, and you can dynamically correct motor power using feed back in order to track a very straight path if you feel the need to do this. It is also the case, with fine resolution, that you don't have to carefully set the wheels in the starting position.
The code in the fast loop follows, you have to put a call to it in the autonomous routine because it is not called in the default code. Calling it in the non-autonomous code is not that useful, unless you want to do clever things with the user controls.
Code Follows:
At the end of user_routines.h:
extern int left, oldleft, leftcounter;
extern long leftstringlength, minleftstringlength;
extern int right, oldright, rightcounter;
extern long rightstringlength, minrightstringlength;
In user_routines_fast.c:
Add the call:
Process_Data_From_Local_IO();
at the end of the while(autonomous_mode) loop so that
the wheel counters are updated while in the autonomous code.
Add, right above the Process_Data_From_Local_IO() definition:
int left, oldleft, leftcounter;
long leftstringlength, minleftstringlength;
int right, oldright, rightcounter;
long rightstringlength, minrightstringlength;
Here is the Process_Data_From_Local_IO() code:
void Process_Data_From_Local_IO(void) {
if((left = ((int)rc_dig_in10)) != oldleft) { /* Left counter is dig in 10 */
oldleft = left;
leftcounter += 1;
if(leftstringlength < minleftstringlength) {
minleftstringlength = leftstringlength;
}
leftstringlength = 1;
}
else {
leftstringlength += 1;
}
/* Repeat the code above for the "right wheel"
*/
}
Now, the minimum string length variable and the counter
values can be printed
out every time it gets smaller, running the wheels with the
joysticks, so that you can be sure that the counters are working
and not missing any transitions. Once you know all is well,
you can delete the tracking of the minimum string length. It is
taking time to execute, after all, and contributes to the possibility
of missing a transition.
The variables need to be suitably initialized, when the RC
comes on line. Do this in the user initialization routine,
after all of the RC controller IO hardware is set up.
#define MINSTRINGLENGTH 1000
oldleft = left = ((int)rc_dig_in10);
leftcounter = 0;
leftstringlength = 1;
minleftstringlength = MINSTRINGLENGTH;
/* Similar for the right wheel counter.
*/
We put this in just before the User_Proc_IS_Ready() call.
I'll leave the state machine code that uses the wheel counters,
packet counter for time, soft starts, soft stops, turns, and so forth,
to do your particular autonomous task as an excersise for the reader.
Any bugs/typos in the above are an excersise for the reader also,
I retyped it reading our code from the PC laptop and may not have
gotten it all, or gotten it all correct.
With good high resolution wheel counters, properly programmed,
you can "dead recon" to fractions of an inch on the floor and get
accurate repeatable turns.
Have Fun,
Eugene
|