Time out soluttion

Hello Arduino masters. I am struggling on one place, and can not seems to continue. What I have in mind is this:
Press a button-> some function start->another function, that count time(timeOut), starts->if some button is pressed->something happens->timeOut reset-If timeOut reach certain value, current function stop, and another function appear.
I am having trouble to clear that into a code. Maybe I am failing to simplify it, and get a clear the idea. The main idea is to hit a button, and display some options on LCD screen, than if no option is chosen (no same or another button hit is registered) for n-amount of time, than clear the screen, and show its normal state.
I am trying to make this timer in function because I am on the limit of my Arduino Uno memory, and I am wondering if it will be possible create the timeOut counter with function thus saving some memory since it can be reused. Any advice will be much appreciated!

Thanks in advance!

use a state machine and millis ➜ look at Using millis() for timing. A beginners guide and Several things at the same time

2 Likes

Post the code you have - there may be other ways to save memory.

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h> //Library or DS1820 temperature sensor
#include <DS3231.h> //Library for DS3231 RTC time, and temperature 
#include <LiquidCrystal.h>

//LCD def
LiquidCrystal LCD(9,8,7,5,4,3);

// Data wire (of DS1820) is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

//SetUpClock
DS3231 myRTC;

File myFile;

double Temperature;
double TemperatureII;
#define button1Pin A1 // where the set button is connected
#define button2Pin A2 // where the Options button is connected
#define button3Pin A3 // where the Options button is connected

bool celsius=true;
char CF;

//Time measurment values
byte hrNow;
byte minNow;
byte interval=1;
byte hrRecord=0;
byte minRecord=0;
unsigned long previousTime=0;
unsigned long timeOutInterval=1000;


//RTC requiered valuues
bool century = false;
bool h12Flag;
bool pmFlag;
bool SpecialEvent=false;


//=================================


void setup() {
   //LCD intro
  LCD.begin (16,2);
  LCD.setCursor (3,0);
  LCD.print ("Nav Light:");
  LCD.setCursor (3,1);
  LCD.print ("TempGraber");
  delay(4000);
  LCD.clear();
  
  // Start up the DallasTemperature library
  sensors.begin();
  
  pinMode(button1Pin, INPUT);
  pinMode(button2Pin, INPUT);
  pinMode(button3Pin, INPUT);

  // Start the I2C interface
  Wire.begin();
  Serial.begin(9600);
   //Card start
  LCD.setCursor (0,0);
  LCD.print ("SD card check...");
  delay(2000);
  LCD.clear();
  
  if(!SD.begin(10)) {
    LCD.setCursor (0,0);
    LCD.print ("SD card failed!");
    return;
  }
    LCD.setCursor (0,0);
    LCD.print ("SD card OK.");
    delay(2000);
    LCD.clear();
  
  //Open file
  myFile=SD.open("DATA.txt", FILE_WRITE);
    if (myFile) {
    LCD.setCursor (0,0);
    LCD.print ("File OK.");
    delay(2000);
    LCD.clear();
  }
  myFile.close();

}

//=================================

void loop() {
 // put your main code here, to run repeatedly:
 //Celsius/Farenhaind switch*/
 if (digitalRead(button1Pin) == HIGH) {
     celFarSwitch();
 }
 delay(100);
 
//ShowTime();

 
 if (digitalRead(button3Pin)== HIGH) {
  Serial.println ("B3");
 }
 if (celsius == true){
   cTemp();
 }
 else {
   fTemp();     
 }
 Display();
 fileWrite(); 
   
}

//=================================

void cTemp(){
  sensors.requestTemperatures();
  Temperature = sensors.getTempCByIndex(0);
  TemperatureII = sensors.getTempCByIndex(1);
  CF='C';
  }
  
void fTemp() {
  sensors.requestTemperatures();
  Temperature = (sensors.getTempCByIndex(0) * 9.0) / 5.0 + 32.0;
  TemperatureII = (sensors.getTempCByIndex(1) * 9.0) / 5.0 + 32.0;
  CF='F';
}

void fileWrite(){
 //check current hour and minute  
 hrNow=myRTC.getHour(h12Flag, pmFlag);
 minNow=myRTC.getMinute();
 //check if record time came
  if (hrNow==hrRecord && minNow==minRecord) {
  myFile=SD.open("DATA.txt", FILE_WRITE);
  myFile.print("Date: ");
  myFile.print(myRTC.getDate(), DEC);
  myFile.print(".");
  myFile.print(myRTC.getMonth(century), DEC);
  myFile.print(".");
  myFile.print(myRTC.getYear(), DEC);
  myFile.print(" ");
  myFile.print("Record time: ");
  myFile.print(myRTC.getHour(h12Flag, pmFlag), DEC); //24-hr
  myFile.print(":");
  myFile.print(myRTC.getMinute(), DEC);
  myFile.print(":");
  myFile.print(myRTC.getSecond(), DEC);
  myFile.print(" "); 
  myFile.print("Temperature Sensor (0): ");
  myFile.print(" ");
  myFile.print(Temperature);
  myFile.print(" ");
  if (celsius==true) {myFile.print("C");}
  else { myFile.print("F");}
  myFile.print(" ");
  myFile.print("Temperature Sensor (1): ");
  myFile.print(" ");
  myFile.print(TemperatureII);
  if (celsius==true) { myFile.print("C");}
  else { myFile.print("F");}
  myFile.print(" ");
  myFile.print("Room temperature:  ");
  myFile.print (myRTC.getTemperature());
  myFile.print("C");
  myFile.println(" ");
  myFile.close(); 
  //set records time to 0;
  minRecord=0; 
  hrRecord=0;
  //Print Record message. If special event is true, print nothing.
  if (SpecialEvent==false) {
    LCD.clear();
    LCD.setCursor (0,0);
    LCD.print ("Record added.");
    LCD.setCursor (0,1);
    LCD.print(myRTC.getHour(h12Flag, pmFlag), DEC); //24-hr
    LCD.print(":");
    LCD.print(myRTC.getMinute(), DEC);
    LCD.print(":");
    LCD.print(myRTC.getSecond(), DEC);
    delay(2000);
    LCD.clear();  
  }
 }
 //set record time
 minRecord = minNow + interval;
 Serial.println(minNow);
  Serial.println(interval);
   Serial.println(minRecord);
 if (minRecord < 60) {
  hrRecord=myRTC.getHour(h12Flag, pmFlag);
 }
 else {
  minRecord = minRecord - 60;
  hrRecord=hrRecord=myRTC.getHour(h12Flag, pmFlag)+1;
 } 
}

void Display(){
  LCD.setCursor (0,0);
  LCD.print ("Snsr0:");
  LCD.setCursor (7,0);
  LCD.print (Temperature);
  LCD.print((char)223);
  LCD.print (CF);
  LCD.setCursor (0,1);
  LCD.print ("Snsr1:");
  LCD.setCursor (7,1);
  LCD.print (TemperatureII);
  LCD.print((char)223);
  LCD.print (CF);
  }

  void ShowTime(){
  SpecialEvent=true;
  LCD.clear();  
  LCD.setCursor (0,0);
  LCD.print ("Date: ");
  LCD.print(myRTC.getDate(), DEC);
  LCD.print(".");
  LCD.print(myRTC.getMonth(century), DEC);
  LCD.print(".");
  LCD.print(myRTC.getYear(), DEC);
  LCD.setCursor (0,1);
  LCD.print ("Time: ");
  LCD.print(myRTC.getHour(h12Flag, pmFlag), DEC); //24-hr
  LCD.print(":");
  LCD.print(myRTC.getMinute(), DEC);
  LCD.print(":");
  LCD.print(myRTC.getSecond(), DEC);
  delay(3000);
  LCD.clear();
  }
    void SetInterval(){
  SpecialEvent=true;
  LCD.clear();  
  LCD.setCursor (0,0);
  LCD.print ("Set save time: ");
  LCD.setCursor (0,1);
  LCD.print(interval);
  LCD.print (" min.");
 }

 void celFarSwitch() {
  SpecialEvent=true;
  LCD.setCursor (0,0);
  LCD.print ("Cel./F. switch ");
  LCD.setCursor (0,1);
  if (celsius==true) {
    LCD.print ("Celsius  <  >   ");
  }
  else {
    LCD.print ("Farenhaind <  > ");
  }
  if (digitalRead(button2Pin)== HIGH) {
   delay(300);
   celsius=!celsius;
 }
 delay(200);
 if (digitalRead(button1Pin) == HIGH) {
  SpecialEvent = false;
  LCD.clear();
 }
}

You can claw a fair bit of RAM back using the F macro when you're printing string literals e.g.:

  LCD.print (F("Nav Light:"));
1 Like

Thank you wildbill! I will adjust accordingly.
WOW it drop with 7 percent! :slight_smile:

Alright,
Maybe I got it. It goes like this:

unsigned long timeCounter=0;
unsigned long timeOfEvent =0;
unsigned long interval=20000;

void loop() {
 timeCounter = millis();
if (digitalRead(button1Pin) == HIGH) { //so we hit a button
  timeOfEvent = millis(); //we mark the time of that event, and also reset the time out 
  options++; // we give a new value to the switch function
  delay (200);
 }

switch (options){
  case 0:
   Menu1();
  break; 
  case 1:
   Menu2();
  break; 
   Menu3();
  break;
}

 if (options>3) { //I loop the option to 0 
  options=0;
}
 if(timeCounter-timeOfEvent>=interval) {
  options=0;
}

So what is this doing? I hit a button, and this presents me with several different menus, on LCD screen. So far so good. If one hit the button several times, it loops around the options, resulting in the default screen on case 0. Finally I check the time, and if interval gets passed the code return to the default case 0. So when one hit the options button, and do nothing for "interval" amount of time, the screen gets back to its default state. That works, and it looks so cool. But I have a glitch (again :)). I need to start counting again every time when one hit any button, to increment the time out. The way I do it, is to update timeOfEvent every time when someone hit some of the buttons. Thus I put timeOfEvent=millis(); on any if occasion where listening for a button push. It seems to work, but on one occasion, I am listening for another button to be pushed (in a function, lets say Menu3();. The glitch is that when I hit this button, the program immediately switch to case0, and I have no idea why. When I print timeOfEvent on this occasion it looks how it should look, and I can not understand what cause case0; Any ideas?

Here is the actual menu3:

 void celFarSwitch() {
  SpecialEvent=true;
  LCD.setCursor (0,0);
  LCD.print (F("Cel./F. switch "));
  LCD.setCursor (0,1);
  if (celsius==true) {
    LCD.print (F("Celsius  <  >   "));
  }
  else {
    LCD.print (F("Farenhaind <  > "));
  }
  if (digitalRead(button2Pin)== HIGH) {
   timeOfEvent = millis();
   celsius=!celsius;
   delay(200);
 }
}

It did work when I get the time of event from the time counter, and not directly from millis();

Do you have pulldown resistors (10k) from GND to A1, A2, A3?

Tx, that is a good question. Short answer is no. I have resistors. First one is like 1 mOHM, and they degrade to one kOHM, and 220 Ohm. Or something similar. I saw that on a tutorial, and planned to discuss it with someone, how to calculate what resistors are needed, and when, but never got the chance to do it. So as any novice just followed the tutorial.

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