Advise needed: Trying to achieve lowest power on an attiny13a

Hello,

Using the code below 690micro Amp is achieved during sleep mode and 2,500micro Amp when it is awake (LED on).
Is it possible to push down the power consumption lower during sleep mode?

  • attiny13a
  • attiny13 core
  • 3v CR2032
  • LED connected to PB4 and grounded via 1meg resistor
  • Pin 1, Pin 2, Pin 5, Pin 6, Pin 7 not connected anywhere

Thank you for reading!

#include <avr/sleep.h>										
#include <avr/power.h>										
#define  LED PB4													

  ISR(WDT_vect) {													
   noInterrupts();                      	
   digitalWrite(LED,digitalRead(LED)^1);
   interrupts();              						
  }//ISR()

void setup(){                           
  pinMode(LED, OUTPUT);									
  WDTCR |= 32;						 //watchdog set for about 2 seconds						  
  WDTCR |= 64; 						 //enable watchdog							
  _SFR_MEM8(0x30)= 0x03;		 //disable Brown Out Detector Control Register
  _SFR_MEM8(0x35)&=0x83;		//PUD disabled, Sleep enabled,  Power Down mode  
  _SFR_MEM8(0x25)=2;				//Power reduction timer enable
  interrupts();													
}// setup()


void loop(){															
  sleep_cpu();    										
}//void loop()
 ISR(WDT_vect) {													
   noInterrupts();                      	
   digitalWrite(LED,digitalRead(LED)^1);
   interrupts();              						
  }//ISR()

You don't need to turn interrupts off, or on, in an ISR. So that can be:

 ISR(WDT_vect) {													
   digitalWrite(LED,digitalRead(LED)^1);
  }//ISR()

690 µA sounds far too high to me. You should be able to get it down to 6 µA.

Try turning off the ADC.

Pin 1, Pin 2, Pin 5, Pin 6, Pin 7 not connected anywhere

this is a big "don't do that" for low power consumption. Even though it is common practice in arduino software, it is a bad idea to leave pins configured as inputs AND not connected to anything; they can easily "float" at non-digital signal levels (or even oscillate), causing unexpectedly high current consumption.

I'd be curious to hear if you actually see any change in consumption JUST by changing the pins to outputs.

And... I usually refrain from commenting on issues of programming style, but THIS is really awful:

  _SFR_MEM8(0x30)= 0x03;		 //disable Brown Out Detector Control Register
  _SFR_MEM8(0x35)&=0x83;		//PUD disabled, Sleep enabled,  Power Down mode  
  _SFR_MEM8(0x25)=2;				//Power reduction timer enable

Those registers, and their bits, are defined for you symbolically in avr/io.h (etc), which is included for you by the arduino system (the same place that _SFR_MEM8() is defined.) You should use them. (in fact, those registers are all defined as "_SFR_IO8(x)", which is not the same as _SFR_MEM8(), so perhaps those lines are not doing what you think they are doing AT ALL!)

Nick, I appreciate the article! Now I know. Thank you so much! :slight_smile:

You don't need to turn interrupts off, or on, in an ISR. So that can be:

 ISR(WDT_vect) {													

digitalWrite(LED,digitalRead(LED)^1);
  }//ISR()

Is there something else I can do to lower the power more?
Thank you for reading!

Modified Code now:

  • 588 micro Amp when LED is off
  • 2,166 micro Amp when LED is on

Other notes:

  • need to modify avrdude.conf (add attiny13a definition, just copy attiny13 and only change ID and Desc
  • iotn13a.h is used (some definitions are not included int attiny13.h)
  • unused pins activated pull-up resistor (Article 10.2.6 of attiny13a datasheet)
#include <avr/sleep.h>										
#include <avr/power.h>										
#define LED PORTB4

ISR(WDT_vect) {													
 PORTB ^= (1<<LED);
}//ISR()

void setup(){                           

  pinMode(LED, OUTPUT);
  pinMode(PORT0,INPUT);      //Article 10.2.6 of attiny13a datasheet
  pinMode(PORT1,INPUT);
  pinMode(PORT2,INPUT);
  pinMode(PORT3,INPUT);
  pinMode(PORT5,INPUT);
  digitalWrite(PORT0,HIGH);
  digitalWrite(PORT1,HIGH);
  digitalWrite(PORT2,HIGH);
  digitalWrite(PORT3,HIGH);
  digitalWrite(PORT5,HIGH);
  
  WDTCR |= (1<<WDP3) | (1<<WDTIE);      //Watchdog set for about 8 seconds						  
  ACSR	|= (1<<ACD);                    //Analog comparator off
  BODCR |= (1<<BPDSE)|(1<<BPDSE);       //Disable Brown Out Detector Control Register
  MCUCR	|= (1<<SM1);                    //Sleep mode to POWER DOWN
  PRR   |= (1<<PRADC)|(1<<PRTIM0);      //Power reduction timer enable , ADC off
  DIDR0	|= (1<<AIN0D)|((1<<AIN1D));     //Digital input disable
  
}// setup


void loop(){															
  sleep_cpu();    										
}//void loop()

Try this where you set ACSR:

ACSR = ADMUX = ADCSRA = 0;

Hello,
Thank you always for reading and for your kind insights.

Found a good link to reduce amperage during sleep mode to 4.5µA !.
However, I noticed that placing the code to setup() and loop() instead of main() yeilded different results.
Please see code and Amp reading below. Any thoughts on what is going on?

NOTES:

  • same attiny13a is used (same circuit also)
  • both codes have been uploaded several times
  • both codes show consistency of output after several uploads
  • all unused pin and reset pin are shorted to +3v of the cr2032

LED on =1700.0µA
LED off= 4.5µA

#include <avr/interrupt.h>
#include <avr/sleep.h>
ISR(WDT_vect) {
  PORTB ^= 1<<PORTB4;
}//ISR
int main(void) {
  DDRB = 1<<DDB4;
  WDTCR |= (1<<WDP3); // (1<<WDP2) | (1<<WDP0);
  WDTCR |= (1<<WDTIE);
  sei(); // Enable global interrupts 
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 for (;;) {
    sleep_mode();   // go to sleep and wait for interrupt...
  }//for
}//main

LED on =1830.0µA
LED off= 190.0µA

#include <avr/interrupt.h>
#include <avr/sleep.h>

ISR(WDT_vect){
  PORTB ^= 1<<PORTB4;
}//ISR

void setup(){
 DDRB = 1<<DDB4;
 WDTCR |= (1<<WDP3); // (1<<WDP2) | (1<<WDP0);
 WDTCR |= (1<<WDTIE);
 sei(); // Enable global interrupts 
 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}//void setup

void loop() {
 for (;;) {
  sleep_mode();   // go to sleep and wait for interrupt...
 }//for
}//main

Well, if you use setup() and loop(), you're letting the Arduino main() run, and that will turn on both timer0 and the ADC.
Using your own main(), those peripherals should be "never touched", and thus OFF.
In your initial code, you were explicitly turning things off (or at least attempting to!); what happened to that code in the latest example?

westfw:
In your initial code, you were explicitly turning things off (or at least attempting to!); what happened to that code in the latest example?

Since the latest code is working, there is no strong reason to keep the initial code. But thanks for the insight!

  • 4.5 microAmp was lowest amperage achieved when using the Watchdog Timer
  • it did not really matter if the other pins were shorted NOR ground or +3v (or not)
  • most efficient coding is to NOT use Arduino's loop() and main() functions