arduino / ArduinoCore-mbed

347 stars 202 forks source link

Access to nRF528x hardware decoder #172

Open alzzxx opened 3 years ago

alzzxx commented 3 years ago

Subject of the issue

I'd like to gain access to the hardware decoder inside the nrF528x, right now I'm reading a quadrature encoder using interrupts on pins 4 (for channel A) and 6 (for channel B), using the InterruptIn mbed instructions, starting from a mbed library found on mbed site, and adapting it to work under arduino core, basically by adding mbed:: before mbed instructions and some callbacks.

    mbed::InterruptIn sqwA;
    mbed::InterruptIn sqwB;
    mbed::InterruptIn pulZero;
    sqwA.rise(mbed::callback(this, &QEI::encode));
    sqwA.fall(mbed::callback(this, &QEI::encode));
    sqwB.rise(mbed::callback(this, &QEI::encode));
    sqwB.fall(mbed::callback(this, &QEI::encode));
    pulZero.rise(mbed::callback(this, &QEI::index));

The code works great for frequencies under 7 kHz, pulse count is correct and also frequency and speed calculations, but when i increase the motor speed i start to lose pulses and the count (and also frequency and speed calculation) goes wrong. So I wanted to see if the problem was the interrupt frequency, maybe is too slow for that motor speed, and I thought that using the hardware decoder was a good option because in theory it gives me the pulse count without any software calculation on the main loop so it should be the fastest option. I started from the example on the nordic SDK 15.0 for the QDEC and a wrote a little sketch to see if I was able to compile it:

#include <hal/nrf_gpiote.h>
#include <hal/nrf_gpio.h>
#include "nrfx_gpiote.h"
#include <hal/nrf_qdec.h>
#include <nrfx.h>
#include <nrfx_qdec.h>

#define NRFX_QDEC_ENABLED 1
#define NRFX_QDEC_CONFIG_REPORTPER NRF_QDEC_REPORTPER_120
#define NRFX_QDEC_CONFIG_SAMPLEPER NRF_QDEC_SAMPLEPER_256us
#define NRFX_QDEC_CONFIG_PIO_A (4u)
#define NRFX_QDEC_CONFIG_PIO_B (6u)
#define NRFX_QDEC_CONFIG_PIO_LED 0xFFFFFFFF
#define NRFX_QDEC_CONFIG_LEDPRE 0
#define NRFX_QDEC_CONFIG_LEDPOL NRF_QDEC_LEPOL_ACTIVE_LOW
#define NRFX_QDEC_CONFIG_IRQ_PRIORITY 2
#define NRFX_QDEC_CONFIG_DBFEN NRF_QDEC_DBFEN_DISABLE
#define NRFX_QDEC_CONFIG_SAMPLE_INTEN NRF_QDEC_INT_SAMPLERDY_MASK

static volatile uint32_t m_accdblread;
static volatile int32_t m_accread;

nrfx_qdec_config_t cfg =
    {
        cfg.reportper = NRFX_QDEC_CONFIG_REPORTPER,
        cfg.sampleper = NRFX_QDEC_CONFIG_SAMPLEPER,
        cfg.psela = NRFX_QDEC_CONFIG_PIO_A,
        cfg.pselb = NRFX_QDEC_CONFIG_PIO_B,
        cfg.pselled = NRFX_QDEC_CONFIG_PIO_LED,
        cfg.ledpre = NRFX_QDEC_CONFIG_LEDPRE,
        cfg.ledpol = NRFX_QDEC_CONFIG_LEDPOL,
        cfg.dbfen = NRFX_QDEC_CONFIG_DBFEN,
        cfg.sample_inten = NRF_QDEC_INT_SAMPLERDY_MASK,
        cfg.interrupt_priority = NRFX_QDEC_CONFIG_IRQ_PRIORITY};

nrfx_qdec_config_t *cfgPoint = &cfg;

static void gpio_config(void)
{
    nrf_gpio_cfg_input(NRFX_QDEC_CONFIG_PIO_A, NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_input(NRFX_QDEC_CONFIG_PIO_B, NRF_GPIO_PIN_PULLUP);
}

static void qdec_event_handler(nrfx_qdec_event_t event)
{
    if (event.type == NRF_QDEC_EVENT_REPORTRDY)
    {
        m_accdblread = event.data.report.accdbl;
        m_accread = event.data.report.acc;
        nrfx_qdec_disable();
    }
}

static void qdec_config(void)
{
    uint32_t err_code;

    // Initialize hardware
    err_code = nrfx_qdec_init(cfgPoint, qdec_event_handler);
    APP_ERROR_CHECK(err_code);
    Serial.println("QDEC testing started");

    nrfx_qdec_enable(); // Event and corresponding interrupt are enabled.
    Serial.println("nrf_drv_qdec_enable");
}

void setup()
{
    Serial.begin(9600);
    gpio_config();
    qdec_config();
}

void loop()
{
    Serial.println(m_accdblread);
    Serial.println(m_accread);
    delay(100);
}

But the problem as commented on arduino/ArduinoCore-nRF528x-mbedos#58, I get the compiler error:

c:\Users\a.rondon\Documents\Arduino\Arduino_VSC\nano33BLE_hardwareDecoder/nano33BLE_hardwareDecoder.ino:65: undefined reference to `nrfx_qdec_init'

c:\Users\a.rondon\Documents\Arduino\Arduino_VSC\nano33BLE_hardwareDecoder/nano33BLE_hardwareDecoder.ino:69: undefined reference to `nrfx_qdec_enable'

and as stated on arduino/ArduinoCore-nRF528x-mbedos#58, the src files for nrfx_qdec.h are missing, I tried copying the files from nordic SDK 15 directly on the sketch folder as suggested by @facchinm but that didn't work either, I took a look at arduino/ArduinoCore-nRF528x-mbedos#72 and what @Polldo said here https://github.com/arduino/ArduinoCore-nRF528x-mbedos/issues/58#issuecomment-625179806, but I think I'm using the right file #include <nrfx_qdec.h>

So, if there is something I could try to solve this problem? There are some mbed API's to read the decoder directly??

Thanks for all the help you could provide guys!!

My workbench

Expected behavior

Well I'd like to use the hardware decoder inside the arduino nano 33 BLE

Actual behavior

The code doesn't compile because it can find the source files for nrfx_qdec.h

facchinm commented 3 years ago

Hi @alzzxx , the quadrature module is not enabled by default in the mbed build, hence the compile time error. The best thing you can do is retrieving nrfx_qdec.c from https://github.com/arduino/mbed-os, remove the #ifdef lines and add it to your sketch. I prepared a zip file with everything in it; it compiles fine but I didn't test if it works correctly :slightly_smiling_face: Try giving it a spin and if you could, please report back since a lot of people might be interested in using that IP :wink:

NANO33BLE_Quadrature_decoder-210329a.zip

alzzxx commented 3 years ago

Gee, thanks, I'll give it a try, and sure i'll report back the result! Thanks again!

Videoworx commented 3 years ago

Hi,

Is anyone able to get this to work? I would very much like to be able to use the built in quadrature decoder.

@facchinm,

I tried your attached file, it compiles but when uploaded the Nano 33BLE freezes. I am a novice at this, so any help would be greatly appreciated! :)