This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Quadrature decoder settings for motor encoder

Hello community,

I tried to read my motor encoders with the QDEC and capture the position of my motor.
Hardware: nRF52840 DK, 2 Hal motor encoders on pin 0.13 and 0.14 which are supplied with an external voltage of 3.3V.

Unfortunately, in my test setups either more edges were detected than available, or not all were detected because supposedly 2 edges occurred at the same time.

In the settings I could only find one setting at the time at which the QDEC should measure. Can this be changed so that the QDEC only reacts when it detects an edge and also recognizes this only once?

I have already experimented with different speeds, but as long as I do not come exactly to the time I have set in the QDEC come again and again errors and the Morot position does not fit.

PS: I have realized it temporarily with an interrupt when changing the state of these two pins, but this is relatively complicated by the comparison with the position of the other encoder and the detection of the direction of rotation.

Maybe one of you has already experiences with the QDEC and can tell me where I can make further settings except in the sdk_config.h.

Thanks in advance

Translated with www.DeepL.com/Translator (free version)

Parents
  • Hi

    Do you know what the maximum frequency of your decoder signal will be?

    What is the value of the SAMPLEPER register in the QDEC, which sets the sampling rate of the QDEC?

    Have you tried to enable the debounce filter in order to handle glitches on the inputs?

    Best regards
    Torbjørn

  • Hi Torbjorn,

    I have two motor encoders each with a max frequency of about 470 Hz. Because I drive the motor with a PWM this frequency changes constantly.

    In the SAMPLEPER register I have currently set 1024us, but here I have also tried all other values. (with moderate success)

    I have activated the debounce filter.

    Is there a possibility to let the QDEC trigger not on the SAMPLEPER register but on the toggling of the inputs?

    Best regards

  • Hi 

    For clarity, when you say 'two motor encoders' it sounds like you mean two separate encoders that are independent of each other. I assume that is not the case?

    The QDEC only supports one encoder that outputs two phases. 

    It is possible to connect these signals to GPIO interrupts instead of the QDEC, if you want to process them immediately. 

    It is also possible to connect the signals to a timer through the PPI controller, allowing you to measure the length of each pulse with an accuracy of 62.5ns (16MHz base timing). 

    Best regards
    Torbjørn

  • Hi,

    yes it is an encoder with two phases which are offset by approx. 90°.

    My current solution is with interrupts, I trigger the interrupt and decide in it with the help of a variable and the old encoder values in which direction the motor turns.

    So it already works, I just wanted to get some more basic information about the QDEC's setting options for such an application.

  • Hi 

    Are you able to share your code with me, showing how you initialize the QDEC and how the interrupts are handled?

    I can make the case private if you don't want to share your code in a public case.

    Best regards
    Torbjørn

  • #include "includes.h"
    
    
    APP_PWM_INSTANCE(motor_pwm, PWM_TIMER);
    
    
    int main(void)
    {
    
        while(1)
        {
              if(flag == 0b00000000)
              {
                  initialisierung_aller_komponenten();
                  initialisierung_pwm(&motor_pwm);
              }
    
              if(nrf_gpio_pin_read(BUTTON_CUSTOM_1) == 0 && flag == 0b00000001)
              {
    
                  while (MOTOR_STELLUNG <= 1000)
                  {
                      for (number_of_pulses=min_number_of_pulses; number_of_pulses<= max_number_of_pulses; number_of_pulses++ )
                      {
                            pulses = number_of_pulses; 
                            nrf_drv_qdec_enable();                  
                            m_report_ready_flag = false;
                            if(nrf_qdec_sample_get() == 1)
                            {
                                  MOTOR_STELLUNG = MOTOR_STELLUNG + 1;
                            }
                            else if(nrf_qdec_sample_get() == (-1))
                            {
                                  MOTOR_STELLUNG = MOTOR_STELLUNG - 1;
                            }
                            NRF_QDEC->TASKS_READCLRACC;
                      }
                      min_number_of_pulses  = 1;       
                      NRF_LOG_RAW_INFO("MOTOR_STELLUNG: %d \r\n", MOTOR_STELLUNG);
                      NRF_LOG_FLUSH();
                  }
              }
        }
    }

    This is my main.c.

    In the function initialisierung_aller_komponenten() are only a few settings for my other pins and the button.

    void qdec_event_handler(nrf_drv_qdec_event_t event)
    {
        if (event.type == NRF_QDEC_EVENT_REPORTRDY)
        {
            m_accdblread        = event.data.report.accdbl;
            m_accread           = event.data.report.acc;
            m_report_ready_flag = true;
            nrf_drv_qdec_disable();
        }
    }
    

    This is my functions_qdec.c.

  • Hi 

    I see you have based your code on the SDK example. 

    To be honest I am not sure exactly what the SDK example is trying to show, so I made my own modified example instead:

    273524_qdec_simple.zip

    This example sets up a simulated QDEC signal on pins 3 and 4, and configures the QDEC peripheral to use inputs 29 and 30. 

    Every time a new report is ready it simply prints the status of that report to the log, and lets the QDEC run continuously. 

    Can you give this example a go and see if it works better?

    If you connect the simulated pins to the input it should report a frequency of ~200Hz, as set by the call to qdec_simulator_set(200); in main.c

    If you connect your own input it should hopefully show the speed of your motor. 

    I moved all the QDEC parameters into the main function to make it more obvious how the QDEC is configured. 

    Best regards
    Torbjørn

Reply
  • Hi 

    I see you have based your code on the SDK example. 

    To be honest I am not sure exactly what the SDK example is trying to show, so I made my own modified example instead:

    273524_qdec_simple.zip

    This example sets up a simulated QDEC signal on pins 3 and 4, and configures the QDEC peripheral to use inputs 29 and 30. 

    Every time a new report is ready it simply prints the status of that report to the log, and lets the QDEC run continuously. 

    Can you give this example a go and see if it works better?

    If you connect the simulated pins to the input it should report a frequency of ~200Hz, as set by the call to qdec_simulator_set(200); in main.c

    If you connect your own input it should hopefully show the speed of your motor. 

    I moved all the QDEC parameters into the main function to make it more obvious how the QDEC is configured. 

    Best regards
    Torbjørn

Children
No Data
Related