Trying to convert offline code for setting a timer to cloud ompatible code

Hello everyone,

I have a working hobby project for a vivarium and I'm trying to make it work with the Arduino IoT so I can run the project on a Giga R1 and expand it. From what I've understood using delay() or any code that makes everything wait till it it finished is bad. So far I've gotten away with delay(50) and 100 to smooth out control with the joystick.
However the original project uses a while() { } structure and I want to find an alternative way to process my input. The existing code works by displaying a value stored in eeprom memory, allowing the value to be changed by joystick and then storing the new value to eeprom. I won't post the whole code (unless requested) but I think this is the relevant bit:

void setRain1Timer() {
  int rainHr = 0;
  int rainMin = 0;
  int rainTime = 0;
  myScreen.fillScreen(BLACK);
  myScreen.setCursor(0, 0);
  myScreen.print("Rain Time 1:");
  myScreen.setCursor(0, 20);
  myScreen.print("ENTER ON TIME");
  myScreen.setCursor(10, 30);
  myScreen.print("00:00");
  myScreen.setCursor(10, 40);
  myScreen.print(" ^");
  int inputGiven = 0;
  while (inputGiven < 4) {
    switch (inputGiven) {
      case 0:
        if (getInput("", 10, 30, rainHr, 24) == true) {
          myScreen.setCursor(10, 40);
          myScreen.print("    ");
          myScreen.setCursor(28, 40);
          myScreen.print(" ^");
          inputGiven = 1;
        };
        break;
      case 1:
        if (getInput("", 28, 30, rainMin, 60) == true) {
          myScreen.setCursor(28, 40);
          myScreen.print("    ");
          inputGiven = 2;
        };
        break;
      case 2:
        if (getInput("Duration: ", 10, 50, rainTime, 60) == true) {
          inputGiven = 3;
        };
        break;
      case 3:  // Write all data to EEPROM here
        EEPROM.write(4, rainHr);
        EEPROM.write(5, rainMin);
        EEPROM.write(6, rainTime);
        inputGiven = 4;
        break;
    }
  }
  // Read and print data from EEPROM here
  printData(rainHr, rainMin, rainTime);
}

boolean getInput(String txt, int x, int y, int& data, int maxValue) {
  static unsigned long lastPrint = 0;
  static unsigned long lastChange = 0;
  static int oldData = 0;
  static String oldText = "";
  boolean Up = joyButtonRead(pbUp);
  boolean Down = joyButtonRead(pbDown);
  boolean Right = joyButtonRead(pbRight);
  if (millis() - lastPrint > 200) {
    lastPrint = millis();
    if (oldData != data || oldText != txt) {
      myScreen.setTextColor(BLACK);
      myScreen.setCursor(x, y);
      myScreen.print(oldText);
      printDigits(oldData);
      oldData = data;
      oldText = txt;
    }
    myScreen.setTextColor(WHITE);
    myScreen.setCursor(x, y);
    myScreen.print(txt);
    printDigits(data);
  }
  if (millis() - lastChange > 200) {
    if (Up) {
      lastChange = millis();
      data++;
      if (data > maxValue) {
        data = 0;
      }
    }
    if (Down) {
      lastChange = millis();
      data--;
      if (data < 0) {
        data = maxValue - 1;
      }
    }
    if (Right) {
      lastChange = millis();
      return true;
    }
  }
  return false;
}

unsigned char joyButtonRead(unsigned char theButton) {

  unsigned char switchState = 0;
  //int joyReading;

  switch (theButton) {
    case pbRight:  // x right as button
      joyRead = analogRead(xPin);
      if (joyRead > highSwitchPoint) switchState = 1;  //1=HIGH 0=LOW
      else switchState = 0;
      break;

    case pbUp:  // y up as button
      joyRead = analogRead(yPin);
      if (joyRead < lowSwitchPoint) switchState = 1;
      else switchState = 0;
      break;

    case pbLeft:  // x left as button
      joyRead = analogRead(xPin);
      if (joyRead < lowSwitchPoint) switchState = 1;
      else switchState = 0;
      break;

    case pbDown:  // y down as button
      joyRead = analogRead(yPin);
      if (joyRead > highSwitchPoint) switchState = 1;
      else switchState = 0;
      break;
  }
  return switchState;
}

Now I'm trying to do the same thing, slightly different in form, but with the same purpose. Except for the Giga connected to the cloud.


  if (currPage == SUB_MENU3_ITEM1) { //================================SUB3 ITEM 1=============================================
    if (updateDisplay){      
      // print the items
      myScreen.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
      myScreen.setCursor(0, 30);
      printSelected(1, sub_Pos_Sub); myScreen.println(F("CHANGE ON TIME"));
      printSelected(2, sub_Pos_Sub); myScreen.println(F("CHANGE OFF TIME"));  

      myScreen.setCursor(10, 80);
      myScreen.print(F("START TIME SET"));
      myScreen.setCursor(10, 100);
      myScreen.print(F("AT:"));
      myScreen.setCursor(40, 100);
      printDigits(EEPROM.readByte(0));
      myScreen.print(":");
      printDigits(EEPROM.readByte(1));

      myScreen.setCursor(10, 120);
      myScreen.print("STOP TIME SET");
      myScreen.setCursor(10, 140);
      myScreen.print("AT:");
      myScreen.setCursor(40, 140);
      printDigits(EEPROM.readByte(2));
      myScreen.print(":");
      printDigits(EEPROM.readByte(3));    
      // clear the update flag
      updateDisplay = false;
    }  
        
    if (checkJoystick() == Down && down_was_down == true) { //move the pointer down
      if (sub_Pos_Sub == 1) {sub_Pos_Sub = 2;}
      updateDisplay = true;
      down_was_down = false;
    }
   
    if (checkJoystick() == Up && up_was_down == true) {  //move the pointer Up
      if (sub_Pos_Sub == 2) {sub_Pos_Sub = 1;} 
      updateDisplay = true;
      up_was_down = false;
    }

    if (sub_Pos_Sub == 1 && checkJoystick() == Right && right_was_down == true) { // change ON timer
      startChangeTime(0, 1, 40, 100);  // startChangeTime(int eepromHour, int eepromMinutes, int xPos, int yPos)
      bool right_was_down = false;
      Serial.println("startChangeTime ON timer");
    }
    
    if (sub_Pos_Sub == 2 && checkJoystick() == Right && right_was_down == true) { // change OFF timer
      startChangeTime(2, 3, 40, 140);  
      bool right_was_down = false;
      Serial.println("startChangeTime OFF timer");
    }
    
    //move back to the root menu
    if (checkJoystick() == Left && left_was_down == true) {
      currPage = SUB_MENU3;
      return;
    }

  }

void printSelected(uint8_t p1, uint8_t p2) {
  if (p1 == p2) { myScreen.print(F(" > ")); } 
  else { myScreen.print(F("   ")); }
}


void startChangeTime(int eepromHour, int eepromMinutes, int xPos, int yPos) { // xPos is starting location for Hour digits. xPos for minutes is shifted right

  bool right_was_down = false;

  if (checkJoystick() == Right) { right_was_down = true; delay(200); }

  int hourTime = EEPROM.readByte(eepromHour);
  int minuteTime = EEPROM.readByte(eepromMinutes);
  bool hourHasBeenSaved = false;
  bool minuteHasBeenSaved = false;

  if (!hourHasBeenSaved) {
    hourTime = changeTime(hourTime, 0, 23, xPos, yPos);

    if (checkJoystick() == Right && right_was_down == true) {
      EEPROM.writeByte(eepromHour, hourTime);
      hourHasBeenSaved = true;
      right_was_down = false;
    }
  }

  if (hourHasBeenSaved && !minuteHasBeenSaved) {
    minuteTime = changeTime(minuteTime, 0, 59, xPos +40, yPos); //+30 to shift from hour digits to minute digits

    if (checkJoystick() == Right && right_was_down == true) {
      EEPROM.writeByte(eepromMinutes, minuteTime);
      minuteHasBeenSaved = true;
      right_was_down = false;
    }
  }
  if (hourHasBeenSaved && minuteHasBeenSaved) {
    hourHasBeenSaved = false;
    minuteHasBeenSaved = false;
    return;
  }
}

int changeTime(int &timeValue, int minValue, int maxValue, int xPos, int yPos) { 
  
  bool down_was_down = false;
  bool up_was_down = false;

  if (checkJoystick() == Down) { down_was_down = true; delay(100); }
  if (checkJoystick() == Up) { up_was_down = true; delay(100); }
  
  myScreen.setTextColor(ST77XX_BLACK, ST77XX_WHITE); //invert the selected block

  if (checkJoystick() == Up && up_was_down == true) {
    timeValue++;
    myScreen.setCursor(xPos, yPos);
    printDigits(timeValue);
    if (timeValue > maxValue) {
      timeValue = minValue;
    }
    up_was_down = false;
    Serial.print("up");
  }
  if (checkJoystick() == Down && down_was_down == true) {
    timeValue--;
    myScreen.setCursor(xPos, yPos);
    printDigits(timeValue);
    if (timeValue < minValue) {
      timeValue = maxValue;
    }
    down_was_down = false;
    Serial.print("down");
  }  

  myScreen.setTextColor(ST77XX_WHITE, ST77XX_BLACK); //revert to normal

  return timeValue;
  
}

Moving the cursor up and down is fine, when in the coresponding position it will print ""startChangeTime ON/OFF timer" but seemingly the startChangeTime() function does nothing.

startChangeTime calls changeTime and when that registers up or down movement it should print the flags, but I'm not seeing them.

Since there is nothing to make everything wait untill startChangeTime() is finished, nothing will in fact wait for it to do something.

So the core of my question is: how can I make startChangeTime() run succesfully without blocking everything?

After googling around it seems my answer would lie somewhere with a state machine. I'll sleep on this and start fresh tomorrow.

1 Like

Alright, I am at the semi-functioning state. The current issue is I can enter the first state and exit/save it. When I get to the seconds state I can change values but I can not break the state. It's almost a perfect copy of the first state and I'm guessing my joystick boolean is not resetting properly. Up and down continue to function, but Right seems to do nothing. Can anyone spot what I'm not seeing?

void startChangeTime(int eepromHour, int eepromMinutes, int xPos, int yPos) { // xPos is starting location for Hour digits. xPos for minutes is shifted right

  bool right_was_down = false;

  if (checkJoystick() == Right) { right_was_down = true; delay(200); }

  int hourTime = EEPROM.readByte(eepromHour);
  int minuteTime = EEPROM.readByte(eepromMinutes);
  bool everythingHasBeenSaved = false;  
  ChangeTimeState state = CHANGING_HOUR;

  //if (!everythingHasBeenSaved) {
  while (!everythingHasBeenSaved) {
    switch (state) {
      case CHANGING_HOUR: 
        myScreen.setTextColor(ST77XX_BLACK, ST77XX_WHITE); //invert the selected block
        hourTime = changeTime(hourTime, 0, 23, xPos, yPos);

        if (checkJoystick() == Right && right_was_down == true) {
          EEPROM.writeByte(eepromHour, hourTime);
          Serial.println("hours saved");
          myScreen.setTextColor(ST77XX_WHITE, ST77XX_BLACK); //revert color to normal
          myScreen.setCursor(xPos, yPos);          
          printDigits(hourTime);
          right_was_down = false;
          state = CHANGING_MINUTE;
        }      
      break;

      case CHANGING_MINUTE: 
        myScreen.setTextColor(ST77XX_BLACK, ST77XX_WHITE); //invert the selected block
        minuteTime = changeTime(minuteTime, 0, 59, xPos +35, yPos); //+35 to shift from hour digits to minute digits
        
        if (checkJoystick() == Right && right_was_down == true) {
          EEPROM.writeByte(eepromMinutes, minuteTime);
          Serial.println("minutes saved");
          myScreen.setTextColor(ST77XX_WHITE, ST77XX_BLACK); //revert color to normal
          myScreen.setCursor(xPos +35, yPos);          
          printDigits(minuteTime);
          right_was_down = false;
          state = SAVING_COMPLETE;
        }
      break;      

      case SAVING_COMPLETE:      
        everythingHasBeenSaved = true;
        Serial.println("saving completed");
      break;
    }
  }
}

int changeTime(int &timeValue, int minValue, int maxValue, int xPos, int yPos) { 
  
  bool down_was_down = false;
  bool up_was_down = false;
  bool right_was_down = false;

  if (checkJoystick() == Down) { down_was_down = true; delay(100); }
  if (checkJoystick() == Up) { up_was_down = true; delay(100); } 
  if (checkJoystick() == Right) { right_was_down = true; delay(200); } 
  
  if (checkJoystick() == Up && up_was_down == true) {
    timeValue++;
    myScreen.setCursor(xPos, yPos);
    printDigits(timeValue);
    if (timeValue > maxValue) {
      timeValue = minValue;
    }
    up_was_down = false;
    Serial.print("up");
  }
  if (checkJoystick() == Down && down_was_down == true) {
    timeValue--;
    myScreen.setCursor(xPos, yPos);
    printDigits(timeValue);
    if (timeValue < minValue) {
      timeValue = maxValue;
    }
    down_was_down = false;
    Serial.print("down");
  }  

  return timeValue;
  
}

edit: Also, I'm still relying on a while loop. When I take to long to enter the values (ie can't/don't exit the loop) The Arduino will crash and reboot. At eralyer stages the if() alternative also wasn't working. I'm hoping it will when I get it all together.

I found a solution by putting

if (checkJoystick() == Right) { right_was_down = true; delay(200); }

into each case. A problem with scope?

So I have something that sort of works, but still might crash the whole thing.

Any tips on sorting that out would be greatly appreaciated!

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