One click-turn of quad encoder produces increment by 4
Erlend
Posts: 612
in Propeller 1
The quad encoder I bought is obviously different from the old one that died. Using the below driver, every click-turn results in the decoded value to increment by 4 (or -4). Assembly has always been my weakness, so although I understand that all it takes is to shift right 2 the result, I do not understand how to do it. Guidance would be nice.
"{{ ┌──────────────────────────────────────────┐ │ Quadrature Decoder │ │ Author: Luke Haywas │ │ │ │ │ │ Copyright (c) <2010> <Luke Haywas> │ │ See end of file for terms of use. │ └──────────────────────────────────────────┘ Description: Uses one cog to continuously monitor a rotary quadrature encoder. As the encoder is turned, each change of position is accumulated to a variable in hub RAM. This variable then reflects how far the encoder has been turned to the left or the right. Wiring: Connect the encoder to two adjacent pins. Pass the number of the first pin as the first parameter of the Start method. Pass the ADDRESS of the variable to accumulate to as the second parameter of the Start method. }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 'use 5MHz crystal clk_freq = (_clkmode >> 6) * _xinfreq 'system freq as a constant mSec = clk_freq / 1_000 'ticks in 1ms uSec = clk_freq / 1_000_000 'ticks in 1us PinQuadA = 20 VAR byte cog LONG gQuadPos OBJ pst : "Parallax Serial Terminal" PUB Main | value pst.Start(9600) 'Remember to start the terminal at 9600b/s WAITCNT(clkfreq + cnt) pst.Str(String("Test of Quad Encoder, press to start")) value := pst.DecIn start(PinQuadA, @gQuadPos) pst.Chars(pst#NL, 2) REPEAT pst.Dec(gQuadPos) WAITCNT(clkfreq/2 + cnt) pst.Chars(pst#NL, 2) PUB start(pin, varaddr) ' Start a cog monitoring the encoder. stop epin1 := pin result := cog := cognew(@quad, varaddr) + 1 {{ Parameters: pin first pin of the encoder input varaddr address of the hub variable to accumulate to Returns: 1 + number of cog it got started in 0 if no cogs available. Note: You can preset the value of the accumulation variable before calling start. Example usage: variable := 25 quad.start(12, @variable) }} PUB stop ' Stop monitoring the encoder. if cog cogstop(cog~ - 1) DAT ORG quad rdlong accum, par ' get initial value of accumulator mov quadmask, #%11 ' initialize encoder mask shl quadmask, epin1 ' bitshift it to encoder pins firstread mov oldstate, ina ' read encoder for the first time and oldstate, quadmask ' call this the "old state" shr oldstate, epin1 ' bitshift it into the LSBs backtostart mov turnpos, oldstate ' PURE VOODOO MAGIC rev turnpos, #30 ' do some funky bit math xor turnpos, #%10 ' new state will match one of these ' whichever it matches = turn direction mov turnneg, oldstate rev turnneg, #30 xor turnneg, #%01 getnewstate mov newstate, ina ' read encoder and newstate, quadmask ' mask it against the encoder mask shr newstate, epin1 ' shift it into the LSBs cmp turnpos, newstate wz ' see if it moved cw if_z jmp #turnedpos cmp turnneg, newstate wz ' see if it moved ccw if_z jmp #turnedneg jmp #getnewstate ' falls through, start over turnedneg add accum, #%1 wrlong accum, par jmp #updatestates ' exit turnedpos sub accum, #%1 wrlong accum, par jmp #updatestates ' exit updatestates mov oldstate, newstate ' mov newstate overwrite oldstate jmp #backtostart epin1 long 12 accum res 1 quadmask res 1 oldstate res 1 turnpos res 1 turnneg res 1 newstate res 1 time res 1 FIT {{ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ TERMS OF USE: MIT License │ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ │is furnished to do so, subject to the following conditions: │ │ │ │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ │ │ │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ }} "
Comments
You might add these methods:
Looking over the PASM code you posted I see that it doesn't allow encoder updates (setting) after it's started. I've attached a dual-encoder object that let's you set each encoder on-the-fly if needed, and accounts for detented encoders that return 4 counts per click.
Good help!
Erlend
New code is attached to my post above.