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
  • Did you solve the issue? 
    I am having the same issue. It is triggering two times for 1 step. My encoder is total 24 steps (I counted manually by hand after a full rotation). And I have a 100nF capacitor installed already for de bounce. And the behavior is consistent it always results in two triggers. 

    /*
     * Copyright 2023 Nordic Semiconductor ASA
     * SPDX-License-Identifier: Apache-2.0
     */
    
    / {
    	aliases {
    		qdec0 = &qdec1;
    	};
    };
    
    &qspi {
    	status = "disabled";
    };
    
    &uart0 {
    	status = "disabled";
    };
    
    &pinctrl {
    	qdec_pinctrl: qdec_pinctrl {
    		group1 {
    			psels = <NRF_PSEL(QDEC_A, 0, 18)>,   /* Ardiuno A0 */
    				<NRF_PSEL(QDEC_B, 0, 19)>;   /* Arduino A2 */
    		};
    	};
    };
    
    &qdec1 {
    	status = "okay";
    	pinctrl-0 = <&qdec_pinctrl>;
    	pinctrl-names = "default";
    	steps = < 24 >;
    	led-pre = < 500 >;
    };
    


    And my code

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/drivers/sensor.h>
    #include <zephyr/sys/printk.h>
    
    
    int main(void)
    {
    	struct sensor_value val;
    	int rc;
    	const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(qdec0));
    
    	if (!device_is_ready(dev)) {
    		printk("Qdec device is not ready\n");
    		return 0;
    	}
    
    	printk("Quadrature decoder sensor test\n");
    
    
    	while (true) {
    		/* sleep first to gather position from first period */
    		k_msleep(1);
    
    		rc = sensor_sample_fetch(dev);
    		if (rc != 0) {
    			printk("Failed to fetch sample (%d)\n", rc);
    			return 0;
    		}
    
    		rc = sensor_channel_get(dev, SENSOR_CHAN_ROTATION, &val);
    		if (rc != 0) {
    			printk("Failed to get data (%d)\n", rc);
    			return 0;
    		}
    
    		if (val.val1 > 0) {
    			printk("Rotation: %d\n", val.val1);
    		} else if (val.val1 < 0) {
    			printk("Rotation: %d\n", val.val1);
    		}
    	}
    	return 0;
    }


    If I increase the sleep time to 1000ms then for 1 step I get single trigger and 30 degrees rotation which is not correct, it should be 15 degrees, meaning that it is still double triggering but just giving single output.

  • I guess the problem is my misunderstanding of the QDEC peripheral. The table in this shows how the increments or decrements are measured. And I now realized that this behavior of double triggering is actually consistent with the table 1. 

Reply Children
No Data
Related