![]() |
|
My other sites |
|
|
|
|||
| [Home] [Projects] [Hardware] [Software] [Books] [Links] [Downloads] | |||
|
|
|||
|
|
|||
This lesson shows the basic method for interfacing to a Quadrature encoder to the OOPic. BOB has two Quad Encoders, one for each wheel. To see more about the mechanics and fabrication of this encoder visit my [TMG Encoder] page. Rotary wheel encoders are found on most high-end robots, so I thought it was important for BOB to have them so I could experiment with different control methods. In this lesson I illustrate a simple way to make pre-programmed movements. This is a very simple form of "Closed Loop" control, where feedback is used to determine when the required action is complete.
Perhaps a quick tutorial about Quad Encoders is a good idea here.
If you have a wheel or cog with slots in it, and you put a single optical sensor on the wheel looking through the slot, you will be able to tell how fast/far the wheel is turning, but you won't be able to tell which direction it's turning. This is OK on something like a drill, but no good on a robot that can change direction. By adding a second sensor near the first one, you can tell which way the wheel is turning by noticing which sensor sees the slot first. A true Quadrature Encoder would have the slot and sensors arranged so that each sensor produces a square wave, and those waves overlap by 90 degrees (dividing the wheel into quarters). But in BOB's case one of the cogs has a 90 degree slot in it, and the two sensor are next to each other. Not the ideal configuration, but it works just fine. Since the encoder gear is early in the gear reduction, each revolution of the gear is a fraction of a wheel turn.
The OOPic has a built in object called oQEncoder that is perfect for our uses. It attaches to two optical encoders and it maintains a 16 bit count. It counts up when the cog rotates one way, and counts down when the cog rotates the opposite way.
As always, in this program (PBot_BOB-E_VC6.osc) I start using the I/O definitions described on the main BOB [Software page]. These are:
//-------------------------------------------------------Here are the Objects that I define for this Lesson:
//-----------------------------------------------------------------
// User Objects. Use these to access BOB hardware.
//-----------------------------------------------------------------
oCountDownO ActionTimer = New oCountDownO; // User Timer
// Wheel sensor and driver Objects
oQencode LeftClicks = New oQencode; // Value for Left Encoder
oQencode RightClicks = New oQencode; // Value for Right Encoder
// LED Object (accessed as group of 4 bits)
oDIO4 LEDs = New oDIO4; // Driver for LEDs
// Wheel motor driver Objects
oDCMotor2 LeftMotor = New oDCMotor2; // Driver for the Left Wheel
oDCMotor2 RightMotor = New oDCMotor2; // Driver for the Right Wheel
In my programs, I always use the SetupIO( ) function configure the OOPic
"Objects" required to interface to the hardware.
In this case it's all pretty much just IO assignments.
//-----------------------------------------------------------------
// SetupIO()
// Configure all the IO Objects here
//-----------------------------------------------------------------
Void SetupIO( Void )
{
// --------------------------------
// setup the ActionTimer Timer for 1/10th Second ticks
// Preload counter with 5 second delay
// --------------------------------
ActionTimer.PreScale = CLOCK_PRESCALE;
ActionTimer.ClockIn.Link(ooPIC.Hz60);
ActionTimer = FIVE_SECONDS;
ActionTimer.Operate = cvTrue;
// --------------------------------
// setup the Wheel Encoders
// --------------------------------
LeftClicks.Value = 0;
LeftClicks.IOLine1 = IO_ENCODER_LEFT_FRONT ;
LeftClicks.IOLine2 = IO_ENCODER_LEFT_BACK ;
LeftClicks.Operate = cvTrue;
RightClicks.Value = 0;
RightClicks.IOLine1 = IO_ENCODER_RIGHT_FRONT ;
RightClicks.IOLine2 = IO_ENCODER_RIGHT_BACK ;
RightClicks.Operate = cvTrue;
// --------------------------------
// setup the LED Drivers
// --------------------------------
LEDs.IOGroup = IO_LED_GROUP ;
LEDs.Nibble = IO_LED_NIBBLE ;
LEDs.Direction = cvOutput ;
// --------------------------------
// setup the Wheel Drivers
// --------------------------------
LeftMotor.Value = 0;
LeftMotor.PreScale = SLOW_PWM;
LeftMotor.Mode = cvOn; // Active Braking
LeftMotor.Brake = cvOff;
LeftMotor.IOLine1 = IO_MOTOR_LEFT_FWD;
LeftMotor.IOLine2 = IO_MOTOR_LEFT_REV;
LeftMotor.IOLineP = IO_MOTOR_LEFT_PWM;
LeftMotor.Unsigned = cvFalse;
LeftMotor.Period = PWM_PERIOD;
LeftMotor.Operate = cvTrue;
RightMotor.Value = 0;
RightMotor.PreScale = SLOW_PWM;
RightMotor.Mode = cvOn; // Active Braking
RightMotor.Brake = cvOff;
RightMotor.IOLine1 = IO_MOTOR_RIGHT_FWD;
RightMotor.IOLine2 = IO_MOTOR_RIGHT_REV;
RightMotor.IOLineP = IO_MOTOR_RIGHT_PWM;
RightMotor.Unsigned = cvFalse;
RightMotor.Period = PWM_PERIOD;
RightMotor.Operate = cvTrue;
}
So all I need to do now is tell BOB to move and I should be able to see the Left and Right Click (encoder values) change. Since I only have 4 LEDs, it makes sense to tell BOB to move the Left Wheel forward 15 clicks and stop, then move the Right Wheel 15 clicks and stop. I'll then repeat this forever. While I'm waiting for each encoder's value to reach 15, I'll display the current value on the 4 LEDs. I expect BOB to wiggle forward as the LED's count from 0 to 15. Here's the main program.
//-----------------------------------------------------------------
// BOB Main Program
//-----------------------------------------------------------------
Void Main(Void)
{
// Always set up the required IO and VC's first.
SetupIO();
// Wait for 5 second "Start Up" to elapse
While(ActionTimer.NonZero);
// Run Wheel Test
While (cvTrue)
{
// Move Left wheel foward 15 clicks
// Reset count and start rotation
LeftClicks.Value = 0;
Drive(50, 0, 0);
// Loop waiting for clicks to reach 15
While (LeftClicks.Value < 15)
{
// Display clicks on LEDs
LEDs.Value = LeftClicks.Value ;
}
Brake();
// Move Right wheel foward 15 clicks
// Reset count and start rotation
RightClicks.Value = 0;
Drive(0, 50, 0);
// Loop waiting for clicks to reach 15
While (RightClicks.Value < 15)
{
// Display clicks on LEDs
LEDs.Value = RightClicks.Value ;
}
Brake();
}
}
I took a little movie of BOB doing the [Wiggle Dance]. It was interesting to play with different motor speeds to see how fast the encoders could count. The encoders had no trouble keeping up with the Tamiya gearbox's top speed with my standard drive voltage. I knew that there was a dead band of low drive voltages that did not have enough oomph the start the wheels turning. So already my mind was working on a way to get speed feedback from the encoders so I could just crawl along reliably :). More on that later...
Next, in [Lesson F] I will look at doing similar closed loop position feedback using virtual circuits.
Web content is copyright © PhilBot.com
2005, Deep Creek Lake, MD.
Contact: Phil Malone 301.387.2331, webmaster
@
PhilBot.com