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

Sleep current: disabling TWI, pull-ups?

I'm developing some simple wireless temperature sensors based on NRF51822s. In essence, they take a temperature measurement from a sensor over TWI, send it to a base-station using the micro_esb libraries, and then go into SYSTEM ON sleep for a period, before waking up and repeating. All without softdevice.

I've written code to do just the radio / sleeping part, which successfully puts the NRF51822 into SYSTEM ON with a current usage of ~3uA (incl. about 0.5uA for the temp sensor (also sleeping)). When I add into the code to read the temperature, the sleep mode uses ~230uA. I suspect I am not stopping and disabling the TWI correctly.

The code includes a command to disable TWI before sleeping:

NRF_TWI1->ENABLE= TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;

Should I be 'stopping' TWI first? And if so, with what command? Is it:

NRF_TWI1->TASKS_STOP=1;

I have also seen the following command used in some people's code. Is it part of the solution?

NRF_TWI1->POWER = 0;

Any advice on the correct sequence of commands to shutdown TWI (and wake it up after SYSTEM ON sleep) would be really appreciated

UPDATE: another thought, i'm also using pull-ups on some of the pins - could this cause the additional ~200uA of current drain? If so, what state should I try and leave the pins in before going into SYSTEM ON sleep if I want to minimise current usage?

main loop code below:

	while (true)
{
    ackd=false;

			// -------------- SENSE ---------------------

			twi_master_init(); 		
			// Trigger a one-shot conversion from the temperature sensor
			write_buffer[0]=1; // i.e. Configuration register
			write_buffer[1]=129; // MSB 128=OS bit, 1=SD bit
			write_buffer[2]=0; // LSB 	
			if(twi_master_transfer(TMP102_ADDRESS , write_buffer, 3, TWI_ISSUE_STOP)){
			}			

			// Wait for OS bit to be re-set to 1 to signal end of conversion
			data_buffer[0]=0;
			while (data_buffer[0] && 128!=128) {
				if (twi_master_transfer(TMP102_ADDRESS | TWI_READ_BIT, data_buffer, 2, TWI_ISSUE_STOP)) {
				}				
			}
			
			// Switch to temperature register (from config register)
			write_buffer[0]=0; // i.e. Temperature register
			write_buffer[1]=0; // MSB? 
			write_buffer[2]=0; // LSB? 	
			if(twi_master_transfer(TMP102_ADDRESS , write_buffer, 3, TWI_ISSUE_STOP)){
			}			
			
			// Read the temperature and place in the payload ready to send
			if (twi_master_transfer(TMP102_ADDRESS | TWI_READ_BIT, data_buffer, 2, TWI_ISSUE_STOP)) {
						tx_payload.data[2] = data_buffer[0];		
						tx_payload.data[3] = data_buffer[1];				
			}
			
			// Disable TWI ready for sleep
			NRF_TWI1->ENABLE= TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
			
			// -------------- TRANSMIT ---------------------
		
			if(uesb_write_tx_payload(&tx_payload) == UESB_SUCCESS)
			{
					tx_payload.data[0]++;
			}
		
			nrf_delay_ms(10);
			
						
			
			// --------------- SLEEP ------------------------
			
			// define length of sleep according to position of SW_TEST switch

			if (nrf_gpio_pin_read(SW_TEST)==0) {	
					NRF_RTC1->CC[0] = 32768;				
			}
			else
			{		
					NRF_RTC1->CC[0] = 32768*60*5;						
			}				
			
			// Start the RTC timer
			NRF_RTC1->TASKS_START = 1;

			// shut down the high-frequency clock
			NRF_CLOCK->TASKS_HFCLKSTOP = 1;
			
			awake=false;
			while(!awake)
			{
				// Enter System ON sleep mode
				__WFE();  
				// Make sure any pending events are cleared
				__SEV();
				__WFE();                
			}
				
			// Stop and clear the RTC timer
			NRF_RTC1->TASKS_STOP = 1;
			NRF_RTC1->TASKS_CLEAR = 1;	

			// Restart the hi-frequency clock
			NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
			NRF_CLOCK->TASKS_HFCLKSTART = 1;
			while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);	
			
			
}
Parents
  • Looks like the problem is with the RTC rather than the TWI. I tested it and found out that if the low frequency clock is not started when starting the RTC, it looks like the high frequency clock is forced on (from the current measurement). Anyhow, the RTC will not function if the low frequency clock is not started. Add this to your initialization code:

    NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_LFCLKSTART = 1;
    while(NRF_CLOCK->EVENTS_LFCLKSTARTED == 0);
    
Reply
  • Looks like the problem is with the RTC rather than the TWI. I tested it and found out that if the low frequency clock is not started when starting the RTC, it looks like the high frequency clock is forced on (from the current measurement). Anyhow, the RTC will not function if the low frequency clock is not started. Add this to your initialization code:

    NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_LFCLKSTART = 1;
    while(NRF_CLOCK->EVENTS_LFCLKSTARTED == 0);
    
Children
No Data
Related