Setting QDEC sampleper value via driver API.

Hi!
I am struggling with figuring out how to properly set the sampling frequency for the qdec device. I noticed that making changes directly to the members of config struct of zephyr/drivers/sensor/qdec_nrfx/qdec_nrfx.c seems to do the trick, but I would rather do the changes via device API. 
I noticed that the nrfx_qdec.c driver seem to use necessary API functions declared in nrf_qdec.h. However the function parameters in nrf_qdec_sampleper_set(). Have wrong types compared with nrfx driver. Is there a standardized way of changing the sampling frequency of the qdec device?

Thanks in advance.

Parents
  • Hi Lukasz

    As a general rule when using Nordic peripherals in a Zephyr (or nRF Connect SDK) project you can choose between using the nrfx API, or use the Zephyr driver if one exists. 

    Using the nrfx API will usually expose more Nordic specific functionality, and allow you to use older software based on the nRF5 SDK, while using the Zephyr driver allows you to write code more aligned to other Zephyr examples. 

    In this case, if using the qdec_nrfx.c driver does not allow you to set the sample period in a streamlined way I would suggest using the nrfx_qdec driver directly.

    Best regards
    Torbjørn

  • Since the nrfx_qdec_init() requires a qdec_nrfx_event_handler  I have written a short switch case handler that only printsout some values. I also see that the init function does enable the qdec via nrfx_qdec_enable call, but I added said call nonetheless to my init function.

    I also created the manual_isr_setup() function to enable interrupt as was suggested by your newest reply. 
    I'm currently unable to figure out why my IRQ setup results in "Spurious Interrupt" behaviour. The code used is shown below:

    void StepperControl::init()
    {
        qdec_device_ = device_get_binding(DT_LABEL(DT_NODELABEL(qdec)));
        if (!qdec_device_) {
            asm("nop");
        }
    
        static nrfx_qdec_config_t config0 =
        {
            .reportper          = NRF_QDEC_REPORTPER_40,
            .sampleper          = NRF_QDEC_SAMPLEPER_2048us,
            .psela              = DT_PROP(DT_NODELABEL(qdec),a_pin),
            .pselb              = DT_PROP(DT_NODELABEL(qdec),b_pin),
            .pselled            = 0xFFFFFFFF,
            .ledpre             = 500,
            .ledpol             = NRF_QDEC_LEPOL_ACTIVE_HIGH,
            .dbfen              = NRF_QDEC_DBFEN_DISABLE,
            .sample_inten       = false,
            .interrupt_priority = NRFX_QDEC_DEFAULT_CONFIG_IRQ_PRIORITY
        };
     
        nrfx_qdec_init(&config0, qdec_nrfx_event_handler);
        nrfx_qdec_enable();
        manual_isr_setup();
    
    }

    static void qdec_nrfx_event_handler(nrfx_qdec_event_t event)
    {
        printk("Enetered qdec_nrfx_event_handler \n");
    	switch (event.type) {
        case NRF_QDEC_EVENT_SAMPLERDY:
            
           
            printk("SAMPLERDY interrupt \n");
            break;
    
    	case NRF_QDEC_EVENT_REPORTRDY:
          
            accumulate(&qdec_nrfx_data, event.data.report.acc);
            printk("REPORTRDY event handled");
            break;
        default:
          
            printk("unhandled event (0x%x) \n", event.type);
            break;
        }

    static void manual_isr_setup(void){
        IRQ_DIRECT_CONNECT(QDEC_IRQn,0,
                    nrfx_qdec_irq_handler,0);
        
    	irq_enable(QDEC_IRQn);
    
    }

Reply
  • Since the nrfx_qdec_init() requires a qdec_nrfx_event_handler  I have written a short switch case handler that only printsout some values. I also see that the init function does enable the qdec via nrfx_qdec_enable call, but I added said call nonetheless to my init function.

    I also created the manual_isr_setup() function to enable interrupt as was suggested by your newest reply. 
    I'm currently unable to figure out why my IRQ setup results in "Spurious Interrupt" behaviour. The code used is shown below:

    void StepperControl::init()
    {
        qdec_device_ = device_get_binding(DT_LABEL(DT_NODELABEL(qdec)));
        if (!qdec_device_) {
            asm("nop");
        }
    
        static nrfx_qdec_config_t config0 =
        {
            .reportper          = NRF_QDEC_REPORTPER_40,
            .sampleper          = NRF_QDEC_SAMPLEPER_2048us,
            .psela              = DT_PROP(DT_NODELABEL(qdec),a_pin),
            .pselb              = DT_PROP(DT_NODELABEL(qdec),b_pin),
            .pselled            = 0xFFFFFFFF,
            .ledpre             = 500,
            .ledpol             = NRF_QDEC_LEPOL_ACTIVE_HIGH,
            .dbfen              = NRF_QDEC_DBFEN_DISABLE,
            .sample_inten       = false,
            .interrupt_priority = NRFX_QDEC_DEFAULT_CONFIG_IRQ_PRIORITY
        };
     
        nrfx_qdec_init(&config0, qdec_nrfx_event_handler);
        nrfx_qdec_enable();
        manual_isr_setup();
    
    }

    static void qdec_nrfx_event_handler(nrfx_qdec_event_t event)
    {
        printk("Enetered qdec_nrfx_event_handler \n");
    	switch (event.type) {
        case NRF_QDEC_EVENT_SAMPLERDY:
            
           
            printk("SAMPLERDY interrupt \n");
            break;
    
    	case NRF_QDEC_EVENT_REPORTRDY:
          
            accumulate(&qdec_nrfx_data, event.data.report.acc);
            printk("REPORTRDY event handled");
            break;
        default:
          
            printk("unhandled event (0x%x) \n", event.type);
            break;
        }

    static void manual_isr_setup(void){
        IRQ_DIRECT_CONNECT(QDEC_IRQn,0,
                    nrfx_qdec_irq_handler,0);
        
    	irq_enable(QDEC_IRQn);
    
    }

Children
Related