Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

app_timer_cnt_get causing high power consumption

Hello,

i am finding that after i  call app_timer_cnt_get() there is a constant power drain.

I have an Ultrasonic sensor. the ECHO pin will fire 2 times into a GPIOTE pin handler. The first time i use app_timer_cnt_get() to get the Ticks on the RTC and then the second time it fires i call app_timer_cnt_get() again to get the Ticks and then diff to 2 times using app_timer_cnt_diff_compute.

But i am finding as soon as app_timer_cnt_get()  gets called i get constant high consumption through the Nordic Power Profiler. 

Any Help would be appreciated.

Regards,

David Hutchinson

Parents
  • Hi,

    1. Can you post the code that causes the power drain?
    2. Are you by any chance doning some floating point operations with the return values? Could it be related to the FPU erratum: [87] CPU: Unexpected wake from System ON Idle when using FPU ?
    3. What kind of currents are we talking? Can you post a screenshot of the current profile?
    4. What chip and SDK are you using?
  • Chip: NRF52832
    SDK: Mesh v2.1.1

    Power Consumption: constant 3 mA

    I have ended up not using  app_timer_cnt_get(); and using a different method for calculating time

    and now it seems to be working with average of 180 uA.

    timer_value = app_timer_cnt_get();

    is the line of code that causes the high drain, if i don't use this it is fine.

  • Hi,

    app_timer_cnt_get() is a simple wrapper function and all it does is returning the counter value from NRF_RTC1->COUNTER. The RTC has no known current issues, and I can find no relevant reports in our case and bug databases. Hence I suspect it is not the function itself that causes the issue, but rather how you use the returned value or the context your are using it in. If you want to get to the bottom of it, I need to see more code and a plot of the current profile. 

  • MartinBL,

    Please see below the Occupancy code that was causing this issue

     

    #include "occupancy.h"
    
    // Module used for the occupancy JSN-SR04T
    //
    // datasheet: https://www.jahankitshop.com/getattach.aspx?id=4635&Type=Product
    // Operation mode 1
    
    #if SELECTED_TAG == CORE_TAG_OCCUPANCY
    
    #define NRF_LOG_MODULE_NAME EXT_OCCUPANCY
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "log.h"
    NRF_LOG_MODULE_REGISTER();
    
    #include "nrf_delay.h"
    #include "nrfx_gpiote.h"
    #include "app_timer.h"
    
    #define devkit_sensor 0
    
    #if devkit_sensor
    #define ULTRASONIC_VCC_PIN_OUT		28// 11	//11
    #define ULTRASONIC_TRIG_PIN_OUT		03// 05	//31
    #define ULTRASONIC_PULSE_PIN_IN		04// 06	//07
    #else
    #define ULTRASONIC_VCC_PIN_OUT		11	//11
    #define ULTRASONIC_TRIG_PIN_OUT		05	//31
    #define ULTRASONIC_PULSE_PIN_IN		06	//07
    #endif
    
    bool accept_measurement;
    bool first_pulse_received = false;
    
    uint8_t distance = 255;
    
    APP_TIMER_DEF(occupancy_timer_id);
    
    static uint32_t Tick,Ticks_Elapsed,TicksDiff = 0;
    
    
    void in_pin_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
    	if (accept_measurement)
    	{
    		if(false == first_pulse_received)
    		{          
                //check the RTC counter value when the module detects a rising edge
                Tick =  app_timer_cnt_get();  //***removing this line stops the high usage
    
                first_pulse_received = true;
                          
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"first hit of pin handler \r\n");
    		}
    		else
    		{
                // compare the RTC ticks between the Rising and Falling edges
    			Ticks_Elapsed =  app_timer_cnt_get();  //***removing this line stops the high usage
    
    			TicksDiff = app_timer_cnt_diff_compute(Ticks_Elapsed, Tick);
                           
    			uint32_t time_us;
    			  
    			time_us= (((float)TicksDiff *1000) / 32768)*1000;
    			
    			distance = time_us / 58;
    
    			__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"ticks: %d  microseconds: %d distance: %dcm  \r\n", TicksDiff ,time_us, distance);
    			
    		    nrfx_gpiote_out_set(ULTRASONIC_VCC_PIN_OUT); //Turn off Sensor                          
    			first_pulse_received = false;
    			accept_measurement=false;
    		}
    	}
    	else
    	{
    		__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"handler was fired when not ready \n");
    	}
    }
    
    ret_code_t Measurement()
    {
            // Init variables
    	accept_measurement = true;
    	
    	//Toggle Triger Pin
    	nrfx_gpiote_out_set(ULTRASONIC_TRIG_PIN_OUT);  // Pulse start
        nrf_delay_us(10);                              
        nrfx_gpiote_out_clear(ULTRASONIC_TRIG_PIN_OUT);// Pulse end
    	
     }
    
    ret_code_t poll()
    {
        ret_code_t ret_code = NRF_SUCCESS;
    
    	// Turn on power of the ultrasonic board
    	nrfx_gpiote_out_clear(ULTRASONIC_VCC_PIN_OUT);
    		
    	// Wait for 100ms for power on
    	nrf_delay_ms(100); //[mS]
    
    	// Check if we are in the correct state
    	if(nrf_gpio_pin_read(ULTRASONIC_PULSE_PIN_IN))
    	{
    		__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"Pulse pin was high at startup\n");
    		ret_code = NRF_ERROR_INVALID_STATE;
    	}
    	else
    	{
            ret_code = Measurement();
    	}
    
    	return ret_code;
    }
    
    static void occupancy_timer_handler(void * p_context)
    {
    	poll();
    }
    
    void occ_initialize(uint32_t refreshRateMs)
    {
    	ret_code_t err_code;
    	err_code = nrfx_gpiote_init();
    	APP_ERROR_CHECK(err_code);
    	
    	// Init GPIOTE
    	nrfx_gpiote_out_config_t out_config =
    	{
    		.action		= NRF_GPIOTE_POLARITY_TOGGLE, 
    		.init_state     = NRF_GPIOTE_INITIAL_VALUE_LOW,
    		.task_pin	= false,
    	};//Needed because non-trivial designated initializers not supported
    
    	// VCC PIN OUT
    	err_code = nrfx_gpiote_out_init(ULTRASONIC_VCC_PIN_OUT, &out_config);
    	APP_ERROR_CHECK(err_code);
    	
    	// TRIGGER PIN OUT
    	err_code = nrfx_gpiote_out_init(ULTRASONIC_TRIG_PIN_OUT, &out_config);
    	APP_ERROR_CHECK(err_code);
    
    	nrfx_gpiote_in_config_t in_config =
    	{  
    			.sense = NRF_GPIOTE_POLARITY_TOGGLE ,
    			.pull = NRF_GPIO_PIN_PULLDOWN,
    			.is_watcher = false,
    			.hi_accuracy = true,
    	};
    
    	//INITIALIZE PULSE PIN IN RISING EDGE   
    	err_code = nrfx_gpiote_in_init(ULTRASONIC_PULSE_PIN_IN, &in_config, in_pin_handler);
    	APP_ERROR_CHECK(err_code); 	
    		  
    	nrfx_gpiote_in_event_enable(ULTRASONIC_PULSE_PIN_IN, true);
    
    	//SET VCC PIN HI
    	nrfx_gpiote_out_set(ULTRASONIC_VCC_PIN_OUT);
    	//CLEAR TRIG PIN
    	nrfx_gpiote_out_clear(ULTRASONIC_TRIG_PIN_OUT);
    
    	app_timer_create(&occupancy_timer_id, APP_TIMER_MODE_REPEATED, occupancy_timer_handler);
    	APP_ERROR_CHECK(app_timer_start(occupancy_timer_id, APP_TIMER_TICKS(refreshRateMs), NULL));
    
    	__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"Initialized\n");
    }
    
    uint8_t getDistance()
    {
      return distance; 
    }
    
    #endif
    

Reply
  • MartinBL,

    Please see below the Occupancy code that was causing this issue

     

    #include "occupancy.h"
    
    // Module used for the occupancy JSN-SR04T
    //
    // datasheet: https://www.jahankitshop.com/getattach.aspx?id=4635&Type=Product
    // Operation mode 1
    
    #if SELECTED_TAG == CORE_TAG_OCCUPANCY
    
    #define NRF_LOG_MODULE_NAME EXT_OCCUPANCY
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "log.h"
    NRF_LOG_MODULE_REGISTER();
    
    #include "nrf_delay.h"
    #include "nrfx_gpiote.h"
    #include "app_timer.h"
    
    #define devkit_sensor 0
    
    #if devkit_sensor
    #define ULTRASONIC_VCC_PIN_OUT		28// 11	//11
    #define ULTRASONIC_TRIG_PIN_OUT		03// 05	//31
    #define ULTRASONIC_PULSE_PIN_IN		04// 06	//07
    #else
    #define ULTRASONIC_VCC_PIN_OUT		11	//11
    #define ULTRASONIC_TRIG_PIN_OUT		05	//31
    #define ULTRASONIC_PULSE_PIN_IN		06	//07
    #endif
    
    bool accept_measurement;
    bool first_pulse_received = false;
    
    uint8_t distance = 255;
    
    APP_TIMER_DEF(occupancy_timer_id);
    
    static uint32_t Tick,Ticks_Elapsed,TicksDiff = 0;
    
    
    void in_pin_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
    {
    	if (accept_measurement)
    	{
    		if(false == first_pulse_received)
    		{          
                //check the RTC counter value when the module detects a rising edge
                Tick =  app_timer_cnt_get();  //***removing this line stops the high usage
    
                first_pulse_received = true;
                          
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"first hit of pin handler \r\n");
    		}
    		else
    		{
                // compare the RTC ticks between the Rising and Falling edges
    			Ticks_Elapsed =  app_timer_cnt_get();  //***removing this line stops the high usage
    
    			TicksDiff = app_timer_cnt_diff_compute(Ticks_Elapsed, Tick);
                           
    			uint32_t time_us;
    			  
    			time_us= (((float)TicksDiff *1000) / 32768)*1000;
    			
    			distance = time_us / 58;
    
    			__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"ticks: %d  microseconds: %d distance: %dcm  \r\n", TicksDiff ,time_us, distance);
    			
    		    nrfx_gpiote_out_set(ULTRASONIC_VCC_PIN_OUT); //Turn off Sensor                          
    			first_pulse_received = false;
    			accept_measurement=false;
    		}
    	}
    	else
    	{
    		__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"handler was fired when not ready \n");
    	}
    }
    
    ret_code_t Measurement()
    {
            // Init variables
    	accept_measurement = true;
    	
    	//Toggle Triger Pin
    	nrfx_gpiote_out_set(ULTRASONIC_TRIG_PIN_OUT);  // Pulse start
        nrf_delay_us(10);                              
        nrfx_gpiote_out_clear(ULTRASONIC_TRIG_PIN_OUT);// Pulse end
    	
     }
    
    ret_code_t poll()
    {
        ret_code_t ret_code = NRF_SUCCESS;
    
    	// Turn on power of the ultrasonic board
    	nrfx_gpiote_out_clear(ULTRASONIC_VCC_PIN_OUT);
    		
    	// Wait for 100ms for power on
    	nrf_delay_ms(100); //[mS]
    
    	// Check if we are in the correct state
    	if(nrf_gpio_pin_read(ULTRASONIC_PULSE_PIN_IN))
    	{
    		__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"Pulse pin was high at startup\n");
    		ret_code = NRF_ERROR_INVALID_STATE;
    	}
    	else
    	{
            ret_code = Measurement();
    	}
    
    	return ret_code;
    }
    
    static void occupancy_timer_handler(void * p_context)
    {
    	poll();
    }
    
    void occ_initialize(uint32_t refreshRateMs)
    {
    	ret_code_t err_code;
    	err_code = nrfx_gpiote_init();
    	APP_ERROR_CHECK(err_code);
    	
    	// Init GPIOTE
    	nrfx_gpiote_out_config_t out_config =
    	{
    		.action		= NRF_GPIOTE_POLARITY_TOGGLE, 
    		.init_state     = NRF_GPIOTE_INITIAL_VALUE_LOW,
    		.task_pin	= false,
    	};//Needed because non-trivial designated initializers not supported
    
    	// VCC PIN OUT
    	err_code = nrfx_gpiote_out_init(ULTRASONIC_VCC_PIN_OUT, &out_config);
    	APP_ERROR_CHECK(err_code);
    	
    	// TRIGGER PIN OUT
    	err_code = nrfx_gpiote_out_init(ULTRASONIC_TRIG_PIN_OUT, &out_config);
    	APP_ERROR_CHECK(err_code);
    
    	nrfx_gpiote_in_config_t in_config =
    	{  
    			.sense = NRF_GPIOTE_POLARITY_TOGGLE ,
    			.pull = NRF_GPIO_PIN_PULLDOWN,
    			.is_watcher = false,
    			.hi_accuracy = true,
    	};
    
    	//INITIALIZE PULSE PIN IN RISING EDGE   
    	err_code = nrfx_gpiote_in_init(ULTRASONIC_PULSE_PIN_IN, &in_config, in_pin_handler);
    	APP_ERROR_CHECK(err_code); 	
    		  
    	nrfx_gpiote_in_event_enable(ULTRASONIC_PULSE_PIN_IN, true);
    
    	//SET VCC PIN HI
    	nrfx_gpiote_out_set(ULTRASONIC_VCC_PIN_OUT);
    	//CLEAR TRIG PIN
    	nrfx_gpiote_out_clear(ULTRASONIC_TRIG_PIN_OUT);
    
    	app_timer_create(&occupancy_timer_id, APP_TIMER_MODE_REPEATED, occupancy_timer_handler);
    	APP_ERROR_CHECK(app_timer_start(occupancy_timer_id, APP_TIMER_TICKS(refreshRateMs), NULL));
    
    	__LOG(LOG_SRC_APP, LOG_LEVEL_INFO,"Initialized\n");
    }
    
    uint8_t getDistance()
    {
      return distance; 
    }
    
    #endif
    

Children
  • Hi,

    It looks like you use app_timer_cnt_get() to get the variables Ticks_Elapsed and Tick. Both of these variables are later used to calculate Ticks_Diff and finally you are doing some floating point math with the result. As I mentioned in my first post there is an erratum that could lead to high current consumption when you are doing floating point math. I suspect that if you only comment out the two references to app_timer_cnt_get() the floating point math is getting optimized away by the compiler, and the erratum never triggers. It would be interesting to see what happens if you leave the references to app_timer_cnt_get() , but comment out the float stuff. 

Related