Go Down

Topic: Advise needed: Trying to achieve lowest power on an attiny13a (Read 1 time) previous topic - next topic

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!

Code: [Select]

#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()


Nick Gammon

Code: [Select]

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:

Code: [Select]

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


http://www.gammon.com.au/interrupts
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

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

http://www.gammon.com.au/power

Try turning off the ADC.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

westfw

Quote
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:
Code: [Select]
  _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!)

attiny13a

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

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

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




attiny13a

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)



Code: [Select]

#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()

fungus

Try this where you set ACSR:

Code: [Select]

ACSR = ADMUX = ADCSRA = 0;

No, I don't answer questions sent in private messages (but I do accept thank-you notes...)

attiny13a

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
Code: [Select]

#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
Code: [Select]

#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

westfw

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?

attiny13a

#9
Nov 26, 2013, 07:25 am Last Edit: Nov 26, 2013, 09:53 am by attiny13a Reason: 1
Quote from: westfw link=topic=200430.msg1

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!


attiny13a


  • 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


Go Up