Sleep and waking the arduino

I’m in the final stretch of my project. The entire program is written without any power savings methods. It works and works well. Nearly the entire program is interrupt driven, 1 timer interrupt and a bunch of PCINT pin change interrupts. The ISR will set a bit when the display needs updating which occurs in the main.

So now time to save some power while I wait for the interrupts. Timer 1 fires every 100ms and the sensor should fire no more than every 750ms. So there’s lots of time to sleep.

I will first post the parts of the code I think most relevant (rather than all 2549 lines).

Setup:

void setup()
 {
  unsigned long current_time; 

  Reset_Counts();

  lcd.begin(16, 2);               // start the library
  lcd.setCursor(0,0);             // set the LCD cursor position 
  lcd.print("Production Count");
  lcd.setCursor(0,1);             // set the LCD cursor position 
  lcd.print("Ver. ");
  lcd.print(SW_VERSION);
  lcd.print(" ");
  lcd.print(SW_DATE);

  current_time = millis();

  pinMode(SENSOR_INPUT_PIN, INPUT_PULLUP);
  pinMode(START_STOP_PIN, INPUT_PULLUP);
  pinMode(SCROLL_PIN, INPUT_PULLUP);
  pinMode(MODE_PIN, INPUT_PULLUP);
  pinMode(LBO_PIN, INPUT_PULLUP);
  pinMode(13, OUTPUT);

  invert_digital_input_state[SENSOR_INPUT_PIN] = true;
  invert_digital_input_state[START_STOP_PIN] = true;
  invert_digital_input_state[SCROLL_PIN] = true;
  invert_digital_input_state[MODE_PIN] = true;
  invert_digital_input_state[LBO_PIN] = true;
  
 // Setup Timer 1 interrupt at 1mSec 
  TCCR1A = 0;          // normal operation
  TCCR1B = bit(WGM12) | bit(CS10) | bit (CS11);   // CTC, scale to clock / 1024
  OCR1A =  249;       // compare A register value (1000 * clock speed / 1024)
  TIMSK1 = bit (OCIE1A);             // interrupt on Compare A Match
  
 // Setup Pin Interruprs D8-D13
  if (SENSOR_INPUT_PIN<=7)
   {   PCMSK2 |= bit (SENSOR_INPUT_PIN); }
   else
    {   PCMSK0 |= bit (SENSOR_INPUT_PIN % 8); }

  if (START_STOP_PIN<=7)
   {   PCMSK2 |= bit (START_STOP_PIN); }
   else
    {   PCMSK0 |= bit (START_STOP_PIN % 8); }

   if (SCROLL_PIN<=7)
   {   PCMSK2 |= bit (SCROLL_PIN); }
   else
    {   PCMSK0 |= bit (SCROLL_PIN % 8); }

  if (MODE_PIN<=7)
   {   PCMSK2 |= bit (MODE_PIN); }
   else
    {   PCMSK0 |= bit (MODE_PIN % 8); }

  if (LBO_PIN<=7)
   {   PCMSK2 |= bit (LBO_PIN); }
   else
    {   PCMSK0 |= bit (LBO_PIN % 8); }

  PCIFR  |= bit (PCIF0);   // clear any outstanding interrupts
  PCICR  |= bit (PCIE0);   // enable pin change interrupts for D8 to D13
  
 // Setup Pin Interruprs D0-D7
  PCIFR  |= bit (PCIF2);   // clear any outstanding interrupts
  PCICR  |= bit (PCIE2);   // enable pin change interrupts for D8 to D13
  
  
  Run_Status=STOPPED;
  Timing_Mode=CYCLE_TIME;
  
  Display_Line_1 = 0;
  Display_Line_2 = 1;

  set_sleep_mode(SLEEP_MODE_PWR_SAVE);

  do
   { } while (millis()-current_time < 5000);
  clear_display();
  timing.display_update = true;
 }

Main:

void loop()
 {
  if (timing.display_update == true)
   {
    timing.display_update = false;
    update_display();
   }
   
  if (timing.calc_required == true)
   {
    timing.calc_required = false;
    Calculate_Production();
   }

  sleep_mode(); 
 }

One Pin change ISR:

ISR (PCINT2_vect) // Pins D0 to D7
 {
  unsigned long current_time;
  current_time=millis();

  if (debounce_task(SENSOR_INPUT_PIN, PIND, current_time, SENSOR_DEBOUNCE_TIME))
   {
    digitalWrite(13, digital_input_state[SENSOR_INPUT_PIN]);
    timing.display_update = true;
    if (Run_Status == RUNNING)
     {
      if (digital_input_state[SENSOR_INPUT_PIN] == Sensor_Start_State)
       { timing.mech_cycle_start = timing.msec_count; }
      if (digital_input_state[SENSOR_INPUT_PIN] != Sensor_Start_State) 
       {
        if (timing.stat == RESET)
         { timing.stat = WAITING; }
         else
          {
           if (timing.count==0)
            {
             timing.veh_cycle_start = timing.msec_count;
             timing.mech_cycle_start = timing.msec_count;
             Display_Line_2 = 3;
            }
            else
             {
              timing.veh_cycle_stop = timing.msec_count;
              timing.mech_cycle_stop = timing.msec_count;
              timing.calc_required = true;
             }
           timing.count++;
           if (timing.stat == WAITING)
            { timing.stat = COUNTING; }        
           if (timing.count > 9999)
            { timing.count = 1; }        
          }   
       } 
     }
   }
 }

The program completes the setup routine, then executes the main loop. I’m not sure, but I think it sleeps. Then I press and hold the button to fire the pin change interrupt, the pin 13 LED comes on. But that’s it. When the button is released, the LED does not turn off. It acts like the interrupt on release is not happening or the processor is not waking to process it.

I’m hoping someone has worked with the interrupts and sleep modes to help me out here.

More information.

I went through and tried each of the six sleep modes. The only one that works is IDLE. The other five only acknowledge the first interrupt. After that, nothing.