Need help getting a encoder index working
krazyideas
Posts: 119
So first off just so you know how much of a beginner I am, I just picked up the reference manul and started programing.
Ok so I can reason through Spin sufficently for my little programs and they work But when it comes to Assembly, I can't make heads or tails of it . I spend about 4 hours today trying with no success.
So now My problem.
I am using a E2 encoder with an index from US digital to run a home made electric motor with my Dad. I got the program running and working, BUT it can only operate at about 1600 RPM. I poked and proded at my program untill I found the part that was causeing the problem.
Which is that my counter (In Spin) can't keep up. So I tryed to convert it to assembly but because assembly is so complicated I ended up looking on the object exchange and found a encoder counter Called "IdxquadDecoder." It's overview says
"Modified Quadrature Decoder object by Luke Hays to use a third pin to preset encoder count to any value allowing the calculation of absolute encoder angle. See Luke Hays' example for reference. The same except uses third pin for index and allows preset by setting the value of BigValue in the asm section of the program."
I got it counting beautifuly, much cleaner then my Spin attempt. But I need the counter or "count register" to be reset to "0" each time the index is triggered, which is once a rotation. I understand in the overview that this is what it does but I can't make it do it.
Can someone point out where in the code I need to change something and please remember I'm clueless.
Here's the Code.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 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.
Ok so I can reason through Spin sufficently for my little programs and they work But when it comes to Assembly, I can't make heads or tails of it . I spend about 4 hours today trying with no success.
So now My problem.
I am using a E2 encoder with an index from US digital to run a home made electric motor with my Dad. I got the program running and working, BUT it can only operate at about 1600 RPM. I poked and proded at my program untill I found the part that was causeing the problem.
Which is that my counter (In Spin) can't keep up. So I tryed to convert it to assembly but because assembly is so complicated I ended up looking on the object exchange and found a encoder counter Called "IdxquadDecoder." It's overview says
"Modified Quadrature Decoder object by Luke Hays to use a third pin to preset encoder count to any value allowing the calculation of absolute encoder angle. See Luke Hays' example for reference. The same except uses third pin for index and allows preset by setting the value of BigValue in the asm section of the program."
I got it counting beautifuly, much cleaner then my Spin attempt. But I need the counter or "count register" to be reset to "0" each time the index is triggered, which is once a rotation. I understand in the overview that this is what it does but I can't make it do it.
Can someone point out where in the code I need to change something and please remember I'm clueless.
Here's the Code.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 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.
VAR byte cog 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 mov IndexMask, #%100 'Mask for Index Pulse *** shl IndexMask, epin1 'Shift to proper pin *** 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 mov MarkIndex, newstate ' Get unmasked index pin *** and MarkIndex, IndexMask wz ' Mask pins other than index *** if_z jmp #over ' Skip accum 0 if index is 0*** mov accum, #0 over 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 IndexMask res 1 MarkIndex res 1 FIT
Comments
Do you not want to use the pin to clear the accumulator but to have the accumulator zero itself once a complete revolution has been made?
If you want to zero the accumulalator once it has reached a certain value, you could add a couple of "cmpsub" statements to the code right before the accumulator is written to the hub.
You'd want to add "pulsesPerRev" as one of your PASM variables. You could preset the value of "pulsesPerRev". For example, if your encoder produced 300 pulses per revolution, you'd change the variable section to:
This is the quick way to set a variable value. There are better ways of setting variables than this.
Edit: I realized you'd need to test for the negative value of pulsesPerRev if the wheel is turning backward. I'm not sure why "turn" labels appear to be opposite in the code.
BTW, When I added encoder support to my Mecanum wheeled robot, I modified JonnyMac's code from his Spin Zone #6 article. I personally think JonnyMac's code was easier to follow and modify than the code you posted.
I'll let you know if I get it working today
And what I really want the to program to do IS to reset the accumulator to Zero each time the index pin is triggered.
But I think just resetting the accumulator at a certen value will work, not as quite as well because if it was reset each time the index was triggered it would eliminate any possible accumulation errors at the start of each rotation of the encoder.
I couldn't make the accumulator reset to Zero and I tryed toggleing each pin individualy, but none of the pins reset it.
Thanks again
carefully looking thru the code I was not able to find any obvious mistakes.
you are using 3 pins to the propeller ? how did you connect your encoder?
the PURE MAGIC you found there is actually pretty neat. a quadrature encoder uses 2 signals (the first two pins) to count and decide in which direction to count. So it compares two readouts to find out which signal came first.
and it checks the third pin and resets the counter to 0 when that third pin is low. But it is adding/subtracting the movment after resetting so you will actually never SEE zero but 1 or -1.
just put some buttons on a breadboard and test it by hand. IMHO it should work like coded.
Enjoy!
Mike
So I have the index connected to pin 0. Then the other two pins connected to pin 1 and 2.
Where it reads
I am passing pin 1, so in effect it reads
So as I understand it that passes pin 1 and pin 2 to be the inputs from the encoder. But what pin do I connect the index pin to ???? I think I tryed all of them but mabe I missed one.
Any thoughts?
Thanks
So I have the index connected to pin 0. Then the other two pins connected to pin 1 and 2.
Where it reads
I am passing pin 1, so in effect it reads
So as I understand it that passes pin 1 and pin 2 to be the inputs from the encoder. But what pin do I connect the index pin to ???? I think I tryed all of them but mabe I missed one.
Any thoughts?
Thanks
Andy
I noticed the "12" also. I don't think it matters though since the start method overwrites the "epin1" value before starting the cog.
I also wrote another little program to make sure that the prop was feeling the index when it went low and high, by turning a LED on and off through the prop based on the condition of the index pin. It worked fine.
This is the demo program I have been useing to read the value of the count
% Quadrature Decoder DEMO %
% Author: Luke Haywas %
% %
% %
% Copyright (c) <2010> <Luke Haywas> %
% See end of file for terms of use. %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Description:
Demonstrates how to use my object QuadDecoder.
Quadrature encoder is connected to pins 1 and 2.
(If connected to different pins, simply change the
value of ENCODER_PIN below)
Displays value of the accumulated variable in
the serial debug terminal.
}}
I've tryed everything I can think of.
Thanks
I can really see the advantage of assembly vs spin but where would a fellow go for a couple of really good tutorals that explained thins well?
Thanks again
I can really see the advantage of assembly vs spin but where would a fellow go for a couple of really good tutorals that explained thins well?
Thanks again
The line before "over" sets the accumulator to zero. If P3 is low, this line gets skipped (the z flag would be set by the "and" statement, so "if_z" is true), if P3 is high the variable "accum" is set to zero.
Thank you guys so much for the help. And the patience with a begginer.
You guys are great.
Take care