Quadrature encoder

Ad.'s icon

Hi
I want to track the speed and the direction of rotation of a wheel.
I use a rotary optical encoder which outputs 2 signals on phase quadrature. (see the doc).

Max Patch
Copy patch and select New From Clipboard in Max.

I have a lot of errors of the direction when the speed is high.
Here's my code to detect the clock-wise and anti-clockwise rotation:

Any help would be appreciated !
Thanks.
Ad

2584.QuadratureEncoder.png
png
Ad.'s icon

Anyone ?
_

christripledot's icon

I built a bicycle-controlled game of "Pong" using reed switches and spoke magnets, and found that I had to set the gearing of the bike such that the wheel rotated quite slowly.

I have no experience with the encoders you describe, but it looks like they operate on the same principle as my out-of-phase reed switch setup. I suspect that either the frequency at which you poll your inputs may be too low for the speed of rotation you need to track. If you're unable to gain more precision that way, then perhaps you could "gear down" the wheel, and use a second (slower-rotating) wheel to drive the encoders?

Ivan's icon

Hi Ad,
Encoders need very high sampling rates to work properly. A typical encoder can easily have around 100 ppr (pulses per revolution). What kind of signal converter are you using to sample the encoders into max? If you're using anything like an arduino you might even find that it is to slow. A good alternative is finding a decent quadrature decoder IC like the ones from Avago or US Digital:

Ad.'s icon

Thx you for your respnonses.
I use arduino Duemilanove yes. A 16MhZ process should do the trick no ?

Has anyone experienced this ?

Here's the encoder I use:

__

Chris Muir's icon

I've successfully read an encoder on the Arduino, but it only really worked when the encoder was going into the Arduino interrupts, and the Arduino was detecting/accumulating the direction.

What sort of code is running on the Arduino?

Ad.'s icon

I use sarcduino so it's a simple digital read wich communicates with max.
Would you have some code samples ? I suppose I would need to make the treatment in the arduino environement and then sends values into max ? Am I right ?
Thx you!
__

Ivan's icon

You're right! :-)

I got satisfactory results from a mix of several of those techniques. Still, like Chris mentioned, you'll need to use pin interrupts. Most arduinos only have two interrupts, which mean you'll only be able to use one encoder (one interrupt per encoder channel). The exception is the Mega, which has 6 native interrupts.
You can go around these limitations by addressing pins directly and using bit shifting but that's way more advanced.

Ad.'s icon

Hi !
I use this code but I don't know what to do with the result:
It doesn't count actually…

Ivan, I didn't use the main rotary encoders code because they turn on the PULLUPS, and I think my bourns encoder doesn't like it !

    uint8_t encoder_A = 2;
    uint8_t encoder_B = 3;
    // Make sure that you declare it as volatile to avoid any memory corruption
    volatile long int count = 0;
    volatile uint8_t sstatus = 0;
    void encoder_counter()
    {
     sstatus=1;
     sstatus|=digitalRead(encoder_A);
     sstatus<
     sstatus|=digitalRead(encoder_B);
// four bit status
     int fbs=sstatus&15;
     if (fbs==2||fbs==4||fbs==11||fbs==13)
{
     ++count;
     }
     else
     {
     --count;
     }
    }

    void setup()
    { Serial.begin(9600);

     pinMode(encoder_A, INPUT);
     pinMode(encoder_B, INPUT);
     // pin 2 corresponds to interrupt 0 as per arduino
     attachInterrupt (0, encoder_counter, CHANGE);
     // pin 3 corresponds to interrupt 1 as per arduino
     attachInterrupt (1, encoder_counter, CHANGE);
    }

    void loop()
    {
     Serial.println(count, DEC);
}

What do you think of that code ?
Thx,