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

ADC sampling while the radio is transmitting

The project I'm working on is running off of a CR2032 battery.  I want to measure the battery voltage while the radio is transmitting to determine when the battery dips down close to BOR voltage (1.8V).  I have tried radio notification, but it does not work as it has an 800us lead time before the radio actually transmit.  By the time the radio transmit, ADC sampling already finished and did not capture the voltage of the pulse.

I'm wondering if there's anyway to capture this voltage dip.  

I have read similar thread on the forum: https://devzone.nordicsemi.com/f/nordic-q-a/27424/best-practice-for-monitoring-coin-cell-battery-voltage-given-esr 

but there are no suggestion that could help me achieve this.

I'm running on nrf52811, SDK 16.0.0 and S140.

Any help would be appreciated.

Thanks.

Parents
  • Hi Kenneth

    It is possible to use the PPI controller to connect one of the radio events to the ADC SAMPLE task, so that the ADC sampling will be synchronized to the operation of the radio. 

    An overview of all the events in the radio can be found here.

    Possible events of interest are the TXREADY or RXREADY events, which occur once the radio is started in TX or RX mode respectively. 
    You could also use the END event, which is triggered when a packet is successfully sentor received. 

    Best regards
    Torbjørn

  • So this is how I set up PPI

    static void ppi_init(void)
    {
        uint32_t err_code = NRF_SUCCESS;
    
    
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
    
        /* Configure 1st available PPI channel to stop TIMER0 counter on TIMER1 COMPARE[0] match,
         * which is every even number of seconds.
         */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1,
                                              (uint32_t)&NRF_RADIO->EVENTS_TXREADY,
                                              (uint32_t)&NRF_SAADC->TASKS_START);
        APP_ERROR_CHECK(err_code);
    
        /* Configure 2nd available PPI channel to start TIMER0 counter at TIMER2 COMPARE[0] match,
         * which is every odd number of seconds.
         */
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel2);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel2,
                                              (uint32_t)&NRF_RADIO->EVENTS_TXREADY,
                                              (uint32_t)&NRF_SAADC->TASKS_SAMPLE);
        APP_ERROR_CHECK(err_code);
    
        // Enable both configured PPI channels
        err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);
        APP_ERROR_CHECK(err_code);
        err_code = nrf_drv_ppi_channel_enable(m_ppi_channel2);
        APP_ERROR_CHECK(err_code);
    }

    SAADC init

    void Adc14bitPolledInitialise(void)
    {
        uint32_t timeout = 10;  
        //Setup C
        nrf_saadc_channel_config_t myConfig =
        {
            .resistor_p = NRF_SAADC_RESISTOR_DISABLED,
            .resistor_n = NRF_SAADC_RESISTOR_DISABLED,
            .gain       = NRF_SAADC_GAIN1_6,
            .reference  = NRF_SAADC_REFERENCE_INTERNAL,
            .acq_time   = NRF_SAADC_ACQTIME_3US,
            .mode       = NRF_SAADC_MODE_SINGLE_ENDED,
            .burst      = NRF_SAADC_BURST_DISABLED,
            .pin_p      = NRF_SAADC_INPUT_VDD,
            .pin_n      = NRF_SAADC_INPUT_DISABLED
        };
    
        nrf_saadc_resolution_set((nrf_saadc_resolution_t) NRF_SAADC_RESOLUTION_14BIT);   // 2 is 12-bit
        nrf_saadc_oversample_set((nrf_saadc_oversample_t) 0);   // 0 no oversampling
        nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
        nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
        nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
        nrf_saadc_enable();
    
        NRF_SAADC->CH[1].CONFIG =
                  ((myConfig.resistor_p << SAADC_CH_CONFIG_RESP_Pos)   & SAADC_CH_CONFIG_RESP_Msk)
                | ((myConfig.resistor_n << SAADC_CH_CONFIG_RESN_Pos)   & SAADC_CH_CONFIG_RESN_Msk)
                | ((myConfig.gain       << SAADC_CH_CONFIG_GAIN_Pos)   & SAADC_CH_CONFIG_GAIN_Msk)
                | ((myConfig.reference  << SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
                | ((myConfig.acq_time   << SAADC_CH_CONFIG_TACQ_Pos)   & SAADC_CH_CONFIG_TACQ_Msk)
                | ((myConfig.mode       << SAADC_CH_CONFIG_MODE_Pos)   & SAADC_CH_CONFIG_MODE_Msk)
                | ((myConfig.burst      << SAADC_CH_CONFIG_BURST_Pos)  & SAADC_CH_CONFIG_BURST_Msk);
    
        NRF_SAADC->CH[1].PSELN = myConfig.pin_n;
        NRF_SAADC->CH[1].PSELP = myConfig.pin_p;
    
    }
    

    and in main, I just initiate both, and read the buffer if the address for saadc indicate finished.

    log_init();
    lfclk_config();
    timers_init();
    Adc14bitPolledInitialise();
    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    peer_manager_init();
    services_init();
    sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);
    sd_power_mode_set(NRF_POWER_MODE_LOWPWR);
    advertising_init();
    conn_params_init();
    
    ppi_init();
    
    advertising_start(false);
    // main loop.
    for (;;)
    {
    
        if( NRF_SAADC->EVENTS_DONE )
        {
            NRF_LOG_INFO("radio RX");
            stopAnalogSample(&vbat);
            advertisingUpdateMfgData();
        }
    
        idle_state_handle(); 
    }
    
    

    it just never get to the stopAnalogSample() function.

    Am I doing something wrong here?

  • Hi 

    I can't see anywhere in your code snippets how you set up the ADC DMA buffers, and if you start the ADC anywhere (through the START task). 

    Are you doing this somewhere else, or is this not included?

    Best regards
    Torbjørn 

  • Hi,

    I initialized my SAADC wrong.  I checked it again when you mentioned it and fixed it. It's working now.

    Thank you for the suggestions.

    Regards,

    Ken

Reply Children
Related