I had a logger project which shown the temperature value on OLED (page 1), and if press any button, then go to setting page (page 2). ( I want to stay at page 2 ,until i exit the setting page...)
the problem facing is :
1.after pressing button, screen go to setting page( page2 ), then back to temperature page ( page 1) instantly
I want the temperature update rate is 3 second, so I put the delay (3000) in loop ,
however, it will also slow down the other function in loop, how to improve?
Many thanks.
void loop() {
if ((!digitalRead(downButton)) || (!digitalRead(upButton)) || !digitalRead(selectButton)) {
buttonaction(); // press any button, then go to setting page
} else {
sensorpage(); // if no button pressed , go to sensorpage
}
}
void buttonaction() { //function that control menu
if (!digitalRead(downButton)) {
updateMenu();
menu++;
delay(100);
updateMenu();
delay(100);
while (!digitalRead(downButton));
}
if (!digitalRead(upButton)) {
menu--;
delay(100);
updateMenu();
delay(100);
while (!digitalRead(upButton));
}
if (!digitalRead(selectButton)) {
executeAction();
delay(100);
updateMenu();
delay(100);
while (!digitalRead(selectButton));
}
}
void sensorpage() //drawing sensor page on OLED
{
display.clearDisplay();
display.setFont(&FreeSans9pt7b);
display.drawLine ( 0, 20, 128, 20, WHITE);
// RTC on top
/* DateTime now = rtc.now();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0, 0);
display.print(now.day(), DEC);
display.print("/");
display.print(now.month(), DEC);
display.print("/");
display.print(now.year(), DEC);
display.setCursor(0, 10);
display.print(now.hour(), DEC);
display.print(":");
display.print(now.minute(), DEC);
display.print(":");
display.print(now.second(), DEC);*/
// DIsplay temp at bottom
int x1 = 45;
int x2 = 105;
int y1 = 40;
int y2 = 60;
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, y1);
display.print("T1:");
display.setTextSize(1);
display.setCursor(x1, y1);
display.print(thermocouple.readCelsius());
display.setCursor(x2, y1);
display.cp437(true);
display.write(167);
display.print("C");
display.setCursor(0, y2);
display.print("T2:");
display.setCursor(x1, y2);
// display.print(rtc.getTemperature());
display.setCursor(x2, y2);
display.cp437(true);
display.write(167);
display.print("C");
display.display();
}
void updateMenu() //function that control menu action
{
display.setFont(&FreeSans9pt7b);
display.setTextSize(1);
switch (menu) {
case -3:
menu = 0;
break;
case -2:
display.clearDisplay() ;
display.display();
case -1:
menu = 0;
break;
case 0:
sensorpage();
break;
case 1:
display.clearDisplay();
display.setTextColor(WHITE);
display.setCursor(0, y);
display.println("> Start Logging");
display.setCursor(0, y2);
display.println(" MenuItem2");
display.display();
break;
case 2:
display.clearDisplay();
display.setTextColor(WHITE);
display.setCursor(0, y);
display.println("Start Logging");
display.setCursor(0, y2);
display.println("> MenuItem2");
display.display();
break;
case 3:
display.clearDisplay();
display.setTextColor(WHITE);
display.setCursor(0, y);
display.println("> Display off");
display.setCursor(0, y2);
display.println(" Back");
display.display();
break;
case 4:
display.clearDisplay();
display.setTextColor(WHITE);
display.setCursor(0, y);
display.println("Display off");
display.setCursor(0, y2);
display.println("> Back");
display.display();
break;
case 5:
menu = 4;
break;
}
}
Take a look at the State Change Detection example in the IDE (File->examples->02.digital->State Change Detection) to see how to detect when a button gets pressed, not if a button is pressed.
Then, set a state variable (e.g. state or inSettingsState) and then use that variable inside loop() to determine which state you are in and act accordingly... Something like this (not real code)
...
bool inSettingsState = false;
void loop() {
if ( checkButtons() ) {
inSettingsState = !inSettingsState;
}
if ( inSettingsState == true ) {
// do Settings things
}
else {
// do regular things
}
}
...
Sometimes, it is also useful to distinguish between the first time to a menu (redraw everything) vs. returning to the same menu (only update what is needed). This is the approach of a finite state machine (google it, if interested) and then you get something more like
...
bool inSettingsState = false;
void loop() {
if ( checkButtons() ) {
inSettingsState = !inSettingsState;
if ( inSettingsState == true ) {
beginSettingsMenu();
}
else {
beginRunMenu();
}
}
if ( inSettingsState == true ) {
// do Settings things
updateSettingsMenu();
}
else {
// do regular things
updateRunMenu();
}
}
...
after reviewing the state change example, i still cant slove 1, 2 problem.
`
void loop() {
BlynkEdgent.run ();
timer.run();
buttonState3 = digitalRead (selectButton);
if ( buttonState3 != lastbuttonState3) { //button press> state change , go setting page
if (buttonState3 == HIGH) {
menu = 1 ;
updateMenu(); // go to setting page
}
} else {
sensorpage(); // need help.... after pressing select button, setting page
// shown 1 second then go to next function...
}
lastbuttonState3 = buttonState3;`
After pressing the select button , setting page shown for one second, then go to next function sensorpage() ,
how to stop looping for a while after entering setting page ?
Your logic appears off as well as what you are defining as a button press. Inside loop(), you read selectButton and then act upon it if it is HIGH. This demands there is an external pull-down resistor tied to that pin. Is the resistor present?
Then, inside buttonaction(), you test for selectButton being LOW
if (!digitalRead(selectButton)) {
in order to do the executeaction() function.
So, follow the logic of the code.
you press the selectButton, the state is not equal to the last state so you call buttonaction(). That function executes once and returns.
you update lastbuttonState3
you execute loop() again.
buttonState3 is now equal to lastbuttonState3 so the else part gets executed which is sensorpage()
First off, how are your buttons wired up? This will dictate if they are HIGH or LOW when pressed. A typical schematic is one side of the button to ground and the other to the input pin with the pin declared as INPUT_PULLUP. It will read LOW when pressed.
Second, your buttonaction() function doesn't do anything if no buttons are pressed. They way you check buttons within the function needs to be the same state change detection example.
An alternative would be to use the Bounce2 library where you can define a button pin and it does all the state change and debouncing inside that library. It will make your life simplier.
Third, as I stated in reply #4, you need to keep track of what state your are in and then call the correct functions.