Encoder with GPIO interrupts

I have an EC11 encoder connected to the SCM20260D and using this to input numeric fields. It kind of works but I am seeing direction changes when I go in 1 direction depending on the speed. I’ve used this encoder before with an STM32 and it was super stable and would count up or down with no reverse pulses detected.

The datasheet says 2-3ms chatter so I set the debounce to 4ms.

Looking at the scope, the pulses look good. I have a 10K pullup and a 0.1uF cap on the input.

This is the count up direction at fast rotation speed. I have the interrupt set for falling edge on the yellow trace and check the blue trace to determine the direction. The scope shows that the pulses are all good with 8ms before the blue trace returns high.

Next is the scope from the other direction, again it all looks good with 6ms before the transition to the other state.

I’ve tried debounce 1ms, 2ms etc and I just don’t get a good response. It doesn’t look good from the operators point of view. Going slow works but that defeats the purpose of the endoder.

How do you disable debounce? Do we just leave this field unset or do we need to set this to ZERO?

Lastly, how does the debounce work? I could not see how the delay is handled in the Library files.

It has been a while but I remember some code from ages ago!! Was this a gadgeteer driver then?

Anyway, do you have some code we can use to look into this for you?

This is the init code. I was careful to ensure that none of the GPIO with the same number is used as per the documents. This is on the SCM20260D.

    encoderA = gpioController.OpenPin(SC20260.GpioPin.PF6);
    encoderB = gpioController.OpenPin(SC20260.GpioPin.PF8);
    encoderButton = gpioController.OpenPin(SC20260.GpioPin.PC13);

    encoderA.SetDriveMode(GpioPinDriveMode.Input);
    encoderB.SetDriveMode(GpioPinDriveMode.Input);
    encoderButton.SetDriveMode(GpioPinDriveMode.Input);

    encoderA.ValueChangedEdge = GpioPinEdge.FallingEdge;
    encoderA.DebounceTimeout = new TimeSpan(0, 0, 0, 0, 2);
    encoderA.ValueChanged += EncoderA_ValueChanged;

    encoderButton.ValueChangedEdge = GpioPinEdge.FallingEdge;
    encoderButton.DebounceTimeout = new TimeSpan(0, 0, 0, 0, 20);
    encoderButton.ValueChanged += EncoderButton_ValueChanged;

This is the interrupt handler.

private static void EncoderButton_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
{
    onEncoderButtonPressed?.Invoke(typeof(IOClass), EventArgs.Empty);
}

private static void EncoderA_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
{
    if (e.Edge == GpioPinEdge.FallingEdge)
    {
        if (encoderB.Read() == GpioPinValue.Low)
        {
            encoderCount++;
        }
        else
        {
            encoderCount--;
        }
        onEncoderValueChanged?.Invoke(typeof(IOClass), EventArgs.Empty);
    }
}

Set it to zero. Unset it will be default 20ms as I remember.

Native does it, library has nothing to do with it.

If we set it to zero and it defaults to 20ms, how do we disable it?