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

Limits to software quadrature decoder with nrf52840 with softdevice.

Hello list,

Starting from the ble_app_uart example I am trying to create 2 dc motor control loops. Instead of using the uart I use the scheduler to create a simple command loop over BLE to control the app.

There is only 1 QDEC device so I need a software decoder, but that only works when the motor is turning slowly because very soon it seems that interrupts are being missed!

I use one of the encoder inputs to create an interrupt on each transition using GPIOTE. The handler is as follows:

void encoder1Event(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
  if (nrf_drv_gpiote_in_is_set(enca1)) {
    if (!nrf_gpio_pin_read(enca2)) {
      encoder1--;
      nrf_gpio_pin_set(LED_DL3_BLU);
    } else {
      nrf_gpio_pin_clear(LED_DL3_BLU);
      encoder1++;
    }
  } else {
    if (!nrf_gpio_pin_read(enca2)) {
      encoder1++;
    } else {
      encoder1--;
    }
  }
}

Note the LED added for debugging. If the motor is running in one direction, the LED should be continuously the same, say ON.

But as soon as the interrupts are coming as fast as one per millisecond, it seems that interrupts are being missed (a lot!) as shown with the led. This is also shown via the command loop in that encoder1 does not continuously increases as it should in this case. A scope reveals that the encoder signals are as they should be.

I thinks that the only thing that could to this is the softdevice, correct?

Does this mean that interrupts are blocked for 1 msec on a regular base by the softdevice?

Thanks in advance, Sietse

Parents Reply
  • Thanks for the reply.

    I am not using QDEC, now only testing the software encoder using 2 gpiote interrupts.

    From 'Interrupt latency due to SoC framework' I read that there is up to 4 microseconds latency to be expected. Why am I seeing 20 microseconds? I would have thought that only a gpiote interrupt has to be redirected to the app.

    What am I doing wrong here. Nothing is happening: the softdevice is "idling" in the connected state and there can be 2  interrupts from the encoder signal. Nothing more.

Children
  • Hi,

    I see. So you are measuring (with a logic analyzer or similar) the time from a change on a GPIO input to a change on a GPIO output? If so, 20 ms is much, I agree. If the device is in system on low power mode (after a call to sd_app_evt_wait() or _WFE()) the HFINT clock needs to be started, which adds about 4 ms. There are also some microseconds for CPU startup etc, and some CPU cycles for your logic. But it should not add up to anything close to 20 ms.

    Can you share a project that reproduce this so that I can test on my side? Please note that I will be off for Christmas holiday until beginning of January though, so my next reply will probably be delayed until then.

  • I found the reason for the long delay, I think!

    During debugging I did set the gcc optimalisation  to -O0. Setting it to -O3 again made the time drop to a little less than 5 msec.

    When the motor/encoder is to be used, there is no need for a low power mode because the motor is already consuming a lot. Is it possible for force there to be NO low power mode when the motor is used, so programmatically? That would hopefully reduce the latency even further!

    Thanks in advance and happy holidays!

  • Hi,

    Sietse said:

    I found the reason for the long delay, I think!

    During debugging I did set the gcc optimalisation  to -O0. Setting it to -O3 again made the time drop to a little less than 5 msec.

    Ah, good news. That could make sense.

    Sietse said:
    Is it possible for force there to be NO low power mode when the motor is used, so programmatically? That would hopefully reduce the latency even further!

    Yes. A typical SoftDevice application enters system ON low power mode by calling sd_app_evt_wait() in the main loop, either directly or via for instance nrf_pwr_mgmt_run(). To not enter a low power mode, simply do not call any of these functions in the main loop (so here you could check if the motor is in use, and only enter low power mode if it is not).

    Happy New Year!

  • Thanks for the help!

    I wasn't able to mark you last reply as the correct answer, but this will do I guess.

Related