Reduce power consumption using IDE

Any recommendations to reduce the power consumption for a 5V, 16MHz Pro Mini clone using software/IDE?

I've already done the hardware mods like removing the power LED and onboard LED. I limited the PWM to 50% and added 220ohm resistors for the fairy light LEDs that brought power consumption down to about 5mA per LED string (6 LEDs per string).

I checked out Nick Gammon's site, but I can't find a place in the code or a time when the uC isn't doing something to put it to sleep. I saw that reducing the frequency affects the power consumption. My understanding is the only way to reduce the frequency is by setting fuses. I don't want to use an ISP to set fuses because the Pro Mini is a WAVGAT clone, and I finally found a use for what is probably the worst clone.

Full Code:

/*
 * FairyLightFade
 * 15 June 2019
 * Big thanks to the Bald Engineer for the base code to fade using millis
 * pwm-fade-with-millis.ino
 * Created by James Lewis
 * See baldengineer.com/fading-led-analogwrite-millis-example.html 
 * for more information
 * 
 * CHALLENGES:
 * 1. Reduce power consumption
 * 2. Connect to 75mAh LiPo with BCM
 * 3. Squeeze everything into a mason jar
 */

// #include <avr/power.h>  // Only needed if power_all_xxxx used

const int pwmLED[] = {3,5,6,9};   // pins connected to LEDs
const int numPins = sizeof(pwmLED) / sizeof(int);  // should equal number of pins used 

const int unusedPins[] = {2,4,7,8,10,11,12,13,A1,A2,A3,A4,A5,A6,A7};  // pins not used
const int numUnusedPins = sizeof(unusedPins) / sizeof(int);   // should equal number of unused pins
 
// define directions for LED fade
#define UP 0
#define DOWN 1
 
// constants for min and max PWM
const int minPWM = 0;
const int maxPWM = 128;
 
// State Variable for Fade Direction
byte fadeDirection[] = {UP,DOWN,DOWN,UP};
 
// Global Fade Value
// but be bigger than byte and signed, for rollover
int fadeValue[] = {0,0,0,0};
 
// How smooth to fade? Smaller = slower
byte fadeIncrementUP = 10;
byte fadeIncrementDOWN = 3;
 
// How fast to increment in ms
int fadeInterval = 40;

// millis() timing Variable for fading and pause
unsigned long previousFadeMillis[numPins];
unsigned long previousPauseMillis[numPins];

// amount of time to pause between blinks
int minPause = 5000;        // minimum time to be off
int maxPause = 12000;       // maximum time to be off
int pauseInterval[numPins]; // determined by random number between min/maxPause
 
void setup() 
{
  // set pins used to OUTPUT & off
  for(byte i = 0; i < numPins; i++)
  {
    pinMode(pwmLED[i], OUTPUT);
    analogWrite(pwmLED[i], fadeValue[i]);   // put pwmLED into known state (off)
  }
  randomSeed(analogRead(A0));  // Generate random number based off of A0 (Pin A0)

  // set unused pins to low power state
  for(byte j = 0; j < numUnusedPins; j++)
  {
    pinMode(unusedPins[j], OUTPUT);
    digitalWrite(unusedPins[j], LOW);
  }

  // disable ADC to reduce power
  //  ADCSRA = 0;                 // Would this interfere with randomSeed on A0??
  // turn off various modules
  //  power_all_disable ();       // Can only be used before putting uC to sleep?? 
}
 
void loop() 
{
  // get the current time, for this time around loop
  // all millis() timer checks will use this time stamp
  unsigned long currentMillis = millis();

  for(int i = 0; i < numPins; i++)
  {
    // is it time to update yet?  if not, nothing happens
    if (currentMillis - previousFadeMillis[i] >= fadeInterval) 
    {
      // yup, it's time!
      if (fadeDirection[i] == UP) 
      {
        // LED brightens
        fadeValue[i] = fadeValue[i] + fadeIncrementUP;  
        if (fadeValue[i] >= maxPWM) 
        {
          // At max, limit and change direction
          fadeValue[i] = maxPWM;
          fadeDirection[i] = DOWN;
        }
      } 
      else 
      {
        //if we aren't going up, we're going down
        fadeValue[i] = fadeValue[i] - fadeIncrementDOWN;
        if (fadeValue[i] <= minPWM) 
        {
          // At min, limit and change direction
          fadeValue[i] = minPWM;
          pauseInterval[i] = random(minPause, maxPause);  // generate random off time
          analogWrite(pwmLED[i], 0);    // turn LED off
          if(currentMillis - previousPauseMillis[i] >= pauseInterval[i])
          {
            fadeDirection[i] = UP;                    // change direction
            previousPauseMillis[i] = currentMillis;   // reset for next iteration
          }
        }
      }
      // Only need to update when it changes
      analogWrite(pwmLED[i], fadeValue[i]);  
   
      // reset millis for the next iteration (fade timer only)
      previousFadeMillis[i] = currentMillis;
    }
  }
}

Putting a controller to sleep (to reduce power consumption) and expecting to use BWD for timing seems counterproductive.

BTW modern LEDs are efficient enough to be still visible at ~5mA.

Minor note: A more common way to compute the size of an array is

const int pwmLED[] = {3,5,6,9};   // pins connected to LEDs
const int numPins = sizeof(pwmLED) / sizeof(pwmLED[0]);  // should equal number of pins used

This way, if you change the type of the array, the code is still correct vs. hardcoding the denominator

According to the Fritzing idiot diagram, the Arduino is supplying power for the LEDs through the output pins, so sleep mode does not help much.

But your post suggests that the diagram is irrelevant. What are fairy light LED strings?

jremington:
According to the Fritzing idiot diagram, the Arduino is supplying power for the LEDs through the output pins, so sleep mode does not help much.

But your post suggests that the diagram is irrelevant. What are fairy light LED strings?

fairylilghts.jpg

fairylilghts.jpg

fairylilghts.jpg

Why don’t the fairies fly out of the open top? ???

blh64:
Minor note: A more common way to compute the size of an array is

const int pwmLED[] = {3,5,6,9};   // pins connected to LEDs

const int numPins = sizeof(pwmLED) / sizeof(pwmLED[0]);  // should equal number of pins used




This way, if you change the type of the array, the code is still correct vs. hardcoding the denominator

Thanks! I spent almost 2 weeks learning about arrays and found that somewhere along the way. I would like not being dependent on the variable for the array.

larryd & jremington,

I was wondering about finding a way to go into sleep mode when all the LEDs were off. Or perhaps turn off modules?

Something like:

if (fadeValue0==0 && fadeValue1==0 && fadeValue2==0 && fadeValue3==0)
    {
      (code to go into a sleep mode);
    }

If your application is turn OFF, turn ON in 1 hour take a reading, turn OFF, sleeping makes sense to save power when using battery power.

int fadeInterval = 40;
. . .
if (currentMillis - previousFadeMillis[i ] >= fadeInterval)

You have to scratch a lot to save power.

This being said, examine Jack Christensen’s ledFire simulator sketch to see a method that you could use in your project to protect your battery.

larryd:
This being said, examine Jack Christensen’s ledFire simulator sketch to see a method that you could use in your project to protect your battery.

I'll check it out. Thanks!