Adding capabilities to my ELS system

Is that 1 count error repeatable. That is, do you see if every single time it rotates 10 revs? Is it cumulative, does it increase for every 10revs back and forth?

So, the only real way for the software encoder to fail would be signals happening to quickly for the interrupts to respond, right? (I think).

If you zoom right into the rising and falling edges of the encoder, ns/div type timescales, do you see any glitches or signal bounces on the rising or falling edges. I often see them on falling edges, but it's possible on rising edges too.
 
Is that 1 count error repeatable. That is, do you see if every single time it rotates 10 revs? Is it cumulative, does it increase for every 10revs back and forth?

So, the only real way for the software encoder to fail would be signals happening to quickly for the interrupts to respond, right? (I think).

If you zoom right into the rising and falling edges of the encoder, ns/div type timescales, do you see any glitches or signal bounces on the rising or falling edges. I often see them on falling edges, but it's possible on rising edges too.
Sort of. What I am seeing is statistical. I have never seen the HW encoder deviate. However, I get some 0's and some 1's for counts with the SW. I've done 100 revs and back, most of the time it's 0, but sometimes not. I've done 10 revs fwd and 11 revs back, all kinds of tests and I don't get any definitive results. It's not bad enough to say it's always off.

This is with no USB Serial active during runtime. No other interrupts are enabled. I'm not using any interrupts, save for what may be in each library.

What's frustrating, and more than a little irritating, is the huge difference in how the two encoders work. The HW seems to be initialized in some sort of way that is reporting the same count, if I go 11T fwd and 10T rev. (I never pass the encoder wheel resolution, how could it know?) But the SW enc reports the difference in counts which is one revolution plus minus error.

I'd like them to report the same way, but both libraries are a bit opaque. That's a fancy way of saying both are NOT WELL DOCUMENTED. There's a dearth of examples, save for the trivial cases.

I'm going to write a better program. It will do the test say 10 times and report on the deviation for each trial.

I see no evidence of glitches on either rising or falling edges, not over 1000's of edges.

Here's 4 runs, using HWenc, and SWenc.
Code:
Using HW encoder
Initial position = 65536
Number of revolutions before reversal = 10.000000, 11.000000

IRQ_TEMPERATURE_PANIC  =    0
IRQ_USB1  =  128
IRQ_ENC1  =   32

Final position = 65536
Error position = 0
Error position = -4096.000000

Using HW encoder
Initial position = 65536
Number of revolutions before reversal = 10.000000, 11.000000

IRQ_TEMPERATURE_PANIC  =    0
IRQ_USB1  =  128
IRQ_ENC1  =   32

Final position = 65536
Error position = 0
Error position = -4096.000000

Using HW encoder
Initial position = 65536
Number of revolutions before reversal = 10.000000, 11.000000

IRQ_TEMPERATURE_PANIC  =    0
IRQ_USB1  =  128
IRQ_ENC1  =   32

Final position = 65536
Error position = 0
Error position = -4096.000000

Using HW encoder
Initial position = 65536
Number of revolutions before reversal = 10.000000, 11.000000

IRQ_TEMPERATURE_PANIC  =    0
IRQ_USB1  =  128
IRQ_ENC1  =   32

Final position = 65536
Error position = 0
Error position = -4096.000000

Using SW encoder
Initial position = 65536
Number of revolutions before reversal = 10.000000, 11.000000

IRQ_TEMPERATURE_PANIC  =    0
IRQ_USB1  =  128
IRQ_GPIO6789  =   32

Final position = 69633
Diff, final-init = 4097
Error position = 1.000000

Using SW encoder
Initial position = 65536
Number of revolutions before reversal = 10.000000, 11.000000

IRQ_TEMPERATURE_PANIC  =    0
IRQ_USB1  =  128
IRQ_GPIO6789  =   32

Final position = 69631
Diff, final-init = 4095
Error position = -1.000000

Using SW encoder
Initial position = 65536
Number of revolutions before reversal = 10.000000, 11.000000

IRQ_TEMPERATURE_PANIC  =    0
IRQ_USB1  =  128
IRQ_GPIO6789  =   32

Final position = 69633
Diff, final-init = 4097
Error position = 1.000000

Using SW encoder
Initial position = 65536
Number of revolutions before reversal = 10.000000, 11.000000

IRQ_TEMPERATURE_PANIC  =    0
IRQ_USB1  =  128
IRQ_GPIO6789  =   32

Final position = 69634
Diff, final-init = 4098
Error position = 2.000000
Same IRQ priority. Count mode is different. One is the reverse of the other. SWenc is occasionally off. This is driving me nuts. Encoders are on the same pins. +/-1 is ok, I guess, not +2. But missing a full rotation on the HW? How does it know what a rotation is? I never passed that information to it? A (unlucky) coincidence?
 
Edit: Maybe I misunderstood what you are describing. I'll leave what I posted below anyway...

The hardware encoder has a modulo count feature. If you tell the library how many pulses per revolution, it will reset it's count modulo that number of counts per rev. Is that what you're running into? I believe if you specify and index pin, or the number of pulses per revolution the library automatically does the modulo math "for you"...

Here's how I configure the encoders in my system, for encoder 2 (change to suite your encoder numbers):

Code:
// create encoder object.
QuadEncoder Enc2(2, ENC2_Apin, ENC2_Bpin);  //Encoder on channel 2

//init encoder in setup().
Enc2.setInitConfig();
Enc2.init();
NVIC_DISABLE_IRQ(IRQ_ENC2);  //Disable encoder interrupts? Are they even used???

//Then read the encoder count values directly from hardware.
ulong Enc2Temp = ENC2_UPOS;  //Capture ENC2 upper bits.
Enc2Temp = (Enc2Temp << 16) | ENC2_LPOSH;  //Read Lower ENC2 Lower Hold register.
 
My encoder config is as follows:
Code:
enableReverseDirection: 0
    decoderWorkMode: 0
    HOMETriggerMode: 0
    INDEXTriggerMode: 0
    IndexTrigger: 0
    HomeTrigger: 0
    clearCounter: 0
    clearHoldCounter: 0
    filterCount: 0
    filterSamplePeriod: 0
    positionCompareValue: ffffffff
    revolutionCountCondition: 0
    enableModuloCountMode: 0
    positionModulusValue: 0
    positionInitialValue: 0
    positionROIE: 0
    positionRUIE: 0
I initialize the position to 64K.
However, if the encoder is rotated forward 10T and reverse 11T, the HW encoder reports 64K again at the end of the test.
I did not program the Modulo Count register, I don't even know how to access it yet.
Why is the HWencoder reporting a count of 64K, when it should be 64K - 4K?

Doesn't QuadEncoder have a method to simply read the 32 bit value in one go? myEnc.read()? I'm not having an issue reading or writing to the encoder count register. The encoder is behaving as if it is modulo, yet I haven't touched the register, nor enabled the modulo count mode.
C++:
int32_t QuadEncoder::read()
{
    uint32_t ret32;

    ret32 = channel[_encoder_ch].ENC->UPOS; /* Get upper 16 bits and make a snapshot. */
    ret32 <<= 16U;
    ret32 |= channel[_encoder_ch].ENC->LPOSH; /* Get lower 16 bits from hold register. */

    return (int32_t) ret32;
}

void QuadEncoder::write(uint32_t value)
{
    channel[_encoder_ch].ENC->UINIT = (uint16_t)(value >> 16U); /* Set upper 16 bits. */
    channel[_encoder_ch].ENC->LINIT = (uint16_t)(value);        /* Set lower 16 bits. */
    
    setConfigInitialPosition();
}
 
Last edited:
Try plot the hardware count value during the run, see if that makes sense?
 
Try plot the hardware count value during the run, see if that makes sense?
FTDI cable isn't here yet, it was delayed until tomorrow. I'll patch something together.

I tried a different "dumber" example program and it works as expected. The count changes sign direction if I change the state of enableReverseDirection.

Dunno, it seems like the index pulse stuff is turned on - making the output modulo, but it is NOT enabled.
 
Dunno, it seems like the index pulse stuff is turned on - making the output modulo, but it is NOT enabled.
IIRC if you specify an index pin, the library automatically does modulo stuff.

That hardware lib was the first thing I played with, even before designing my board. There were some weird things I noticed, and some of that is enabled in the hardware by the library. I eventually figured out how I wanted to use the hardware, and was satisfied with how it all worked. But this details are buried in cob webs in the brain right now! Lol
 
It's irritating, the dumb program works. Mine with adding the stepper, doesn't. I can't read the HW encoder correctly in my original program. I don't know why - I'm getting a constant never changing value. And yes, I'm using volatile for that variable... :bang head:
 
Watch where you initialize pins that the hardware encoder is using. IIRC if you initialize them after you configure the encoder the crossbar mapping will change and no longer be connected. But, it appears that if you initialize them as inputs BEFORE you configure the encoder hardware, it also fails.

I have a note in my initpins() function that "Configuring these as Inputs seems to prevent QuadEncoder from using them". So apparently I had trouble with this at one point...
 
Watch where you initialize pins that the hardware encoder is using. IIRC if you initialize them after you configure the encoder the crossbar mapping will change and no longer be connected. But, it appears that if you initialize them as inputs BEFORE you configure the encoder hardware, it also fails.

I have a note in my initpins() function that "Configuring these as Inputs seems to prevent QuadEncoder from using them". So apparently I had trouble with this at one point...
Thanks for that. Interesting gotcha.

Wish there was a way to enable an interrupt to expose the index pulse so I can check for slipping independently.
 
Back
Top