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

Trouble with simple SAADC sampling

I'm having a heck of a time getting the SAADC to just return one sample in a blocking manner using SDK 15.2.0

I'm pretty far along in developing a couple of nRF52840-based products on custom hardware with FreeRTOS (bluetooth currently not being used but I do have the softdevice linked in ready to go in the future).

I've got it sleeping at low current and then waking up once every 6 seconds to read some sensors and then go back to sleep. When I wake up, I want to turn on the ADC,  take a single sample of my battery voltage, and then turn off the ADC and move on to other things. The examples all seem to want to use a timer and the PPI for scheduled sampling, but I already have FreeRTOS waking me up when I want to sample and I don't want to leave the ADC running and drawing a lot of power - I just want a simple single sample.

I think the code I have now ought to work, but nrfx_saadc_sample_convert is failing on the NRFX_ASSERT after this line in nrfx_saadc.c:

      NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_END), HW_TIMEOUT, 0, result);

Here's the code:

void Battery_Level_Callback(nrf_drv_saadc_evt_t const * p_event)
{
uint32_t result;

if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
//result = (uint32_t)(*p_event->data.done.p_buffer);
}
}

void Battery_Level_Init(void)
{
ret_code_t err_code;
nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);

err_code = nrf_drv_saadc_init(&default_config, Battery_Level_Callback);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_saadc_channel_init(0, &channel_config);
APP_ERROR_CHECK(err_code);
}

void Battery_Level_Take_Reading(void)
{
nrf_saadc_value_t result;
uint32_t calc;

if (nrfx_saadc_sample_convert(0, &result) != NRFX_SUCCESS)
{
DBG_PRINT("ADC failure\r\n");
}
else
{
calc = result;
calc *= NANOVOLTS_PER_BIT;
calc /= MV_PER_NV; // Calc now contains the voltage in mV

DBG_PRINT("ADC: %d\r\n", calc);

// Clamp the reading between what we're calling full and empty battery
if (calc > BAT_PCT_100)
{
calc = BAT_PCT_100;
}

if (calc < BAT_PCT_0)
{
calc = BAT_PCT_0;
}

m_last_battery_level_pct = ((calc - BAT_PCT_0) * 100) / (BAT_PCT_100 - BAT_PCT_0);
}
}


//----------------------------------------------------------------------------
// Name : Battery_Level_Get_Last_Reading
// Desc : Return the last battery level reading
// Ins : none
// Outs : Battery level, 0-100%
//----------------------------------------------------------------------------
uint8_t Battery_Level_Get_Last_Reading(void)
{
//DBG_PRINT("Battery percent: %d\r\n", m_last_battery_level_pct);
return m_last_battery_level_pct;
}

Related