Rotary Encoder Help
Hey all!
I'm having a tough time figuring out how to read my rotary encoder to the propeller as is is not the common 2-bit type.
Data Sheet : http://www.alps.com/WebObjects/catalog.woa/E/HTML/Encoder/Incremental/EC11/EC11EH224403.html
If any one could clue me in as to how to read this "ABC Switch"? type of encoder it would be of great help as I would like to use this as the interface for a Tesla coil driver I am building based around the propeller.
Thanks in advance for any help
-ADZ
I'm having a tough time figuring out how to read my rotary encoder to the propeller as is is not the common 2-bit type.
Data Sheet : http://www.alps.com/WebObjects/catalog.woa/E/HTML/Encoder/Incremental/EC11/EC11EH224403.html
If any one could clue me in as to how to read this "ABC Switch"? type of encoder it would be of great help as I would like to use this as the interface for a Tesla coil driver I am building based around the propeller.
Thanks in advance for any help
-ADZ

Comments
http://obex.parallax.com/objects/666/
http://obex.parallax.com/objects/24/
So far I have written some simple code that checks the input pins and displays the binary output through the serial terminal as expected i see:
CW
%010
%001
%100
CCW
%010
%100
%001
with only a one bit change between detents.
If you could include some simple code that dispays a value in the serial terminal that is manipulated by the knob I would be very gratefull
Thanks Again!
-ADZ
'******************************************************************************************************** ' input is the 3 bits read from the encoder ' old is the previous value read from the encoder ' count is a variable that is incremented or decremented based on the direction the encoder is turned '******************************************************************************************************** case input %001: case old %010: count := count - 1 ' going ccw subtract 1 from count %100: count := count + 1 ' going cw add 1 to count %010: case old %100: count := count - 1 ' going ccw subtract 1 from count %001: count := count + 1 ' going cw add 1 to count %100: case old %001: count := count - 1 ' going ccw subtract 1 from count %010: count := count + 1 ' going cw add 1 to count old := input '{3-bit encoder reader -ADZ} CON _clkmode = xtal1 + pll8x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 10_000_000 VAR long old long input long count OBJ pst : "Parallax Serial Terminal" PUB Main init count := 50 repeat input := ina pst.str(string("Raw Input = ")) pst.bin(input,3) pst.Chars(pst#NL, 1) read pst.str(string("Current Count = ")) pst.dec(count) waitcnt(clkfreq / 20 + cnt) pst.clear PUB read '******************************************************************************************************** ' input is the 3 bits read from the encoder ' old is the previous value read from the encoder ' count is a variable that is incremented or decremented based on the direction the encoder is turned '******************************************************************************************************** NOTE THAT THIS CODE IS NOT SHOWING UP CORRECTLY ON THE FORUM BUT IS EXACTLY AS POST #5 FROM kwinn case input 1: case old 0: count := count - 1 ' going ccw subtract 1 from count 0: count := count + 1 ' going cw add 1 to count 0: case old 0: count := count - 1 ' going ccw subtract 1 from count 1: count := count + 1 ' going cw add 1 to count 0: case old 1: count := count - 1 ' going ccw subtract 1 from count 0: count := count + 1 ' going cw add 1 to count old := input ' PRI init pst.start(921_600) 'dira := 0Thanks!
-ADZ
Again any help would be greatly appreciated as i am currently stumped.
repeat input := ina pst.str(string("Raw Input = ")) pst.bin(input,3)Well, for one thing you have not selected any pins to input in the ina. The statement should be ina [Px..Py] where x is the first pin and y is the last pin. As it is you are inputting all 32 pins. That means the case statement is looking at all 32 pins as well so the chance of a match is pretty slim.The other thing to do is to manually enter the code I posted. It looks like you may have cut and pasted it and it is possible some non printable characters got inserted.
PUB Main init count := 50 repeat input := ina[0..2] pst.str(string("Raw Input = ")) pst.bin(input,3) pst.Chars(pst#NL, 1) read pst.str(string("Current Count = ")) pst.dec(count) waitcnt(clkfreq / 20 + cnt) pst.clearand have double checked my read routine and it is exactly as in your previous post. The count variable just sits there at 50 or 0 if I don't pre-initilize it.The input variable however changes as expected. Still cant figure out exactly what I'm doing wrong here.
Thanks again for being so patient and helpful.
-ADZ
Thanks again!
-ADZ
gets me the result of one click cw and the number continually counts up and if i move it once ccw it continually counts down. I think I'm close!
EDIT : it seams that turning th knob has this result, one click cw and it continually counts up, next click in the same direction and it continually counts down, on the next click in the same direction the count stops. Not sure whats going on here. Ideally the count would increment by 1 for every forward click and decrement by 1 for reverse.
CON _clkmode = xtal1 + pll8x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 10_000_000 VAR long old long input long count long count1 OBJ pst : "Parallax Serial Terminal" PUB Main init count := 50 repeat input := ina[0..2] if input <> old ' see if the switch input has changed pst.str(string("Raw Input = ")) ' no point printing all this if the pst.bin(input,3) ' switch has not moved pst.Chars(pst#NL, 1) read ' increment or decrement the counter pst.str(string("Current Count = ")) pst.dec(count) ' waitcnt(clkfreq / 20 + cnt) ' not really needed now pst.clear PRI read '******************************************************************************************************** ' input is the 3 bits read from the encoder ' old is the previous value read from the encoder ' count is a variable that is incremented or decremented based on the direction the encoder is turned '******************************************************************************************************** case input %001: case old %010: count := count - 1 ' going ccw subtract 1 from count %100: count := count + 1 ' going cw add 1 to count %010: case old %100: count := count - 1 ' going ccw subtract 1 from count %001: count := count + 1 ' going cw add 1 to count %100: case old %001: count := count - 1 ' going ccw subtract 1 from count %010: count := count + 1 ' going cw add 1 to count old := input PRI init pst.start(921_600) 'dira := %000 DAT name byte "string_data""Got to input case 001"
However the counter is still not incrementing. I also posted this on the propeller 1 forum and got some useful code that with a few small changes does exactly what I was looking for, a counter that increments and decrements one per detent and resets with the pushbutton:
CON _clkmode = xtal1 + pll8x _xinfreq = 10_000_000 knob_basepin = 0 knob_button = 3 ' Requires 3 pins to sense direction of rotation, offset is set to the lsb ' Clockwise rotation produces the pattern 011, 110, 101 (with common on ground and pullups on pins) VAR byte knob_pos long counter OBJ pst : "Parallax Serial Terminal" PUB Main pst.start(921_600) ' Initialize serial terminal knob_pos := knob_position ' Initialize knob position repeat ' Repeat loop if CW ' If CW sub-routine returns true counter++ ' increment counter variable by 1 if CCW ' If CCW sub-routine returns true counter-- ' deincrement counter variable by 1 if ina[3] == 0 ' If button pressed counter := 0 ' Reset counter to zero pst.dec(counter) ' Display current counter waitcnt(clkfreq / 100 + cnt) ' Delay to alow time to view terminal display pst.clear ' Clear screen to keep cursor in the same position PRI Knob_position : pos pos := (ina >> knob_basepin) & 1 PRI CW | c_pos c_pos := Knob_position if (c_pos == 1 and knob_pos == 0) or (c_pos == 0 and knob_pos == 1) or (c_pos == 1 and knob_pos == 1) knob_pos := c_pos result := 1 PRI CCW | c_pos c_pos := Knob_position if (c_pos == 1 and knob_pos == 1) or (c_pos == 1 and knob_pos == 0) or (c_pos == 0 and knob_pos == 1) knob_pos := c_pos result := 1the thing with this is that I had to wire pullups for each switch pin as apposed to one pullup to 3.3vEDIT: Code will not paste correctly, file is attached.ABC_Encoder.spin
Thanks again for all your help!
If you have break before make sensor, you will go via 000, and your present state structure will fail.
You can either cover all states, or pull in the old := input line, to be inside only the valid states.(as below)
This means old can now only have one of three values - before it could have 8 possible values.
It will take a couple of clicks for the state engine to 'grabs' the right phase, but from there it should ignore 000 and 111, and other states, and
edge-act only on the valid three.
{case input %001: pst.str(string("Got to input case 001")) case old %010: count := count - 1 ' these are one-shot state branches, as old becomes %001 %100: count := count + 1 ' %001 is no change, or no edge, so cycles many times, waiting for next change old := input %010: pst.str(string("Got to input case 010")) case old %100: count := count - 1 %001: count := count + 1 ' %010 is no change, or no edge, so cycles many times, waiting for next change old := input %100: pst.str(string("Got to input case 100")) case old %001: count := count - 1 %010: count := count + 1 ' %100 is no change, or no edge, so cycles many times, waiting for next change old := input }Regarding post 23: The most popular method of connecting this type of encoder is to have the switch common connected to ground and 3 pullup resistors to V+ on the switch outputs. The alternative is to have the common go to V+ and pulldown resistors to ground. The resistors are required to avoid floating inputs.