Arduino one avr/sleep and timer2 problem

Hi,
Im new in the arduino world, and i have to make a program that print the hour in the Serial monitor and alternate some leds. To make that i have used the timer2 using MsTimer2.
The problem becames when i have to put arduino to sleep if it recives an invalid hour from the Serial, and it's supposed to stop printing on the serial monitor, and keep updating the time using the timer2 interruptions.

Im ussing the library avr/sleep.h and using the SLEEP_MODE_EXT_STANDBY, testing using the standby mode i discovered that in that mode dont print in serial, but I asked to my teacher if its okay and say no.

if someone could help me I would be very grateful I am very stuck.

I let you the code (dont judge im newin this world)

#include<MsTimer2.h>
#include <avr/sleep.h>

volatile bool led;
volatile bool sleep;
const int  greenLed = 5;
const int redLed = 10;
const int btnPin = 3;
volatile int second = 0;
volatile int minute = 0;
volatile int hour = 0;
int th;
int tm;
int ts;
volatile bool tup;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(greenLed, OUTPUT);
  pinMode(redLed, OUTPUT);
  pinMode(btnPin, INPUT);
  set_sleep_mode(SLEEP_MODE_STANDBY);
  MsTimer2::set(1000,changeTime);
  MsTimer2::start();
  Serial.println("Clock Started");

}

void loop() {  
  if(sleep){
    sleepNow();
   }else{
    if(Serial.available() > 0){
    th = Serial.parseInt();
    tm = Serial.parseInt();
    ts = Serial.parseInt();
    tup = true;
    while (Serial.available()) Serial.read();
    }
  }   
}

void changeTime(){
     updateTime();
     if(led){ digitalWrite(greenLed,LOW); digitalWrite(redLed,HIGH); } 
     else{ digitalWrite(redLed,LOW); digitalWrite(greenLed,HIGH);}
     led = !led;
     printHour();
}

void updateTime(){
  if(tup){
     updateValues();
  }  
  second++;
  if(second>59){
    second = 0;
    minute++;
  }
  if(minute>59){
    minute = 0;
    hour++;
  }
  if(hour>23){
    hour= 0;
  }
}

void updateValues(){
   if(th > 23 || tm > 59 || ts > 59){
    th=0, tm=0, ts=0;
    tup = false;
    Serial.print("Entering sleep mode\n");
    Serial.flush();   
    sleepNow();
    }else{
    hour = th;
    minute = tm;
    second = ts;
    th = 0,tm=0,ts=0;
    tup = false;
    }
    
  }
 

void wakeUp(){
  sleep = false;
  detachInterrupt(digitalPinToInterrupt(btnPin));
}

void sleepNow() {
  digitalWrite(greenLed,LOW);
  digitalWrite(redLed,LOW);
  sleep = true;
  cli();
  sleep_enable();
  attachInterrupt(digitalPinToInterrupt(btnPin),wakeUp,FALLING);
  sei(); 
  sleep_cpu(); 
  sleep_disable();
}

void printHour(){
   Serial.print(hour);
   Serial.print(":");
   Serial.print(minute);
   Serial.print(":");
   Serial.print(second);
   Serial.print("\n");
   Serial.flush();
}

Simple solution: Don't use sleep and timers.

yeah, but the problem is that I need to use it T-T

First step: select a sleep mode that allows to receive Serial input.

Sorry if I don't explain myself well but the problem is that when the arduino go sleep, the program shouldnt print in serial monitor, i know that the timer2 makes an interruption and wake up arduino, but i have a bool to check if its sleep and go sleep again.
I use the extended standy mode because i want only to update the hour in memory and dont turn on leds and dont print in serial monitor.

So what does it print?

It looks like what you want is:

If the time is valid, display the updated time once per second.
Set the time from Serial if any characters have arrived.
Sleep as much as possible.
Is that correct?

You should be doing as little as possible in the interrupt handler. In your case, it should be sufficient to set a flag to say that the interrupt had occurred:

void changeTime()
{
  Tick = true;
}

and then handle the event in loop():

boolean Tick = false;
boolean TimeIsValid = false;
boolean LEDState = false;

void loop()
{
  if (Tick)
  {
    Tick = false;
    if (TimeIsValid)
    {
      digitalWrite(greenLed, LEDState); 
      digitalWrite(redLed, !LEDState); 
      LEDState = !LEDState;

      updateTime();
      printHour();
    }
  }

  // Act on incoming serial
  if(Serial.available() > 0)
  {
    // Read Hour, Minute, and Second from Serial
    th = Serial.parseInt();
    tm = Serial.parseInt();
    ts = Serial.parseInt();
    while (Serial.available()) 
      Serial.read();
    TimeIsValid = th < 24 && tm < 60 && ts < 60;
  }

  sleepNow();
}

I think i solve it but i dont know if its the correct way to do it, the only problem i found is if you introduce the time just before the time change it will not go sleep.

void loop() { 
  if(sleep){
     sleepNow();
  } 
  if (Tick)
  {
    Tick = false;
    updateTime();
      if(!sleep){
        digitalWrite(greenLed, LEDState); 
        digitalWrite(redLed, !LEDState); 
        LEDState = !LEDState;
        printHour();
      }  
  }

  // Act on incoming serial
  if(Serial.available() > 0 && !sleep)
  {
    // Read Hour, Minute, and Second from Serial
    th = Serial.parseInt();
    tm = Serial.parseInt();
    ts = Serial.parseInt();
    while (Serial.available()) 
      Serial.read();
    TimeIsValid = th < 24 && tm < 60 && ts < 60;
  }
}

void changeTime(){
     Tick = true;
}

thats the code your answer was very usefull but, i only want to sleep when a invalid time arrives, the rest of the time i want to print hour and update led state

Every interrupt will awake the controller, e.g. also some Serial input or ongoing output. You have to put the controller asleep at the end of every loop iteration.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.