Need help with rotary encoder
rodbrink
Posts: 9
in BASIC Stamp
I have an incremental quadrature encoder that I'm trying to use with a BS2. It's the mechanical type and has switch bounce. I've tried using the code I found on the Parallax website but apparently it works only with an optical encoder that's free of switch bounce. My encoder is causing erratic jumps in the counter. Here's the code:
' =========================================================================
'
' File...... Rotary Encoder.bs2
' Purpose... Read A Rotary/Optical Encoder
' Author.... Parallax, Inc.
' E-mail.... support@parallax.com
' Started...
' Updated... 07-15-2005
'
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' =========================================================================
'
[ Program Description ]
' This code demonstrates reading a rotary/optical encoder using a BASIC
' Stamp 2 Module. This code will work on the BS2e, BS2sx, BS2p24, BS2p40,
' BS2pe and BS2px24.
'
[ I/O Definitions ]
' A Output Connects To P0
' B Output Connects To P1
'
[ Variables ]
oldBits VAR Nib ' Previous State Of I/O Pins 0 - 3
newBits VAR Nib ' Current State Of I/O Pins 0 - 3
direction VAR Bit ' Direction Encoder Is Turned
counter VAR Byte ' Counter (0-255)
'
[ Initialization ]
OUTS = %0000000000000000 ' Set All Output Pins Low
DIRS = %1111111111111100 ' I/O Pins 0 - 1 Inputs
newBits = INA
'
[ Program Code ]
Main:
DO
newBits = INA ' Get State Of I/O Pins 0 - 3
IF newBits <> oldBits THEN ' Have Bits Changed?
direction = newBits.BIT0 ^ oldBits.BIT1
counter = counter - 1 + (2 * direction)
DEBUG HOME, DEC3 counter ' Show New Counter On DEBUG Screen
oldBits = newBits ' Update oldBits
ENDIF
LOOP
STOP
I've tried a jillion ways to eliminate the effects of the switch bounce with no good results. I need help, please...
' =========================================================================
'
' File...... Rotary Encoder.bs2
' Purpose... Read A Rotary/Optical Encoder
' Author.... Parallax, Inc.
' E-mail.... support@parallax.com
' Started...
' Updated... 07-15-2005
'
' {$STAMP BS2}
' {$PBASIC 2.5}
'
' =========================================================================
'
[ Program Description ]
' This code demonstrates reading a rotary/optical encoder using a BASIC
' Stamp 2 Module. This code will work on the BS2e, BS2sx, BS2p24, BS2p40,
' BS2pe and BS2px24.
'
[ I/O Definitions ]
' A Output Connects To P0
' B Output Connects To P1
'
[ Variables ]
oldBits VAR Nib ' Previous State Of I/O Pins 0 - 3
newBits VAR Nib ' Current State Of I/O Pins 0 - 3
direction VAR Bit ' Direction Encoder Is Turned
counter VAR Byte ' Counter (0-255)
'
[ Initialization ]
OUTS = %0000000000000000 ' Set All Output Pins Low
DIRS = %1111111111111100 ' I/O Pins 0 - 1 Inputs
newBits = INA
'
[ Program Code ]
Main:
DO
newBits = INA ' Get State Of I/O Pins 0 - 3
IF newBits <> oldBits THEN ' Have Bits Changed?
direction = newBits.BIT0 ^ oldBits.BIT1
counter = counter - 1 + (2 * direction)
DEBUG HOME, DEC3 counter ' Show New Counter On DEBUG Screen
oldBits = newBits ' Update oldBits
ENDIF
LOOP
STOP
I've tried a jillion ways to eliminate the effects of the switch bounce with no good results. I need help, please...
Comments
-Phil
Phil: The encoder fails at ALL speeds. I've tried putting PAUSE commands inside the DO loop to try and slow down the polling of the incoming bits but can't get that to work either.
-Phil
I inserted your line and I do get an occasional error. But only an occasional one. In the meantime the counter changes erratically - sometimes by a single step (which is what I want), but more often in steps of 3-5.
I've looked at the encoder outputs using a digital storage scope and they look pretty much as expected. I have simple RC filters connected to both outputs that tend to kill some of the switch bounce but certainly not entirely.
BTW, it might be worth mentioning that the quiescent outputs are both pulled high and that the quadrature pulses pull the outputs to ground (in sequence depending upon rotation direction) and thereafter they go back high. I guess this is normal behavior for this encoder type, but since this is my first experience with them I can't be certain...
Rod
If not, can you post a photo?
-Phil
Yes, it does. Here's a link to it: http://www.digikey.com/product-search/en?keywords=PEC11R-4225F-S0024-ND
Rod
I don't know what to suggest, except to get a better encoder. I'm glad I didn't try incorporating one of these into a project!
-Phil
Thanks for spending your time and for your support..
Rod
Can you post a scope capture.
Maybe this is an example of serious price engineering, and the classic Quadrature rules may need to be modified.
If each detent changes both, and they idle HH, maybe the rule needs to be which edge occurs first ?
As they are made in volumes, there has to be some Software solution to using them.
A microcontroller programmed in machine code would be able to keep up with and track the glitchy signals. In this case the bouncing would not ruin the count except for very short-term up-down or down-up intervals that could easily be filtered out. I suspect the market for these encoders is tilted toward micros or PLDs with faster responses than a BASIC Stamp provides.
-Phil
Like Phil I'm getting multiple counts for each detent - usually 3-5. I want just one count. Note in the scope shot that the time during which the two output pulses are unequal is about 22 ms. I'm thinking the problem is NOT so much from switch bounce but it's the code I'm using. Depending upon the speed of the DO loop it can read multiple instances of "unequalness" during that 22 ms. It seems to me the problem could be resolved simply by adding an appropriate PAUSE command inside the loop, thereby slowing down the sample period. But I can't get that to work.
Rod
The code is designed to change the count on each edge from either channel. Because there's a complete cycle of four edges between detents, you get four counts, nominally.
-Phil
It takes advantage of the fact that on detent, both outputs are high. So it keeps track of the motion between detents. Then, when both outputs go high, it checks to see if any motion occurred, and in which direction. Only then does it increment or decrement the count. So you get just one count change per detent.
-Phil
Your code is working great here. Thanks very much.
You've taught me something I didn't know about Stamp. I didn't think that Stamp could read edges. I thought it could only poll its inputs and that it samples at some time period after acknowledging the IN command. Responding to edges is almost as good as having interrupts and of course we know that Stamp doesn't support interrupts.
So, do I have it correct - that an IN command waits for an edge?
-Phil
I use optical encoders and have never needed debounce but I have shown how this could be implemented at label A1B1
The solution to this would require a more stringent test than simply non-zero. For example, you could make sure it was one of -4 (%1100), -3 (%1101), 3 (%0011), or 4 (%0100) before allowing a change in count.
-Phil
The code you posted is working fine with my encoder.