4

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?

thallia
  • 43
  • 1
  • 4

1 Answers1

9

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.

Nick Gammon
  • 38,901
  • 13
  • 69
  • 125