Society of Robots - Robot Forum

Software => Software => Topic started by: lcab on April 13, 2010, 01:07:38 PM

Title: having trouble trying to get encoders to work.
Post by: lcab on April 13, 2010, 01:07:38 PM
hello i am trying to write a program that uses encoders to make it drive certain amount of distance. i am using a atmega 640 microporsisor and an trying to use Lynxmotion 12VDC, 200rpm, 0.78Kg-cm GHM-16 w / rear shaft gear motors with  Lynxmotion Quadrature Motor Encoder (with Cable). the link below shows the two parts side by side.
http://www.robotshop.ca/ProductSearch.aspx?qs=rb%2Dlyn%2D251 (ftp://http://www.robotshop.ca/ProductSearch.aspx?qs=rb%2Dlyn%2D251).

can somebody please show me some sample code, something like some to drive for 5 seconds then stop. i would greatly appreciate it because having a lot of trouble with the code thank you.i just need a boost start because i don't know whats going on.
Title: Re: having trouble trying to get encoders to work.
Post by: Invicta on May 15, 2010, 09:58:00 AM
Most of the sensors (sonar, IR, Laser, encoder) you are likely to use on your robot work with distance and not time especially when the robot is trying to map its environment. I assume that you have some control over the speed of your motors. So if you want to the robot to move for a given time calculate the distance the robot will travel in that time using the speed at which it will travel. Then by measuring the distance it has travelled using the feedback from the encoders stop the robot when it has reached the target. Usually though you just move the robot from A to B at whatever speed is suitable for the occasion and do not bother with the time taken.
Title: Re: having trouble trying to get encoders to work.
Post by: KurtEck on May 15, 2010, 11:27:20 AM
I have been playing with the same motors and encoders on a Lynxmotion tri-track.  Earlier I wrote code that for the Atom Pro to handle the quadrature encoders.  The difficulty is handling the number of events. Specficially assume that your motors are running at 150rpm, the motor has a 30 to 1 reduction and the encoders have 100 or 400 quadrature events per revolution.  That implies that you will have about: 150*30*400/60 events per second or: about 30,000 events per second per motor.

In the past I wrote the code to interrupt on one of the two channels.  The interrupt code would change which edge it is looking at and check the state of the other channel.  With this you can detect the direction the motor is going, however I am only using half the resolution.  In my cases the was plenty accurate (1 revolution of the motor gives you: 12000 transitions, so accuracy of 1/6000 of the revolution of the motor is sufficient).  I found that this code eats up a lot of processing power, especially the idea of processing something like 30000 interrupts per second.  

A couple of years ago I also wrote code for an Atmega32 for the SRS workshop robot.  This used a wheel watcher with far fewer events.  At that time I found the code much more reliable to continuously poll the encoders versus processing the interrupts.  I am not proud of this code, but maybe it will get you started:
Code: [Select]
void ENCODER::CheckStates()
{
// We will do this as a psuedo state machine.
char bNewState;
// First the Left One...
RecheckState:
bNewState = 0;

switch (_bState)
{
case ENS_00_PBIAS: // Neither Channel High Positive bias.
if (_pinA->IsHigh())
{
// Channel A went high
_sTicks++;
_sDist += _sIncr;
bNewState = ENS_A;
}
else if (_pinB->IsHigh())
{
// Channel A went high
_sTicks++;
_sDist -= _sIncr;
bNewState = ENS_B;
}
break;

case ENS_00_NBIAS: // Neither Channel High Positive bias.
if (_pinB->IsHigh())
{
// Channel A went high
_sTicks++;
_sDist -= _sIncr;
bNewState = ENS_B;
}
else if (_pinA->IsHigh())
{
// Channel A went high
_sTicks++;
_sDist += _sIncr;
bNewState = ENS_A;
}
break;

case ENS_A: // A went high first wait for both to go to zero
if (!_pinA->IsHigh() && !_pinB->IsHigh())
bNewState = ENS_00_PBIAS;
break;

case ENS_B: // B went high first wait for both to go to zero
if (!_pinA->IsHigh() && !_pinB->IsHigh())
bNewState = ENS_00_NBIAS;
}
if (bNewState)
{
_bState = bNewState;
goto RecheckState;
}
}
The code was called from the main loop as often as possible.  

Now backing up for a second, the question is what do you currently have working?  Are you starting from scratch.  What are you using to control it?  Are you using a motor controller, if so which one, if not what... On my old SRS, I started off just getting the code to when I pressed a button the little rover would start going foreward.  Once that was working I added turning, then added sensors and had it try to follow a wall.  Only after things like that were working would I add in the encoders.

As a side note, this is a common problem that processing encoders eats up a lot of processing power.  That is why for example the company Basic Micro is working on a Motor controller that does the processing for you, including having commands to say, make the motor go at so many encoder events per second and stop after you go a certain distance.

Good Luck and sorry about my ramblings.

Kurt