PDA

View Full Version : [Question(s)] Working with encoders

kankatee
12-05-2008, 07:35 PM
I just got my BaneBot 36mm encoders (http://banebots.com/docs/EN-G0361-KT-Assembly.pdf)(pdf) all hook up and calibrated yet I am not fully sure how to work with the A/B signal lines.

I am trying to solve the issue of not being able to run a straight line, or compensate for mechanical imperfections, etc.

Any help getting started would be huge!

Thanks,
David

lnxfergy
12-05-2008, 09:05 PM
There are several ways to use encoders - I'm gonna assume you are using some microcontroller. Your encoders basically give you pulses related to distance moved by the wheels. Unfortunately, you want to control the speed, which is the distance/time.

First we shall look at the encoders themselves. If you just want speed information (and not direction) you could read the input pulses from just one of the signals (for now we shall assume you are using A). Then count the ups-and-downs that occur in some given time. On a micro, this is best achieved using interrupts to count, and some hardware timer to set your time intervals.

But of course, the advantage of a quadrature encoder is that you can get speed AND direction. Add the use of the B line gains two things: you can get direction of movement and increase the number of counts/rotation that your encoder reports. The key to this is that A and B are 90 degrees out of phase. For instance, if you have an interrupt that triggers on a positive change in A, you can choose how your count changes based on B: if B = 0, rotation is CW, if B = 1, rotation is CCW. You can do a lot more to increase the resolution of the encoder... but I'll leave that for another time.

http://forums.trossenrobotics.com/attachment.php?attachmentid=857&stc=1&d=1228532268

With any of these schemes, the difficult part is that you then need to compare this counts/time against some ideal number (the actual speed you want to move at). You then need to adjust your PWM output to the motor until you get the desired count. This can be as simple as adding an error term that is equal to the a proportion of the difference:
new_pwm = old_pwm + K(desired_speed - actual_speed)
The issue here is that the system may go into oscillation, which means it never gets the desired speed, it keeps going too fast, too slow, too fast, too slow... and the "solution" to such a problem is some form of a PID controller. We've had several threads recently on PID control - I can sum it up like this: it's a pain....

-fergs

kankatee
12-05-2008, 09:46 PM
Thanks for the reply. Slightly over my head, but I get the idea. And your assumption is correct, I am using a BS2 and simply care about speed of rotation.

You reference "some hardware timer." I was advised to also purchase a pair of encoder dividers (http://banebots.com/pc/ELECTRONICS/EN-A0001-KT). Does this achieve / solve the timing aspect of what you were referring to?

Reading the input of signal A via PULSIN is the correct method?

lnxfergy
12-05-2008, 10:54 PM
Thanks for the reply. Slightly over my head, but I get the idea. And your assumption is correct, I am using a BS2 and simply care about speed of rotation.

You reference "some hardware timer." I was advised to also purchase a pair of encoder dividers (http://banebots.com/pc/ELECTRONICS/EN-A0001-KT). Does this achieve / solve the timing aspect of what you were referring to?

Reading the input of signal A via PULSIN is the correct method?

I'm gonna answer those in reverse order. The PULSIN probably isn't want you want.. that would tell you how long the pulse is, which I think would probably be very unreliable. It might work, but I really doubt it. Unfortunately for you (and fortunately for me, IMHO), I don't use Basic Stamps. You might google around for some sample code, because this is a fairly common thing that people do - putting encoders on robots. It is likely that either someone has done this with a Basic Stamp - or many people will have posted that it is too difficult to do.

I say that, because I'm not sure the BS2 has enough hardware to do speed control. A typical setup is that you would connect your A line to a pin that supports hardware interrupts. Then every time the pin goes from low to high, a special piece of code (the interrupt) runs, this code simply checks the B line and then adjusts COUNT as neccessary. COUNT would then be the distance move. This alone may be useful - for instance, I typically skip speed control because my robots all follow walls - but I use encoders for turning. I start the robot turning and then wait until the count passes some point that indicates the robot has turned enough - I can use similar code to do things like MOVE FORWARD X INCHES. Speed control though is a bit more difficult - you need to add a time element. The common way to do this would be to run some control loop at a set frequency - say 20Hz (the robot updates it's speed 20 times per second). Inside this loop we would look at how many counts we accumulated in the last 20th of a second, then compare this to the desired, update the PWM and wait until the next round. Typically, this 20Hz loop would also be an interrupt. The problem I see is that I'm not sure the BS2 has that much of an interrupt structure - or is fast enough. Thus, there may be some other way that BS2 users have come up with.

A common problem with encoders is that they have TOO fine of a resolution. Often, encoders will give you several thousand counts per rotation, if you have a small wheel, that is several thousand counts per inch (CPI) of travel. Often, this is just too much data, and your poor micro controller can't do anything else but count the rotations of the wheel. The encoder divider will simply divide the number of pulses the encoder sends. So, if your encoder gave 4000CPI, and your encoder divider was set to 16, you would only 400CPI, a more manageable amount.

-Fergs

lnxfergy
12-05-2008, 10:59 PM
Out of curiosity, the below is from Parallax:

Does the BASIC Stamp module support interrupts
No, the interpreter chip used in the BASIC Stamp microcontroller does not support interrupts. In many cases, a fast polling routine may be used to accomplish the same effect, however, depending on the number and size of the tasks involved in some applications, this will not be fast enough and the BASIC Stamp microcontroller may not be a plausible solution. While not true interrupts, the BS2p24, BS2p40 and BS2px24 modules support “polled interrupts.” The “polling” commands allow the BASIC Stamp modules to respond to certain I/O pin events at a faster rate than what is normally possible through manual PBASIC programming. In this case the interpreter periodically checks the state of the designated polled-input pins. It “polls” these pins after the end of each PBASIC command and before it reads the next PBASIC command from the user program; giving the appearance that it is polling “in the background.” -Fergs

kankatee
12-05-2008, 11:51 PM
I do have a few PICAXE chips. But before I even get to that, my encoders are in fact not calibrated yet. I am still fidgeting with this encoder divider board.

12-06-2008, 02:30 AM
You might also just dedicate a "real" MCU to the task.

An ATMEGA 168 @ 20Mhz is \$4.11 from Digikey. Figure \$5 more for the glue hardware/board/voltage regulator. \$9 and you're set.

The "toy" MCU's (learning products - ie. anything that runs BASIC ;) ) are ok for introducing students in a non-threatening way to MCUs, but when you need to get into realtime interrupt-driven systems I'd prefer "the real thing".

The other downside is that they're all terribly expensive for what they offer - even things like the Arduino. I buy one board of a certain system (like the Arduino) to quickly prototype with, but I implement my own on the 'bot, because there's never more than \$15 in actual hardware there, \$25 if you want to etch a custom board.

Fergs - to get closer in the derivation of speed, since he's really looking to just balance his motors at any given speed, couldn't he sample the apparent speed of one motor, and then just quickly step-up the other one just one step at a time until the speeds matched? I can't imagine that it'd take more than one revolution if the encoders are high res... (that eliminates Kahlman Filtering or some other advanced PID, but doesn't save you from wanting hardware interrupts)

Oh, and +Rep if I can give it again, Fergs! Great investment into the answer!

kankatee
12-06-2008, 10:19 AM
Adren- Yes, all I want to do is balance the motors speeds. BaneBots advised that I dont need to mess with calibration unless I am concerned with direction.

Since the PICAXE supports interrupts, is there a simple way to do this?

And I totally hear what you are saying regarding "toy" MCUs.

lnxfergy
12-06-2008, 11:25 AM
You might also just dedicate a "real" MCU to the task.

The "toy" MCU's (learning products - ie. anything that runs BASIC ;) ) are ok for introducing students in a non-threatening way to MCUs, but when you need to get into realtime interrupt-driven systems I'd prefer "the real thing".

Fergs - to get closer in the derivation of speed, since he's really looking to just balance his motors at any given speed, couldn't he sample the apparent speed of one motor, and then just quickly step-up the other one just one step at a time until the speeds matched? I can't imagine that it'd take more than one revolution if the encoders are high res... (that eliminates Kahlman Filtering or some other advanced PID, but doesn't save you from wanting hardware interrupts)

Oh, and +Rep if I can give it again, Fergs! Great investment into the answer!

First, thanks, the "toy" MCU was sort of what I was trying to say - without being quite so blunt about it....

As to comparing the counts of the two motors - maybe. It would definately be easier than comparing both to some desired count, so I would say that is probably a good idea (to make the desired count one motor's count, and just tune the one to it). Regardless, this will have the same possibility of jumping into nasty oscillation - in fact, I would say it is more likely.. if motor A is your desired speed, and B is trying to catch it, imagine the situation where A is oscillating a small amount because of some inconsistentcy in the floor surface - now B is going to oscillate - but it is likely that proportional error term alone will actually amplify the oscillation - now your bot is wiggling back and forth at high speed...

And yea - no way around interrupts... unless you are willing to dedicate 100% of a processor's time to this task and only this task and do polling

-Fergs

kankatee
12-06-2008, 12:09 PM
Despite interrupts (which the PICAXE does support) I am still unfamiliar with how I get the speed out of the encoder divider or straight from the encoders.

lnxfergy
12-06-2008, 02:32 PM
Encoders don't measure speed - they measure rotation. If we only look at one output - say A, what you get from the encoder is a wave signal that goes up and down and up and down and....

http://www.spectronav.com/images/M3-SquareWave.jpg

You can count how many times it goes up and down - and that is a measure of how much the wheel has rotated. To get "speed" we need to add time because physics tells us that: SPEED = DISTANCE_TRAVELED/ TIME. Or in our case, ROTATIONAL_SPEED = ROTATION_AMOUNT/TIME.

Adrenalynn made a suggestion earlier that would make this easier to do: just compare the left motor and the right motor. We'll assume that one of the motors is running close to desired speed, for now let's assume that is the right motor (since it is called right, it must also be correct ;)). We assume you have two interrupts running, one for each motor. Each interrupt triggers when the A input from that motor goes from low to high - if we throw out direction, we have:
when_left_A_goes_high:
left_count++

when_right_A_goes_high:
right_count++

You would then have a loop like this:
loop_forever:
error = right_count - left_count
left_pwm = left_pwm + K_TERM * error
wait_some_time

Where K_TERM is some constant you use to scale error - if it is too high you system will wildly osciallate and the thing will drive like a drunken congressman. If it is too low, it won't fix the difference fast enough and your robot will still move in an arc.

As far as using the divider board - it really should just insert itself into between the motor encoders and the processor. Quite frankly - get this working without the divider and then add it into the system if you find the processor can't keep up with your wheel speeds.

-Fergs

lnxfergy
12-06-2008, 02:39 PM
Also, here is a link to some of my own code on the AVR micro that implements encoders, note that it doesn't do speed control, just distance and angle movements. It also uses some funky code in the interrupts to get the absolute maximal resolution out of the encoders, and is isn't the most accurate in movement (e.g. there is no PID on anything to keep it from overshooting the end-point).

http://svn.blunderingbotics.com/filedetails.php?repname=Projects&path=%2Favrra%2Flibrary%2Fencoders.h

-Fergs

12-06-2008, 02:40 PM
I think I was considering "locking" the speed, where you set a baseline and use which ever motor is faster when you make your sample. I don't think you'd need to sample all that often with all that high a precision really. Looking at R/C, you set your trim and ignore it for the next year or two until some bozo picks up your remote and just HAS to slide the trim sliders (;)) I was really just trying to approximate a trim control.

You don't get "speed" out of an encoder. That's what Fergs was explaining - speed is a function of Time/Distance, it's not a natural output. What you get is nothing more than "Tick" "Tick" "Tick". You need to have a clock that measures how long it takes between those "ticks", which gives you time, and know how far apart those ticks are in distance from each other. Now you have time and distance, and you know the size of the wheel, you can compute speed - although I'm not sure you need it per-se. You're more looking at RPM, just fraction R, fraction M ["shaft speed" or "wheel speed"]. And that is probably more illustrative of the way you'd go about it. You need to time how long it takes to get some fraction of a revolution represented by the known wheel-ticks.

12-06-2008, 02:41 PM
Sorry, Fergs - I stepped on you with a similar answer - but yours was more detailed...

kankatee
12-06-2008, 02:45 PM
Right. Got ya.

I have dropped the encoder dividers and have the A signal line of each encoder running into 2 sep pins on the PICAXE. Now I can loop and calculate time between ticks. The signal lines are just going to give me a logic high/low or 1/0. Correct?

Thanks for all your help so far guys.

kankatee
12-06-2008, 03:42 PM
874 So I wired up the motors with encoders to a PICAXE-08M. The image is a snapshot of the test code I am using. According to the Counters, Counter2 is running a touch faster. Of course this is not yet time bound and no adjustments are being made to the motors yet. Just want to make sure I had it straight...

sunithaya
12-07-2008, 09:24 PM
Fergy, thanks for the excellent post. It really helps. One of my students tried unsuccessfully to uses quadrature encoders with a BS2 and gave up. But still he needs speed and direction information, so that will be fun :-)