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

TIMER + PWM + SAADC + PPI

I'd like to control a DC motor using PWM (PWM0, pretty straight forward). To determine motor speed I disable the PWM every 5ms (TIMER1, pretty straight forward) and measure Back-EMF via SAADC. To synchronise this I'd like to use PPI

In order to implement a stable solution I'd like to clarify a few things with you:

1. Start SAADC

err = nrf_drv_ppi_channel_assign (ppiCh, (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[1], (uint32_t)&NRF_SAADC->TASKS_START);

NRF_PPI->FORK[ppiCh].TEP = (uint32_t)&NRF_SAADC->TASKS_SAMPLE;

Do I need the FORK instruction? What is the difference between START and SAMPLE? I find the manual is not very clear on this.

2. SAADC multi-channel Every 5ms (i.e. when PWM disabled) I'd like to sample 2 channels. Here is my code

nrf_saadc_channel_config_t  adcChannel0 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE (AIN0);
adcChannel0.gain      = NRF_SAADC_GAIN1_4;
adcChannel0.reference = NRF_SAADC_REFERENCE_VDD4;
err = nrf_drv_saadc_channel_init (0, &adcChannel0);

nrf_saadc_channel_config_t  adcChannel1 = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE (AIN1);
adcChannel1.gain      = NRF_SAADC_GAIN1_4;
adcChannel1.reference = NRF_SAADC_REFERENCE_VDD4;
err = nrf_drv_saadc_channel_init (1, &adcChannel1);

In case that one channel is configured (AIN0 only) my code works as expected In case that two channels are configured (AIN0/1, as per example above) the 5ms time slots are lost. Why? We're working with Rev1 samples. Can we use Scan Mode? There are numerous references about it being buggy...

3. SAADC results

I believe I understand the concept behind this:

NRF_SAADC->RESULT.PTR    = (uint32_t)mAdcResult;
NRF_SAADC->RESULT.MAXCNT = 1;

When running my code I doubt that values in mAdcResult are correct. They are updated but the value doesn't change even though the actual analog voltage does.

4. Other stuff Here is some more you might need to know:

nrf_drv_saadc_init (NULL, onAdcEvent);

static void  onAdcEvent (nrf_drv_saadc_evt_t const *event)
{
    if (event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        NRF_SAADC->TASKS_STOP = 1;  <-- Do I need this ?
        NRF_SAADC->EVENTS_END = 0;  <-- Do I need this ?

        nrf_gpio_pin_toggle (PIN_DEBUG);
    }
}

SAADC resolution: set to 10bit SAADC oversamling: set to disabled

Thanky for your help

Related