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

saadc sample cant use with sd_power_system_off()

When I use saadc to sample battery's power,the software restart ceaselessly.I use the steps as following:

1.void saadc_init(void).

2.void saadc_callback(nrf_drv_saadc_evt_t const * p_event).read the sample value.

3.use nrf_drv_saadc_sample() in bsp_event_handler function. When button has pushed,saadc sample.

If I comment out saadc,software can go to sleep with sd_power_system_off().If do this ,device cant sample battery.

If I comment out sd_power_system_off(),software can work with saadc,but cant sleep.

So I don't know how to use saadc to sample and device can sleep not restart ceaselessly

  • FormerMember
    0 FormerMember

    sd_power_system_off() puts the chip in system OFF:   System OFF is the deepest power saving mode the system can enter. In this mode, the system’s core functionality is powered down and all ongoing tasks are terminated. 

    What you should use is the system ON mode: System ON is the default state after power-on reset. In System ON, all functional blocks such as the CPU or peripherals, can be in IDLE or RUN mode, depending on the configuration set by the software and the state of the application executing.

    To set the chip in system ON, use sd_app_evt_wait(). For how to use this function, see the BLE examples in the SDK.

  • Thank you for your reply.I see your point. I want to achieve  when chip works completely including sample battery's value and so on, it calls sd_power_system_off() enter system OFF to save power.

    While a button was pushed, the chip wake up , init saadc and use saadc to sample. 

    Now,the question is saadc module and system_off use together, the chip always restart from main. It seems somewhere mistake,but log cant print fatal error.

  • Hi Kristin.I modify my third step above. I use a timer to measure battery's current every 2s. But in saadc_callback(),I use ble_bas_battery_level_update to send percent of battery level. The function return 0x3002. It represent BLE_ERROR_INVALID_CONN_HANDLE. When call ble_bas_battery_level_update(), it need to connected?Can you tell me how to solve this error? 

  • #define SAMPLES_IN_BUFFER 1
    static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
    
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
    	uint16_t  adc_result;
    	uint8_t   adc_result_notify;
    	uint16_t  adc_lvl_in_milli_volts;
    	uint16_t  batt_lvl_in_milli_volts;
    	uint32_t  err_code;
            int i;
            for (i = 0; i < SAMPLES_IN_BUFFER; i++)
            {
                NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
            }
    	//calculate some sac value.
    	adc_result = p_event->data.done.p_buffer[0];
    	adc_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result);
    	NRF_LOG_INFO("adc_lvl:%d",adc_lvl_in_milli_volts);
            batt_lvl_in_milli_volts = BATTERY_IN_MILLI_VOLTS(adc_lvl_in_milli_volts);
    	NRF_LOG_INFO("batt_lvl:%d",batt_lvl_in_milli_volts);
    	adc_result_notify = (batt_lvl_in_milli_volts - MIN_MILLI_VOLTS) / PERCENT_MILLI_VOLTS;
            err_code = ble_bas_battery_level_update(&m_bas, adc_result_notify);
    	NRF_LOG_INFO("battery err_code:%d",err_code);
            if ((err_code != NRF_SUCCESS) &&
            (err_code != NRF_ERROR_BUSY) &&
            (err_code != NRF_ERROR_RESOURCES) &&
            (err_code != NRF_ERROR_FORBIDDEN) &&
            (err_code != NRF_ERROR_INVALID_STATE) &&
            (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING))
    	{
    		APP_ERROR_HANDLER(err_code);
    	}
    	err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);
            APP_ERROR_CHECK(err_code);
    }
    
    void saadc_init(void)
    {
        ret_code_t err_code;
        nrf_saadc_channel_config_t channel_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(SAADC_CH_PSELP_PSELP_AnalogInput3); //SAADC_CH_PSELP_PSELP_VDD
    
        err_code = nrf_drv_saadc_init(NULL, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_channel_init(0, &channel_config);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    		
        err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
        APP_ERROR_CHECK(err_code);
    }
    
    static void bsp_event_handler(bsp_event_t event)	
    {
    	...
    	case	BSP_EVENT_ADVERTISING_START:
    		err_code = nrf_drv_saadc_sample();
    		APP_ERROR_CHECK(err_code);
    		...
    	...
    }		

    I use saadc module like attachment. The software restart continuously.

  • FormerMember
    0 FormerMember in reply to liu_zhixiang

    Yes, for the battery level update to work, the device will have to be connected. To get connected the device has to start advertising. If the central is known, directed advertising can be used for a fast connection setup. I would assume that ble_bas_battery_level_update() uses notifications to update the battery level to the central. If that is the case, the central will also have to enable notifications before the peripheral (your device) can transmit the battery level update.

     

Related