Chief Delphi

Chief Delphi (http://www.chiefdelphi.com/forums/index.php)
-   Programming (http://www.chiefdelphi.com/forums/forumdisplay.php?f=51)
-   -   Troublesome encoder ISR (http://www.chiefdelphi.com/forums/showthread.php?t=70028)

pogenwurst 14-11-2008 17:15

Troublesome encoder ISR
 
I'm having trouble with the encoder interupt routine I wrote yielding incorrect results. The tick count increases overall, but along the way the count "rolls back" despite the shaft turning in the same direction.

Would anyone care to make a quick check of it for me? It may just be a silly mistake, but I've gone over it again and again and still can't see where I've gone wrong.

A little background:
-> I'm only using one encoder, and resolution is very important for the task at hand, so I'm using the interrupt on digital inputs 3-6 (channel A is in 3, channel B is in 4) so that I can count the ticks for both channels and on both rising and falling transitions.
-> This is on a Vex controller, so I'm using the IFI code, not Kevin's.
-> The following code is contained within the appropriate conditional branch for interrupts 3-6.
-> "encoderCount" is a global volatile signed long, and oldPORTB is a global unsigned char (I use it nowhere but the ISR, so it needn't be indicated as volatile, correct?).

Code:

        const unsigned char aMask = 0x10;
        const unsigned char bMask = 0x20;

        unsigned char a = (PORTB & aMask) == aMask;
        unsigned char b = (PORTB & bMask) == bMask;

        if((PORTB ^ oldPORTB) == aMask)
        {
                if(a)                                                // a transitioned high
                {
                        if(b)                                        // b is high
                                ++encoderCount;
                        else                                        // b is low
                                --encoderCount;
                }

                else                                                // a transitioned low
                {
                        if(!b)                                        // b is low
                                ++encoderCount;
                        else                                        // b is high
                                --encoderCount;
                }
        }

        else if((PORTB ^ oldPORTB) == bMask)
        {
                if(b)                                                // b transitioned high
                {
                        if(!a)                                        // a is low
                                ++encoderCount;
                        else                                        // a is high
                                --encoderCount;
                }

                else                                                // b transitioned low
                {
                        if(a)                                        // a is high
                                ++encoderCount;
                        else                                        // a is low
                                --encoderCount;
                }
        }

        oldPORTB = PORTB;

        INTCONbits.RBIF = 0;    /*    and clear the interrupt flag        */

Thanks for any help you can offer

Andrew Schreiber 14-11-2008 18:37

Re: Troublesome encoder ISR
 
How fast are they spinning? What COULD be happening is you are spinning them fast enough that when you check for direction (I assume Quadrature Encoders based on a and b in your code) you have already transitioned too far. The only real solution would be slow it down. Turn the encoders by hand to see if this is happening then too. Hope this helps.

pogenwurst 19-11-2008 17:27

Re: Troublesome encoder ISR
 
They're spinning pretty slowly -- the 'bot takes several seconds to move a meter, and the shaft it's on has a sprocket quite a bit larger than that on the wheels' shaft (48 teeth encoder/motor shaft : 15 teeth wheel shaft, IIRC), which slows down the tick rate on the encoder even more if I'm not mistaken.

Also, when my ISR is simply "++encoderCount", it accurately counts the number of ticks (but without sense of direction, obviously). My direction-aware ISR isn't enormously complicated; it doesn't seem like enough to make it miss ticks, though I certainly could be mistaken.

Next time I have access to the machine I'll experiment with turning the shaft, though.

Thank you for your reply. I'll let you know if I figure it out.

Mr. Lim 19-11-2008 22:05

Re: Troublesome encoder ISR
 
I know this will only give you 1/4 the resolution you want, but does at least this work?

Code:

        const unsigned char aMask = 0x10;
        const unsigned char bMask = 0x20;

        unsigned char a = (PORTB & aMask) == aMask;
        unsigned char b = (PORTB & bMask) == bMask;


        if((PORTB ^ oldPORTB) & aMask == aMask)
        {
                if(a)                                                // a transitioned high
                {
                        if(b)                                        // b is high
                                ++encoderCount;
                        else                                        // b is low
                                --encoderCount;
                }
        }

        oldPORTB = PORTB;

        INTCONbits.RBIF = 0;    /*    and clear the interrupt flag        */

If this does work, then chances are it's an ISR timing problem. If this doesn't work, then it's likely a logic issue that's not obvious to us. Either way, it'd help us narrow down the nature of the beast.

-Shawn T. Lim...


All times are GMT -5. The time now is 00:04.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi