Main Site Documentation

Snippet - Gray code decoder


#1

Gray code decoder

This is the manage code version of the Gray code decoder from Circuits@ Home:
http://www.circuitsathome.com/mcu/programming/reading-rotary-encoder-on-arduino

It is fast and simple and doesn’t require debouncing.

The example is set to be run on Panda II. Signal A from encoder goes to Di9, B to Di8.


#2

This would have been nice to have a couple weeks ago when I needed it!

I adapted a different solution using interrupts on Cerb40. Glitch filter is used at the default setting… it can read reliably at a pretty high rate.

I have to be really trying in order to spin it fast enough to get reverse readings… and that is with no knob on the encoder shaft. It would be even less likely to happen with a knob.

        static InterruptPort encPinA =
                new InterruptPort(FEZCerberus.Pin.PA1, true,
                                   Port.ResistorMode.PullUp,
                                   Port.InterruptMode.InterruptEdgeBoth);

        static InterruptPort encPinB =
                new InterruptPort(FEZCerberus.Pin.PA0, true,
                                   Port.ResistorMode.PullUp,
                                   Port.InterruptMode.InterruptEdgeBoth);

        static int _encoderPosition = 1;

        public static void Main()
        {
            encPinA.OnInterrupt +=
                new NativeEventHandler(encPinA_OnInterrupt);

            encPinB.OnInterrupt +=
                new NativeEventHandler(encPinB_OnInterrupt);

            
            Thread.Sleep(Timeout.Infinite);
        }

        static void encPinA_OnInterrupt(uint port, uint state,
                                          DateTime time)
        {

            if (encPinA.Read() == true)
            {
                // check channel B to see which way encoder is turning
                if (encPinB.Read() == false)
                    _encoderPosition++;         // CW
                else
                    _encoderPosition--;         // CCW
            }
            else   // must be a high-to-low edge on channel A                                       
            {
                // check channel B to see which way encoder is turning  
                if (encPinB.Read() == true)
                    _encoderPosition++;
                else
                    _encoderPosition--;         // CCW
            }
        }

        static void encPinB_OnInterrupt(uint port, uint state,
                                          DateTime time)
        {
            if (encPinB.Read() == true)
            {
                // check channel A to see which way encoder is turning
                if (encPinA.Read() == true)
                    _encoderPosition++;        // CW
                else
                    _encoderPosition--;         // CCW
            }
            // Look for a high-to-low on channel B
            else
            {
                // check channel B to see which way encoder is turning  
                if (encPinA.Read() == false)
                    _encoderPosition++;          // CW
                else
                    _encoderPosition--;          // CCW
            }
        }

#3

@ FireyFate - Nice!

Btw, did you ask about it on the forum? I don’t recall seeing it.


#4

Nope. I searched around a bit, didn’t see it, so I adapted that from an Arduino tutorial. I’m sure it could be written in less lines… but I think it’s a good learning example.


#5

It is a good example! Thank you!