Sleep errors.

I am having some issues with the sleep mode in my project.

When I put it to sleep via pulling a pin low it works fine but when I try doing it by code with an auto off function ( at the end of the sketch) it leave some LED's on ( outputs high)

What have I missed?

I have had to delete much of the sketch as it was over the allowable post size but the Sleepnow part is included as is the auto off function at the end.

Thanks

Before posting code use the CTRL-T in the IDE to optimize layout, reads better :slight_smile:

Sorry

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


int ledoner = 2;      // select the pins for LED one
int ledoneg = 3;  
int ledtwor = 4;     // select the pins for LED two
int ledtwog = 5;  
int ledthreer = 6;   // select the pins for LED three
int ledthreeg = 7;  
int button = 10;    //button pin 10
int PPO1pin =A1;    // assign  sensor input pins
int PPO2pin =A0;
int PPO3pin =A2;
int LDR=A5;
int fail1=0;
int fail2=0;
int fail3=0;
int autooff=0;
int aveppo=0;


int ppo=20;    //internall generated value to be removed later
int ppo1 = 0;  //Value to be converted from O2 cell 1
int ppo2 = 0;  //Value to be converted from O2 cell 2
int ppo3 = 0;  //Value to be converted from O2 cell 3
int flash = 0; // Number of flashes from LED's  
int ppolow =0;  // value to measure PPO against
int ppohi=0; // value to measure PPO against
int mult1=0;
int mult2=0;
int mult3=0;
int mv1=0;
int mv2=0;
int mv3=0;
int state=0;
int mode=0;
int light=0;

void setup() 
{
  pinMode(ledoneg, OUTPUT);
  pinMode(ledoner, OUTPUT);
  pinMode(ledtwog, OUTPUT);
  pinMode(ledtwor, OUTPUT);
  pinMode(ledthreeg, OUTPUT);
  pinMode(ledthreer, OUTPUT);
  pinMode(button, INPUT);
  digitalWrite(button, HIGH);
  pinMode(LDR, INPUT);
  Serial.begin(9600); 
  pinMode(13, HIGH);
} 







void sleepnow()  {
  /* Now is the time to set the sleep mode. In the Atmega8 datasheet
   * http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
   * there is a list of sleep modes which explains which clocks and 
   * wake up sources are available in which sleep modus.
   *
   * In the avr/sleep.h file, the call names of these sleep modus are to be found:
   *
   * The 5 different modes are:
   *     SLEEP_MODE_IDLE         -the least power savings 
   *     SLEEP_MODE_ADC
   *     SLEEP_MODE_PWR_SAVE
   *     SLEEP_MODE_STANDBY
   *     SLEEP_MODE_PWR_DOWN     -the most power savings
   *
   *  the power reduction management <avr/power.h>  is described in 
   *  http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
   */

  digitalWrite(ledoner,LOW);
  digitalWrite(ledtwor,LOW);
  digitalWrite(ledthreer,LOW);
  digitalWrite(ledoner,LOW);
  digitalWrite(ledtwor,LOW);
  digitalWrite(ledthreer,LOW);

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here

  sleep_enable();          // enables the sleep bit in the mcucr register
  // so sleep is possible. just a safety pin 

  attachInterrupt(0,loop, LOW);// digital pin 1

  power_adc_disable();
  power_spi_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_timer2_disable();
  power_twi_disable();

  sleep_mode();            // here the device is actually put to sleep!!
  // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
  sleep_disable();         // first thing after waking from sleep:
  // disable sleep...
  power_all_enable();

} 



void loop() { 

  mult1 = EEPROM.read(1); // reads the prestored calibration values
  mult2 = EEPROM.read(2);
  mult3 = EEPROM.read(3);
  fail1 = EEPROM.read(4);
  fail2 = EEPROM.read(5);
  fail3 = EEPROM.read(6);


  mode=0;
  state= digitalRead (button);   //read button

    if (state==0) {
    { 
      digitalWrite(ledoneg,HIGH);
      delay (200);
      digitalWrite(ledtwog,HIGH);
      digitalWrite(ledtwor,HIGH); 
      delay (200);
      digitalWrite(ledthreer,HIGH); 
      delay(600);// turn on GOR
      state= digitalRead (button); 
    }  //read button

      if (state==0) {  
      digitalWrite(ledoneg,LOW); 
      digitalWrite(ledoner,LOW);
      delay (200);
      digitalWrite(ledtwog,LOW);
      digitalWrite(ledtwor,LOW);
      delay (200);
      digitalWrite(ledtwor,LOW);
      digitalWrite(ledthreer,LOW);
      delay(600); //turn off LEDs
      state= digitalRead (button); 
      if (state==1) mode =1;   
    }   //read button



    if (state==0) {
      digitalWrite(ledoneg,HIGH); 
      digitalWrite(ledtwog,HIGH); 
      digitalWrite(ledthreeg,HIGH);
      delay(1000) ; 
      if (state==1)mode=0;
      digitalWrite(ledoneg,LOW); 
      digitalWrite(ledtwog,LOW); 
      digitalWrite(ledthreeg,LOW);  
      state= digitalRead (button); 
      delay (1000) ; 
      if (state==1) mode=2;
    }


    if (mode==1) {
      delay(1000); 
      Serial.print(222); 
      Serial.print("\t");  
      sleepnow();
    }


    if (mode ==2)   {
      digitalWrite(ledoneg,HIGH);
      digitalWrite(ledtwog,HIGH);
      digitalWrite(ledthreeg,HIGH);
      delay (1000);//green
      digitalWrite(ledoner,HIGH);
      digitalWrite(ledtwor,HIGH);
      digitalWrite(ledthreer,HIGH);
      delay (1000);// orange
      digitalWrite(ledoneg,LOW);
      digitalWrite(ledtwog,LOW);
      digitalWrite(ledthreeg,LOW);
      delay (1000);//red
      digitalWrite(ledoneg,HIGH);
      digitalWrite(ledtwog,HIGH);
      digitalWrite(ledthreeg,HIGH);
      delay (1000);//orange
      digitalWrite(ledoneg,LOW);
      digitalWrite(ledtwog,LOW);
      digitalWrite(ledthreeg,LOW);
      delay (1000);//red
      digitalWrite(ledoner,LOW);
      digitalWrite(ledtwor,LOW);
      digitalWrite(ledthreer,LOW);
      delay (1000);//off

      mv1=analogRead(PPO1pin);    //calibrates and stores values in eeprom
      mv2=analogRead(PPO2pin);   
      mv3=analogRead(PPO3pin);   


      fail1=0;
      fail2=0;
      fail3=0;

    



      mult1=(mv1/4);   
      EEPROM.write(1, mult1);
      EEPROM.write(4, fail1); //calibrates and stores values in eeprom
      mult2=(mv2/4);   
      EEPROM.write(2, mult2);
      EEPROM.write(5, fail2);
      mult3=(mv3/4);   
      EEPROM.write(3, mult3);
      EEPROM.write(6, fail3);
    }


  }





  flash =flash+1;




  if (flash==9){
    (flash=1);
  }
  if (flash==1){
    mv1=analogRead(PPO1pin); //reads thecell values
    mv2=analogRead(PPO2pin); 
    mv3=analogRead(PPO3pin);     
    ppo1=(mv1*25)/mult1; //calculates PPO based on multiplier from calibration and mv from sensor
    ppo2=(mv2*25)/mult2;
    ppo3=(mv3*25)/mult3;
  }



  Serial.print(aveppo); 
  Serial.print("\t");
  Serial.print(autooff);  
  Serial.println("");

  if (flash==1) {
    ppolow=105; 
    ppohi=95;
  }  //turns red LED on if PPO is less than ppolo and gree LED ON if PPOP over ppohi. So both green and red will be on if pppo is 95-105
  if (flash==2) {
    (ppolow=85); 
    (ppohi=115);
  }  
  if (flash==3) {
    (ppolow=75); 
    (ppohi=125);
  }
  if (flash==4) {
    (ppolow=65); 
    (ppohi=145);
  }
  if (flash==5) {
    (ppolow=55); 
    (ppohi=155);
  }
  if (flash==6) {
    (ppolow=45); 
    (ppohi=165);
  }
  if (flash==7) {
    (ppolow=35); 
    (ppohi=175);
  }
  if (flash==8) {
    (ppolow=25); 
    (ppohi=185);
  }

  if (ppo1<ppolow) { 
    (digitalWrite(ledoner,HIGH));
  } //turns on 1st red LED when required
  if (ppo2<ppolow) { 
    (digitalWrite(ledtwor,HIGH));
  }
  if (ppo3<ppolow) { 
    (digitalWrite(ledthreer,HIGH));
  }

  if (ppo1>ppohi) { 
    (digitalWrite(ledoneg,HIGH));
  } //turns on 1st green LED when required
  if (ppo2>ppohi) { 
    (digitalWrite(ledtwog,HIGH));
  }
  if (ppo3>ppohi) { 
    (digitalWrite(ledthreeg,HIGH));
  }



  if (fail1==1) {
    (digitalWrite(ledoner,LOW)); 
    (digitalWrite(ledoneg,LOW));
  }
  if (fail2==1) {
    (digitalWrite(ledtwor,LOW)); 
    (digitalWrite(ledtwog,LOW));
  }
  if (fail3==1) {
    (digitalWrite(ledthreer,LOW)); 
    (digitalWrite(ledthreeg,LOW));
  }


  delay (250); 
  digitalWrite(ledoner,LOW); 
  digitalWrite(ledoneg,LOW); 
  digitalWrite(ledtwor,LOW); 
  digitalWrite(ledtwog,LOW); 
  digitalWrite(ledthreer,LOW); 
  digitalWrite(ledthreeg,LOW)  ;
  delay (250);  
  aveppo=((ppo1+ppo2+ppo3)/3);
  if (aveppo<=40) autooff+=1;
  if (aveppo>=40) autooff=0;
  if (autooff== 50) {
    autooff=0;
    delay(1000);
    sleepnow();
  } 

}

Thanks, (you could also modified your previous post, but OK)

Problem seems to be in sleepnow, as you only put the red LEDs low (twice :slight_smile:

void sleepnow()  {
  /* Now is the time to set the sleep mode. In the Atmega8 datasheet
   * http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
   * there is a list of sleep modes which explains which clocks and 
   * wake up sources are available in which sleep modus.
   *
   * In the avr/sleep.h file, the call names of these sleep modus are to be found:
   *
   * The 5 different modes are:
   *     SLEEP_MODE_IDLE         -the least power savings 
   *     SLEEP_MODE_ADC
   *     SLEEP_MODE_PWR_SAVE
   *     SLEEP_MODE_STANDBY
   *     SLEEP_MODE_PWR_DOWN     -the most power savings
   *
   *  the power reduction management <avr/power.h>  is described in 
   *  http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
   */

  digitalWrite(ledoner,LOW);   <<<<<<
  digitalWrite(ledtwor,LOW);
  digitalWrite(ledthreer,LOW);
  digitalWrite(ledoner,LOW);   <<<<<<<<
  digitalWrite(ledtwor,LOW);
  digitalWrite(ledthreer,LOW);

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here

  sleep_enable();          // enables the sleep bit in the mcucr register
  // so sleep is possible. just a safety pin 

  attachInterrupt(0,loop, LOW);// digital pin 1

  power_adc_disable();
  power_spi_disable();
  power_timer0_disable();
  power_timer1_disable();
  power_timer2_disable();
  power_twi_disable();

  sleep_mode();            // here the device is actually put to sleep!!
  // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
  sleep_disable();         // first thing after waking from sleep:
  // disable sleep...
  power_all_enable();

}

Oops, so I did but that is not the problem. ( if you turn it off twice it should still be off shouldnt it?)
It was supposed to be turning the other 3 LED's off as well even though they dont need it.

What seems to be happening is once it gets to the sleep command the sketch continues to run the loop for about 2 seconds at a very high speed while ignoring the delays.

When I put it to sleep via pulling a pin low it works fine but when I try doing it by code with an auto off function ( at the end of the sketch) it leave some LED's on ( outputs high)

What have I missed?

Which leds stay on ???

Oops, so I did but that is not the problem. ( if you turn it off twice it should still be off shouldnt it?)

No, twice is ok, but you should disable the green ones too

Can you explain why you do this: attachInterrupt(0,loop, LOW);// digital pin 1
Is it needed?

I need to be able to switch the unit back on again and I thought that was the command to do it.
ie if digital pin 1 goes LOW then goto loop.

I am probably wrong since it does not work :~

interrupt 0 is digital pin 2, not digital pin 1

So it is.
But this does not fix the problem of it not turning off the LED's before sleeping. I have got around that by waiting until the end of the loop before sending it to sleep.

So now it goes to sleep and all the LED's are off. But when I ask it to wake up it does ( as far as I can tell) runs through part of the loop, turns on an LED the seems to crash.

Any suggestions on how to diagnose the problem?

I have thrown in a few serial writes and to see how far it gets but that does not seem to help.
I put one in front of any code turning on that LED but it does not show in the Serial monitor. Perhaps I should put a delay after the serial write??: edit: This worked some what and I think I know the point at where it crashes. After one pin is set LOW(LED) and just before another will be.

So regarding the command attachInterrupt(0,loop, LOW); 0= digital pin 2, loop = where the program restarts ( How do you get it to restart where it interrupted)?, LOW= means you pull the pin low to interrupt the sleep. Is this all correct?

No experience with sleepmode with Arduino, but I think the Arduino just stops in the middle of sleepNow() and if it wakes up it continues where it left.

From logic point of view it makes no sense to call loop from an IRQ as it is too big and it will be called automatically . SO I can imagine you get a stack overflow or reentry problem.

Please remove the attachInterrupt line //comment it and retry

Thanks, I tried that and it didnt work. What did work was detachInterrupt(interrupt).
In fact it solved both issues. Now LED's turn off and it wakes up and stays awake on the next button push.

But I (sort of) understand what you mean and wonder if there is a better way to wake it back again.

Next mission is to figure out how to make it wake up every few minutes, check an input and go back to sleep unless xxxxxx.
Watch dog timer sounds like it does this.

Yes the watchdog timer does this. I've used Jeelabs' Sleepy class in their Ports library which wraps up all the sleep and watchdog related stuff into a few methods.