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?