2

I'm working on a binary watch project. I want my circuit to live off of batteries for as long as possible, so I want to decrease the power consumption of my chip.

I'm using a barebones ATmega328P-PU with two 74HC595 shift registers. The ideal situation would be to keep the CPU, clock, flash, and I/O going so my program can continuously count the time on its own, but disable everything else that I'm not using, such as the ADC, BOD, TWI, timer1 and timer2, USART0, etc.

I took a look at the ATmega328P datasheet for the sleep modes, and it seems as though they all disable the CPU/Clock. Is this true? And if so, are there ways to disable the modules without enacting a sleep mode?

  • 2
    You do not want to keep the CPU running on a battery-powered project! You should use a timer for keeping the time, and let the CPU sleep. Ideally, you would connect a 32,768 Hz crystal to TOSC1/TOSC2 and have Timer 2 work in RTC mode. I have a clock running since June 2012 on the same pair of AA cells using this low-power technique. – Edgar Bonet Mar 14 '18 at 9:12
  • 1
    You could use sleep_mode_idle. You can also try running at a slower speed. But that won't save a whole lot. I'd second the idea from Edgar, in using a 32kHz cystal to run timer2 in asynchronous mode, and put the MCU in SLEEP_MODE_PWR_SAVE. – Gerben Mar 14 '18 at 16:21
4

Certainly there is.

  // disable ADC
  ADCSRA = 0;  

You can disable lots of internal modules like this:

  power_all_disable();  // turn off all modules

See my page about power saving.


Majenko commented that turning off the ADC, while leaving the processor running was pointless. The real way to save battery power is to sleep, and it is possible to do that and still keep track of the time.

On my page about timers there is code to use a 32.768 kHz clock crystal to sleep and wake every second, which you could then use to alter the display on your watch.

Code from that page:

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

const byte tick = 3;

// interrupt on Timer 2 compare "A" completion - does nothing
EMPTY_INTERRUPT (TIMER2_COMPA_vect);

void setup() 
 {
  pinMode (tick, OUTPUT);

  // clock input to timer 2 from XTAL1/XTAL2
  ASSR = bit (AS2);  

  // set up timer 2 to count up to 32 * 1024  (32768)
  TCCR2A = bit (WGM21);                             // CTC
  TCCR2B = bit (CS20) | bit (CS21) | bit (CS22);    // Prescaler of 1024                                  
  OCR2A =  31;              // count to 32 (zero-relative)                  

  // enable timer interrupts
  TIMSK2 |= bit (OCIE2A);

  // disable ADC
  ADCSRA = 0;  

  // turn off everything we can
  power_adc_disable ();
  power_spi_disable();
  power_twi_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_usart0_disable();

  // full power-down doesn't respond to Timer 2
  set_sleep_mode (SLEEP_MODE_PWR_SAVE);  

  // get ready ...
  sleep_enable();

  }  // end of setup

void loop() 
  { 

  // turn off brown-out enable in software
  MCUCR = bit (BODS) | bit (BODSE);
  MCUCR = bit (BODS); 

  // sleep, finally!
  sleep_cpu ();  

  // we awoke! pulse the clock hand
  digitalWrite (tick, ! digitalRead (tick));

  }  // end of loop

Whilst asleep, the processor uses very little power. In the example sketch I measured 1.46 µA current consumption, when the output was LOW, if running from 5V power supply, and 1.1 µA if running from 3.3V power supply.


Example setup:

Low-power clock board

I have two decoupling capacitors (the blue ones). A pull-up resistor on Reset. A 32.768 kHz crystal between pins 9 and 10. A 22 pF capacitor between each leg of the crystal and ground.

A current-limiting resistor and a LED. It works, and toggles at 1 Hz. When asleep (LED not on) it draws 1.46 µA as mentioned above.

| improve this answer | |
  • Thank you for the quick response! I added these to the void setup() part of my code, recompiled/loaded and tested it, but there was no change in the power draw of my circuit. It's sticking around 0.39mA. Is this normal? – thallia Mar 14 '18 at 8:58
  • I only tried out the top suggestion (as well as power_adc_disable();), since I don't want to power off everything, as the bottom line of code suggests. – thallia Mar 14 '18 at 9:06
  • The ADC contributes about 0.00001% to the total power draw. The saving is swamped by the CPU consumption. Turning off just the ADC is pointless. – Majenko Mar 14 '18 at 10:11
  • Have you tested that? According to my measurements turning off ADC results in almost 1/1000 times power consumption. – Nick Gammon Mar 14 '18 at 11:06
  • > With that there the power consumption drops a large amount, down from 335 µA to 0.355 µA! (that is, 355 nA) – Nick Gammon Mar 14 '18 at 11:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.