Wake up arduino using Serial communication

Hi everyone and good afternoon!
In order to save energy, i tried some time ago to send a code in hexa using the serial port of the arduino (ATMEGA2560) to place it into sleep except for the usart (still awake).

This part was working without issues. The second goal was too wake it up using an another hexa code. I tried to link an interruption pin on Rx and wake up the arduino when receiving the code.

The problem is that it was waking up for any code (because interruption is just spotting a change of voltage). So i added a condition after wake up (if (not the good code)-->go back to sleep) but impossible to go back to sleep. I think it is because of some interruption flag not set somewhere but I can't find where.

If you have any suggestion or a better idea of how to implement some kind of ON/OFF application :grinning:

Here is the testing code from that time.

#include <avr/wdt.h>            // library for default watchdog functions
#include <avr/interrupt.h>      // library for interrupts handling
#include <avr/sleep.h>          // library for sleep
#include <avr/power.h> 
#include <avr/io.h>
#define LED 3
#define pin2_Interrupt 2

ISR(INT0_vect){ 
  }

char enterSleepONOFF(char State)
{ 
  Serial.println(State);
  if(State =='I'){
    power_all_enable();      
    Serial.println( "awake" );
  }
  else{
   set_sleep_mode( SLEEP_MODE_IDLE );
   cli();
   Serial.println( "sleeping\n" );
   Serial.flush();
   sleep_enable();
   sei();
   power_all_disable();
   power_usart0_enable(); //only let the usart0 awake to wake up the arduino
   sleep_mode();
   sleep_disable();
   State = Serial.read();
   power_all_enable();
   Serial.println("Interrupt");
   cli();
   Serial.println(State);
   Serial.println("i'm here");
   return State;
  }
  
  
}
void setup() {
  // put your setup code here, to run once:
  pinMode(LED,OUTPUT);
  Serial.begin(9600);
  Serial.println("Initialisation complete.");
}

void loop()
{
  sei();
  char inSleep;
  int WakeUp = 0;
  char State=Serial.read();
  Serial.println(State);
  if (State== 'O'|| WakeUp == 1){
    inSleep = enterSleepONOFF(State);
    Serial.println("back to sleep");
    Serial.println(inSleep);
    if (inSleep =! 'I'){
      inSleep = enterSleepONOFF(State);
      WakeUp = 1;
      }
    else{
      WakeUp=0;
    }
    }
  delay(6000);
  digitalWrite(LED,HIGH);
  delay(100);
  digitalWrite(LED,LOW);
  cli();
  }

Thanks in advance and sorry for my poor english! :sweat_smile:

char enterSleepONOFF(char State)

It would be far better to have two functions - one to go to sleep and one to wake up.

Why do you keep turning interrupts off and on in loop()?

    if (inSleep =! 'I'){

What does THAT operator do?

Hi thanks for your reply!
Doing 2 funcitons would be better indeed, i have no idea why i did not think about it!

I keep turning interrupts on and off because i want to call the function latter in a bigger programme, i just thought that implementing it right now won't change much.

And this operator is supposed to verify the fact that the caractere send on the Serial port is the right one. But this one is not working yet because the interruption seems to already take the signal on the Serial port to launch the interruption. So i can't read this signal which is the main target in the programme (like if not 'I', go back to sleep)

PaulS:

    if (inSleep =! 'I'){

What does THAT operator do?

I think it will assign zero/false to inSleep.

'I' will be treated as the ASCII code for capital letter I. "!" is the logical-NOT operator. Any non-zero value, such as the ASCII code for I, will be treated as true, and not(true) is false, which is represented as zero. The "=" operator is assignment, so inSleep will be set to zero. C language is full of bear-traps.