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

SAADC Advanced mode with PPI (NRFX_SAADC_V2)

How start sampling by timer with PPI?

#define SAADC_CHANNEL_COUNT   4
#define SAADC_BUF_SIZE   SAADC_CHANNEL_COUNT * 8
#define SAADC_SAMPLE_INTERVAL_MS 250

static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0);
static volatile bool is_ready = true;
static nrf_saadc_value_t samples[SAADC_BUF_SIZE];
static nrfx_saadc_channel_t channels[SAADC_CHANNEL_COUNT] = {NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN0, 0),
                                                             NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN1, 1),
                                                             NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN2, 2),
                                                             NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN3, 3)};
static nrf_ppi_channel_t     m_ppi_channel;
static uint32_t              m_adc_evt_counter;

APP_TIMER_DEF(m_sample_timer_id);     /**< Handler for repeated timer used to blink LED 1. */
 
static void event_handler(nrfx_saadc_evt_t const * p_event)
{
    ret_code_t err_code;
    switch (p_event->type)
    {
        case NRFX_SAADC_EVT_FINISHED:
            for(int i = 0; i < p_event->data.done.size; i++)
            {
                NRF_LOG_INFO("CH%d: %d", i, p_event->data.done.p_buffer[i]);
            }

            is_ready = true;
            nrf_gpio_pin_toggle(LED_ST_B);
            break;
        case NRFX_SAADC_EVT_BUF_REQ:
            err_code = nrfx_saadc_buffer_set(samples, SAADC_BUF_SIZE);
            APP_ERROR_CHECK(err_code);
            //buf_to_load++;
            break;
        default:
            break;
    }

    /* Applying workaround from Errata 212, otherwise current is stuck at 4-500uA during sleep after first sample. */
    volatile uint32_t temp1;
    volatile uint32_t temp2;
    volatile uint32_t temp3;

    temp1 = *(volatile uint32_t *)0x40007640ul;
    temp2 = *(volatile uint32_t *)0x40007644ul;
    temp3 = *(volatile uint32_t *)0x40007648ul;

    *(volatile uint32_t *)0x40007FFCul = 0ul; 
    *(volatile uint32_t *)0x40007FFCul; 
    *(volatile uint32_t *)0x40007FFCul = 1ul;

    *(volatile uint32_t *)0x40007640ul = temp1;
    *(volatile uint32_t *)0x40007644ul = temp2;
    *(volatile uint32_t *)0x40007648ul = temp3;
}

void saadc_sampling_event_init(void)
{
    ret_code_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler);
    APP_ERROR_CHECK(err_code);

    /* setup m_timer for compare event every 10ms */
    uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 100);
    //uint32_t ticks = nrf_drv_timer_us_to_ticks(&m_timer, 10);
    nrf_drv_timer_extended_compare(&m_timer,
                                   NRF_TIMER_CC_CHANNEL0,
                                   ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    nrf_drv_timer_enable(&m_timer);

    uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer,
                                                                                NRF_TIMER_CC_CHANNEL0);
    uint32_t saadc_sample_task_addr   = NRF_SAADC_TASK_SAMPLE;

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                          timer_compare_event_addr,
                                          saadc_sample_task_addr);
    APP_ERROR_CHECK(err_code);
}
 
int main(void)
{
    err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);                       //Configure Logging. LOGGING is used to show the SAADC sampled result. Default is UART, but RTT can be configured in sdk_config.h
    NRF_LOG_DEFAULT_BACKENDS_INIT();
    NRF_LOG_INFO("nrfx_saadc_api2 simple SAADC Low Power Example.");	

    err_code = nrfx_saadc_init(NRFX_SAADC_CONFIG_IRQ_PRIORITY);
    APP_ERROR_CHECK(err_code);
 
    err_code = nrfx_saadc_channels_config(channels, SAADC_CHANNEL_COUNT);
    APP_ERROR_CHECK(err_code);

    nrfx_saadc_adv_config_t config = {
        .oversampling      = NRF_SAADC_OVERSAMPLE_8X,       // oversample.
        .burst             = NRF_SAADC_BURST_ENABLED,       // burst.
        .internal_timer_cc = 0,                             // Sample 0.
        .start_on_end      = true,                          // Latch next buffer at END event in interrupt.
    };
    err_code = nrfx_saadc_advanced_mode_set((1<<0|1<<1|1<<2|1<<3),
                                          NRF_SAADC_RESOLUTION_12BIT,
                                          &config,
                                          event_handler);
    
    APP_ERROR_CHECK(err_code);
    
    err_code = nrfx_saadc_buffer_set(samples, SAADC_BUF_SIZE);
    APP_ERROR_CHECK(err_code);

    //timers_init();
    saadc_sampling_event_init();


    err_code = nrfx_saadc_mode_trigger();
    APP_ERROR_CHECK(err_code);

    while (1)
    {
        while(NRF_LOG_PROCESS() != NRF_SUCCESS);
        __WFE();
    }
    
}


/** @} */

  • Hi Karl,

    Thank you very much!

    I change my clock source, use RTC to trigger the SAADV(PPI mode), the baseline current consumption is about 12uA. This is a good news!!

    Now, I have another problem.

    What is the low-power mode of SAADC?

    When I use RTC+SAADC (PPI mode), if enable low-power mode, baseline current is 12uA;  If I disable low-power mode, baseline current is 700uA, why?

    I mean:

    if (saadv_config.low_power_mode == true),   then current = 12uA;

    if (saadv_config.low_power_mode == false), then current = 700uA;

    why?

  • Hello,

    lvpeng said:
    I change my clock source, use RTC to trigger the SAADV(PPI mode), the baseline current consumption is about 12uA. This is a good news!!

    I am happy to hear that you were able to achieve the low power consumption, great! :)

    lvpeng said:
    What is the low-power mode of SAADC?

    The low power mode will turn off the SAADC between samplings. So, this is why you are seeing a sharp increase in power consumption when not using low-power mode.

    Best regards,
    Karl

Related