Hi, I've a very long code, which is basically an alarm clock with LCD and 4 buttons. My first button is NextMenu button which changes value of a variable(int) named Menu.
My main loop is below, it just jumps to different ISR depending on Menu value.
void loop() {
if(Menu==1) DisplayTime();
if(Menu==2) DisplayTemperature();
if(Menu==3) DisplayAlarmTime();
if(Menu==4) CurtainOpenTime();
if(Menu==5) CurtainCloseTime();
}
Inside ISRs, I use millis function to turn of backlight after 15s and jump to "Display Time" interrupt after 30 seconds if no buttons are pressed.
if(millis()-currentMillis>=15000)
{
lcd.noBacklight();
}
if(millis()-currentMillis>=30000)
{
Menu=1;
lcd.clear();
DisplayTime();
}
Lets say I'm inside "DisplayAlarmTime" interrupt by clicking menu button 2 times. When 30 seconds pass without any button click, below code works and jumps back to "DisplayTime" ISR. I also change Menu value to 1 so that when I click menu button one more time, it will increase to 2, and it will jump to "DisplayTemperature".
However it wont work as I expected. In "DisplayAlarmTime" ISR, 30 seconds pass without button click, it jumps to "DisplayTime" ISR as expected and Menu value is changed to 1. After that if I click Menu button, it does not jump to second menu which is "DisplayTemperature" but it jumps where it was before.
How can I make arduino to forget last position and dont jump back to previous position?
Attached you can find whole code, however it is too long and not perfected yet, still in test phase, however works as expected except above problem.
Irrigation_and_Curtain_System.ino (11.9 KB)
How can I make arduino to forget last position and dont jump back to previous position?
Basically as I understand it you can't if you program it in C.
When an interrupt occurs the state of the machine is pushed onto a stack. If you can get at that stack then you can remove the return address as well as any saved machine state and replace it with the memory address of where you want to return to. I have done this on other processors like the MC6802 and the Z80 but not while programming it in a high level language only in machine code.
I don't see any ISRs in the code that you posted. What I see are calls to functions.
I am on a mobile so cannot open the attachment. Are you actually using interrupts ?
You are causing yourself a problem by calling the DisplayTIme() function from within another function, that will always return you to the place that DisplayTIme() was called from. When you reach the 30 second timeout, instead of calling DisplayTime(), break out of the while() loop and go back to loop().
Something to the effect of this:
void DisplayTemperature() { //Menu=2
currentMillis = millis();
menu_timeout = false; // menu_timeout is declared as a bool global variable
while ((menu_timeout == false ) && (digitalRead(NextMenu) == HIGH)) { //Run this loop while Next Menu button is not pressed
float h = dht.readHumidity();
float t = dht.readTemperature();
float hic = dht.computeHeatIndex(t, h, false);
if (millis() - currentMillis >= 15000) {
lcd.noBacklight();
}
if (digitalRead(Plus) == LOW || digitalRead(Minus) == LOW || digitalRead(Set) == LOW) {
lcd.backlight();
currentMillis = millis();
}
lcd.home();
lcd.write(1);
lcd.print(t);
lcd.write(223); //° Character for Celcius
lcd.print("C");
lcd.print(" ");
lcd.write(2);
lcd.print(h);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("Felt:");
lcd.print(hic);
lcd.write(223); //° Character for Celcius
lcd.print("C");
if (millis() - currentMillis >= 30000) {
Menu = 1;
lcd.clear();
//DisplayTime();
menu_timeout = true; //this will cause you to leave the while loop
}
}
if (menu_timeout == false) { //execute only if NEXTMENU was pressed
Menu = 3;
lcd.backlight();
delay(200);
lcd.clear();
}
}