Nrfx_qdec double trigger for one turn

I am having an issue with the nrfx_qdec driver in zephyr, I am trying to simply detect when the turn happens and the direction of the turn is.
Most of the time this is triggered fine, but sometimes for one turn of the encoder I get 2 triggers, I am trying to figure out how I should best debounce this, whether in the qdec configuration 
or something on the my side in data_ready_handler for example.
I am using NRF connect SDK v2.9.1 in VScode
MCU is nrf52810_xxAA_REV2
qdec dts config 
&qdec {
    status = "okay";
    pinctrl-0 = <&qdec_default>;
    pinctrl-1 = <&qdec_sleep>;
    pinctrl-names = "default", "sleep";

    steps = <20>;
    led-pre = <0>;
};

Here is the code I am using to test out the qdec.

static
void data_ready_handler(const struct device *dev, const struct sensor_trigger *trig)
{
    struct sensor_value value;

    int err = sensor_sample_fetch_chan(qdec_dev, SENSOR_CHAN_ROTATION);

    if (err)
    {
        LOG_ERR("Cannot fetch sensor sample (err %d)", err);
        return;
    }

    err = sensor_channel_get(qdec_dev, SENSOR_CHAN_ROTATION, &value);
    if (err)
    {
        LOG_ERR("Cannot get sensor value");
        return;
    }

    int rc;

    LOG_INF("Position = %d degrees\n", value.val1);
    if (value.val1 > 0)
    {
        LOG_INF("+\n");
        device_state = RUNNING;
        uint8_t brightness = get_brightness();
        if (brightness != increment_brightness())
        {
            // only set if the brightness changed
            set_segment_led();
        }
    }
    else if (value.val1 < 0)
    {
        LOG_INF("-\n");

        device_state = RUNNING;
        uint8_t brightness = get_brightness();
        if (brightness != decrement_brightness())
        {
            // only set if the brightness changed
            set_segment_led();
        }
    }
}

void qdec_setup()
{
    struct sensor_value val;
    int rc;

#ifdef QUAD_ENC
    static const struct sensor_trigger qdec_trig = {
        .type = SENSOR_TRIG_DATA_READY,
        .chan = SENSOR_CHAN_ROTATION,
    };
    // setup the callback for when the qdec is triggered
    int err = sensor_trigger_set(qdec_dev, (struct sensor_trigger *)&qdec_trig,
                                 data_ready_handler);
    if (err)
    {
        LOG_ERR("Cannot setup trigger");
    }
    return;
#endif
}
Should I be reading the sensor differently or configuring it to debounce? It seems that the double turns happen within under 100ms of each other.
Parents Reply Children
  • Hey Kenneth, thank you for the reply, I'm not sure exactly what part of those sections you are referring that I should look at? I didn't see my problem described in that page.

    To be clear my problem is turning the quadrature encoder a single step sometimes generates two rotation triggers in that direction, when it should only be one. 

  • I would likely have tried with debounce as first step. But if you want to debug this I would have connected a logic analyzer to the qdec input pins and a debug output pin from the application that toggle when you experience irregularities Then you can go shortly back in time and hopefully find the issue.

    Edit: Can you try with steps = 4. Then on every 4 transitions = one full detent.  Do you see the same problem then?

    Kenneth

  • Hello Kenneth,
    Gave this a try and still no luck, even with counting a 4 transitions for a single detent still getting incorrect events sometimes. I will add I have watched the quadrature signals on a oscilloscope and they seem to be clean and as expected even when I get these multiple triggers for one step of the encoder. I also don't think that debouncing will solve my problem now as turning the encoder very slowly can result in 3 or more triggers at any time for one step of the encoder. 

    Not sure where to go from here at least on using the qdec peripheral side.  

    Here's a screenshot of the oscilloscope when I got a double trigger. Signals look as expected in my opinion.

  • Hmmm... can you try to use sample-period = 3 (1024us), also enable debouncing (NRF_QDEC->DBFEN = 1) in any case?

    The only thing I can think of is that thode edges as not as "clean" as we think.

    Kenneth


  • No luck here either very slow turns still result in more than one trigger. 
    Signals looked good here as well.
    Gave it a try setting up like this (had to grab that qdec_nrfx_config struct from the nrfx_qdec zephyr driver)
    struct qdec_nrfx_config
    {
        nrfx_qdec_t qdec;
        nrfx_qdec_config_t config;
        void (*irq_connect)(void);
        const struct pinctrl_dev_config *pcfg;
        uint32_t enable_pin;
        int32_t steps;
    };

        struct qdec_nrfx_config *config = dev->config;
        nrfx_qdec_disable(&config->qdec);
        config->config.sampleper = NRF_QDEC_SAMPLEPER_1024US;
        config->config.dbfen = true;
        nrfx_err_t nerr;
        nerr = nrfx_qdec_reconfigure(&config->qdec, &config->config);
        nrfx_qdec_enable(&config->qdec);

        if (nerr != NRFX_SUCCESS)
        {
            LOG_ERR("Cannot reconfigure qdec");
        }
Related