Good Technique for getting encoder speed?
Kye
Posts: 2,200
Hey guys,
I've been making a dual encoder driver to complete my set of motor/servo drivers aviable in the obex. However, I've been trying to go one step further and provide a function that returns the current speed in seconds.
The speed value is the number of ticks per second.
So, I thought of a nice way to avoid the sample rate vs accuracy problem when doing deltaV/deltaT using integer only math... However I'm having a problem with sensitivy...
So the more accurate technique is to count the number of microseconds that pass between each new tick from the encoder. This means that I just have to count how much time passes between when the next encoder line reaches me from the previous one.
So, then all I have to do is do (samplefreq / ticksAccumulated).
For example, if sample freq was 500_000 then if 1 tick came every sample time then the speed would be 500_000 ticks per second. Or if 1 tick came every 500_000 samples then the speed would be one tick per second.
So, by doing this I get a REALLY sensitive speed value. However, the problem with this is that due to integer only math. Since the value is so sensitive it jumps arround alot. This wouldn't normally be a problem by fixing it through averaging. But integer only math causes the lower values of ticksAccumulated to be wieghted more than higher values.
This causes averaging to fail.
So is there a better way to do this? I can only do divides in spin and the driver is in pasm. Besides that to keep the sample freq high I cannot really do much beyond a few instructions.
Any ideas?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
I've been making a dual encoder driver to complete my set of motor/servo drivers aviable in the obex. However, I've been trying to go one step further and provide a function that returns the current speed in seconds.
The speed value is the number of ticks per second.
So, I thought of a nice way to avoid the sample rate vs accuracy problem when doing deltaV/deltaT using integer only math... However I'm having a problem with sensitivy...
So the more accurate technique is to count the number of microseconds that pass between each new tick from the encoder. This means that I just have to count how much time passes between when the next encoder line reaches me from the previous one.
So, then all I have to do is do (samplefreq / ticksAccumulated).
For example, if sample freq was 500_000 then if 1 tick came every sample time then the speed would be 500_000 ticks per second. Or if 1 tick came every 500_000 samples then the speed would be one tick per second.
So, by doing this I get a REALLY sensitive speed value. However, the problem with this is that due to integer only math. Since the value is so sensitive it jumps arround alot. This wouldn't normally be a problem by fixing it through averaging. But integer only math causes the lower values of ticksAccumulated to be wieghted more than higher values.
This causes averaging to fail.
So is there a better way to do this? I can only do divides in spin and the driver is in pasm. Besides that to keep the sample freq high I cannot really do much beyond a few instructions.
Any ideas?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
Comments
When I have done encoders before and also measured speed by measuring pulse period as is done for lower frequency inputs I have used an averaging buffer where I store the samples so that as I put a new one in I add it to the accumulator and subtract the old one from the end of the buffer. The buffer itself is not really used in any calculation, only the end value is used. This gives an averaging window as well so it's useful for rejecting spurious readings. Does this help?
P.S. I keep the buffer at a binary multiple so all I need to do is shift the accumulator right for an average. If I use 256 bytes for the buffer then I just read the high byte of the accumulator.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
*Peter*
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
*Peter*
Hah, well thanks Peter!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
All depends on what is your target speed range vs encoder resolution. Now, to measure speed two techniques are used depending if you look for high or low speeds: each one is good on one side.
1) measuring pulses in a given time: good for high speed, resolution one pulse. Let say the time unit is second and the real speed is 2.5 pps you will show a speed value oscillating from 2 to 3 so with 20% error. If the real speed is 1000.5 pps you will show 1000 and 1001 so the error is 0.005%. Here if you treats the two encoder channels by looking at the rising/falling edges you can quadruple the resolution and have the same accuracy at 4 times lower speed
2) measuring pulse lenght with a reference frequency: here you don't count the encoder pulses your reference frequency pulses and use the enceder pulse as a trigger; resolution is one reference frequency pulse. This is appropiate for low speeds. Let say again a real speed of 2.5pps and the reference frequency is 1 kHz. One encoder pulse is 400 ticks; in this range the error (your measure oscillation) could be 0.25%. With a real speed of 750pps your measure will be once 1 once 2 with an error of 50%. Here the limit is the reference frequency. As higher go the speed higher must be the reference frequency to keep the accuracy.
Now a you can see for position measure and high speed you use a quadrature decoder working on edges. For low speed you use the 2nd method (optionally with self adaptive reference frequency). There is a point where when the speed increase you switch from method 2 to method 1.
For noise reduction you can average the measures (moving average) but this will low pass the process variable and keep the measuring errors in the system. A low pass filter is time delay line so your regulators must take this in account and will be slower. I suggest you a median filter. This kind of filtering introduces a slight delay but remove the peak errors and preserve the signal shape (eg. if in your process you have an instant change of your variable from 10% to 50% this kind of filtering will slightly delay the edge but will preserve it, not smooth)
I hope my english is understandable to explain the concepts
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· Propeller Object Exchange (last Publications / Updates);·· Vaati's custom search
At each scan the new val in INPUT is taken and the median result is stored in OUTPUT
bye
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
· Propeller Object Exchange (last Publications / Updates);·· Vaati's custom search
The output value however is very sensitive and must be average through a filter or something but it produces the kinda raw value you would expect to see from the standard speed sensor.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
I know I'm a bit late. I just discovered this thread. I'm currently experimenting with encoder speed detection, too. I do it as follows:
* One cog watches the encoder inputs and counts up or down when a change happens. Additionally it records the value of the system counter CNT every time this happens. This one runs assembler and can keep up with count rates up to 1MHz. It has system clock resolution (12.5ns) because it uses waitpne to wait for an input change.
* a second cog manages the speed control loop. It has a fixed sample rate, say several kHz. Once every sample period it reads the current count and current time (most recently input change) values. As it also remembered the values from the last period it can calculate speed as delta-count / delta-time (if delta count is zero avoid division because delta time·may also be zero).
This has a very good accuracy for both high and low speeds. You could even extend the speed range by allowing delta-times greater than one sample period. You just have to be careful about special cases then. The timer may overflow and you get no more input changes when the speed drops to zero. So you would need a time-out in this case.
Cheers
I do the timeout stuff however in a PID loop which is not in the posted driver online.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
The main source of error seems to be jitter in the output pulses from the encoder which I am guessing are due to variations in sensing the change from dark to light. This can be reduced by counting the prop clock over several encoder pulses, and seems to be less of a problem for lower resolution encoders.