Shop OBEX P1 Docs P2 Docs Learn Events
Good Technique for getting encoder speed? — Parallax Forums

Good Technique for getting encoder speed?

KyeKye Posts: 2,200
edited 2010-03-05 19:35 in Propeller 1
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,

Comments

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2009-11-21 01:13
    Hi Kye,

    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*
  • KyeKye Posts: 2,200
    edited 2009-11-21 01:19
    Maybe Peter, the problem with this is that the spurious readings are like +10000 larger than the real value due to the sensitivity. This kills any hope of using averaging. I need a way just select the lowest value that come in the period. The lowest value in the set is actually the real value. I wonder how I can do that is PASM...

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2009-11-21 02:10
    To have spurious readings that high sounds more like a hardware problem (jitter) or maybe even software. But surely the lowest value is easy to do so I must be missing something as you are experienced with PASM. What's the problem with it in PASM?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    *Peter*
  • KyeKye Posts: 2,200
    edited 2009-11-21 02:59
    Actually I think it is a software problem. I just realized that I continously update the count into main memory... this would explain how such low values are getting in there. Since the read from another core is asynchronous. So it could be sampling the value as it counted up. This is how my technique is sopposed to work. But, I need to prevent this action so I'll have to stagger updates. This should fix the problem.

    Hah, well thanks Peter!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • dMajodMajo Posts: 855
    edited 2009-11-21 16:06
    Kye: many thinghs here.

    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
  • dMajodMajo Posts: 855
    edited 2009-11-21 18:12
    BTW: this is·a median filter on 3 vals. The concept is correct, for the syntax I hope (still a newbie on self modifing code: if a guru want to validate it ...)
    At each scan the new val in INPUT is taken and the median result is stored in OUTPUT

    Median Filter (3)
    ==============================================
                 CMP   MEM2,   INPUT      wc
           if c  MOVS  Med31,  @INPUT
           if_nc MOVS  Med31,  @MEM2
           if c  MOVD  Med32,  @INPUT
           if_nc MOVD  Med32,  @MEM2
    
           if c  MOVS  Med33,  @MEM2
           if_nc MOVS  Med33,  @INPUT
    
    Med31        CMP   MEM3,   @0         wc
    
           if_c  MOVD  Med32,  @MEM3
                 NOP 
    
    Med32        CMP   @0,     @0         wc 
                 MOV   Temp,   Med32
                 SHR   Temp,   #9
                 MOVS  Med33,  Temp
                 NOP
    Med33        MOV   OUTPUT, @0
                 MOV   MEM3,   MEM2
                 MOV   MEM2,   INPUT
    

    bye

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    · Propeller Object Exchange (last Publications / Updates);·· Vaati's custom search
  • KyeKye Posts: 2,200
    edited 2009-11-22 00:11
    Very nice dMajo. I just finished the code for the driver and I have it working very good now. It gives a REALLY good speed measurement without any problems associated from sampling the position and determining speed.

    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,
  • ManAtWorkManAtWork Posts: 2,178
    edited 2010-03-05 10:30
    Hello Kye,

    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
  • KyeKye Posts: 2,200
    edited 2010-03-05 17:14
    @ManAtWork - I have done the same thing with my dual quadature encoder object too posted in the obex.

    I do the timeout stuff however in a PID loop which is not in the posted driver online.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Nyamekye,
  • kwinnkwinn Posts: 8,697
    edited 2010-03-05 19:35
    Kye, you may be interested in some testing I did a while back. I found was that there is very little difference in the accuracy of a speed measurement between using a 1000 line, 256 line, and a 64 line encoder if you select the optimum point at which to switch from using the prop clock to the encoder pulses.
    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.
Sign In or Register to comment.