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

Accurate ADC measurement without the Soft Device

I'd like to measure the voltage of a lithium ion battery every minute or so in a way that's highly accurate. I need to do this without using the Soft Device because a) I need all the memory I can get for logging the voltages and b) what I'm really testing is a generator that's charging my battery so I want the power consumption of my board while I'm testing to be fairly low.

There's plenty of discussion about using the high frequency clock with the soft device to get an accurate ADC reading here:

devzone.nordicsemi.com/.../adc-softdevice-sample-rate-on-nrf51822

That code does this ten times a second:

static void adc_sampling_timeout_handler(void * p_context)
{
	uint32_t p_is_running = 0;
		
	sd_clock_hfclk_request();
	while(! p_is_running) {  							//wait for the hfclk to be available
		sd_clock_hfclk_is_running((&p_is_running));
	}               
	nrf_gpio_pin_toggle(NRF6310_LED_2);		//Toggle LED2 to indicate start of sampling
	NRF_ADC->TASKS_START = 1;							//Start ADC sampling
}

and then releases the clock at the end of the IRQ handler:

sd_clock_hfclk_release();

My question is, how do I do the same thing but without use of the Soft Device?

Parents
  • Eliot, I must apologize for going off-topic. This is a continuation of the WFE-talk in the comments area.

    As events and interrupts are closely coupled in the MCU core, you'll need to enable this in the INTENSET register prior to using SEV/WFE.

    1. you enable SEV instruction in SCB->SRC.
    2. You enable the event/interrupt for HFCLK-started (INTENSET)
    3. Start the task enabled in 2)
    4. The first WFE will cause the MCU to go to sleep and wake up on EVENTS_HFCLKSTARTED.
    5. SEV will set the Event Register in the core register.
    6. Second WFE will see that the event register is set, and clear this. No sleep will be executed at this call.
    7. EVENTS_HFCLKSTARTED and IRQn is cleared.

    Safest approach: I had a chat with our nrf_soc developer, and was told a better implementation. The above usage of WFE/SEV/WFE can cause you to wake up immediately if the internal event register is already set.

    To be certain that you wake up on the correct event, you should do like this:

    
    NRF_CLOCK->INTENSET = CLOCK_INTENSET_HFCLKSTARTED_Msk;
    // Enable wake-up on event
    SCB->SCR |= SCB_SCR_SEVONPEND_Msk; 
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1; 
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) 
    {
      __WFE();
    }
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NVIC_ClearPendingIRQ(POWER_CLOCK_IRQn);
    
    

    In general, I recommend reading up on WFI/WFE/SEV instructions: infocenter.arm.com/.../index.jsp infocenter.arm.com/.../index.jsp

    BR Håkon

  • No problem, this looks like the lowest power consumption approach to my problem too. Thanks.

Reply Children
No Data
Related