What to turn off, and how?

I'm trying to figure out what all I can turn off on a 328P to save on battery consumption. The majority of what it's doing is driving two LED strings (2-wire communication) using A0 - A3 (don't ask), then it has 2 separate LEDs (pins 3 and 4) that act as indicators, one's a heartbeat and the other flashes when the unit receives an RF signal. The RF module uses pins 13, 12, 11, 8, and 7 (SPI communications). The SPI pins are broken out but they're shared with the RF module pins. The FTDI pins are also broken out (RX/TX/RST), and there's an external oscillator attached as well.

So what can be turned off? Do I need the watchdog? Do I need the ADC? What about the timers? And how does one turn them off? Is it all done in programming?

Is it all done in programming?

yes, of course. Practically, your best bet is to make sure your unused pins are set to outputs or have pullups enabled. The other things you're talking about probably only make a small difference compared to the other things you have in your system (the whole AVR should consume less than 25mA when active. (table 29-16 "Additional current consumption" in the datasheet says that the peripherals add 1 to 4% additional for each of the 7 possible. ADC is most power hungry.)

Ok, so basically just do something like 'pinMode(UNUSED_PIN, OUTPUT);' would suffice? What about killing the ADC?

You could also use low current LED (around 3mA instead of 20mA)

Your best bet is to look in the datasheet. It's really not that bad if you know what you're looking for, and I hadn't even thought of it as a good place to find information.

Here's a similar project.

Also, please don't cross-post.

After declaring pinMode, digitalWrite the unused pins HIGH. Also helps to run from 3 1.5V batteries & bypass the regulator.

WizenedEE: I specifically didn't cross post, I merely added a pointer from one thread to the other. I didn't know whether my question pertained to either of them, partly because I thought it could have to do with fuses, in which case, in my mind, it has to do with the microcontroller itself, and not programming. But then it dawned on me, maybe what I wanted to achieve can only be done (or also done) through programming, in which case my post should've been there. If you're going to nitpick about a pointer from one to the other, I say find something better to do. There are far worse posters than me.

CrossRoads: Possible. I could also put a zener in place and drop the incoming 6V down and do away with a regulator. As I've discovered I ordered the wrong regulator to begin with, the zener route is looking promising at the moment. Doubt I have enough time to build up another order in time (I'm not paying high shipping for $12 worth of stuff.)

0.7V series Diode drop would do it, get you down to 5.3V.

The following code works well for me, the ATmega328P draws < 0.5µA current while in power-down mode (running on 2 AA cells). Before calling goToSleep(), I ensure that all pins are either (a) defined as inputs with pullups enabled, or (b) set to a low level if they’re output pins driving loads like LEDs or whatever. Be sure to provide a way to wake up, in this case I’m using pin change interrupts on any of several pins.

Of course this will not reduce current consumption of other circuit components like voltage regulators, etc., as CrossRoads correctly states.

#include <avr/sleep.h>
void goToSleep()
    byte adcsra, mcucr1, mcucr2;

    PCICR = _BV(PCIE1);            //enable pin change interrupts 8-14
    PCMSK1 = _BV(PCINT8) | _BV(PCINT11) | _BV(PCINT12) | _BV(PCINT13);    //enable PCINT8,11,12,13 (PC0,3,4,5)
    adcsra = ADCSRA;               //save the ADC Control and Status Register A
    ADCSRA = 0;                    //disable ADC
    mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE);  //turn off the brown-out detector
    mcucr2 = mcucr1 & ~_BV(BODSE);
    MCUCR = mcucr1;                //timed sequence
    MCUCR = mcucr2;                //BODS stays active for 3 cycles, sleep instruction must be executed while it's active
    sei();                         //ensure interrupts enabled so we can wake up again
    sleep_cpu();                   //go to sleep
    sleep_disable();               //wake up here
    ADCSRA = adcsra;               //restore ADCSRA