A global variable behave like local variable (Solved)

Hello all arduino lovers!

A lot of time I can't solve one problem. The all code works as I want except incrementing and decrementing of global variable named "waiting". The double pushing of button should decrement the variable and triple pushing of button should increment the variable. But this global variable behave like local variable. It starts from initial meaning equal 2 every pushing of button. Thus double pushing of button decrement it to 1. Next double pushing of button makes the same result. Similar situation with triple pushing. Every triple pushing of button makes "waiting" variable equal 3.

Whole code and output of com port in attachment.

Here the piece of code that I meant:

if (butt1.isDouble()) {
    if (setLev == 1) {
      print(F("waiting before = "), &waiting);
      --waiting;
      print(F("waiting after = "), &waiting);
      Serial.println(F("hold the button to save waiting variable"));
      if (waiting <= 0) waiting = 1;  // guard from assigning variable 0 value
    }
  }

  if (butt1.isTriple()) {
    if (setLev == 1) {
      print(F("waiting before = "), &waiting);
      ++waiting;
      print(F("waiting after = "), &waiting);       // Triple click check. If true it raises of current value.
      if (waiting > 5) waiting = 5;  // guard from assigning variable big value
      Serial.println(F("hold the button to save waiting variable"));
    }
  }

Here the piece of output of com port:

...
23:13:57.311 -> printF waiting before = 2
23:13:57.311 -> printF waiting after = 3
23:13:57.349 -> hold the button to save waiting variable
23:14:00.013 -> printF waiting before = 2
23:14:00.013 -> printF waiting after = 3
23:14:00.013 -> hold the button to save waiting variable
23:14:03.795 -> printF waiting before = 2
23:14:03.795 -> printF waiting after = 1
23:14:03.830 -> hold the button to save waiting variable
23:14:09.580 -> printF waiting before = 2
23:14:09.580 -> printF waiting after = 1
23:14:09.619 -> hold the button to save waiting variable
...

Please help me to solve this problem.

Com3_output.txt (1.61 KB)

temporary.ino (4.19 KB)

Where did you get the GyverButton library from and which Arduino board are you running this on ?

For the convenience of others here is the complete program

OP please note !

/*
  The variant for tests.
  Author Roman Shentsev.

*/

#include <GyverButton.h>
#include <EEPROM.h>

#define BUTTPIN 3        // key is connected here (PIN --- key --- GND).
#define PUMP1PIN 4        //
#define PUMP2PIN 5        //
#define SETLEV_AMOUNT 14
#define WORKLEV_AMOUNT 7

GButton butt1(BUTTPIN, HIGH_PULL, NORM_OPEN);

byte waiting;
boolean LEDflag = true;  // flag of LED state.
int setLev;
int workLev = 0;
unsigned long timeCounter, standard, waitTimer; // variables for saving of current millis() value  // workTimer, pauseTimer;
byte switchCounter = 0;

template<typename t1, typename t2>
void print(const t1 *varName, t2 *var)
{
  Serial.print(F("printF "));
  Serial.print(varName);
  Serial.println(*var);
}

template<typename t1, typename t2>
void nextLev(const t1 *varName, t2 *var)
{
  Serial.print(F("nextLevF "));
  if (*var == setLev)
  {
    ++(*var);
    print(varName, var);
    if (*var > SETLEV_AMOUNT) *var = 0;
  }
  else
  {
    ++(*var);
    print(varName, var);
    if (*var > WORKLEV_AMOUNT) *var = 0;
  }
}

void setup()
{
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);  // LED
  pinMode(PUMP1PIN, OUTPUT); // pump 1
  pinMode(PUMP2PIN, OUTPUT); // pump 2
  timeCounter = millis();
  butt1.setTickMode(AUTO);
  butt1.setDebounce(80);      // settings of anti debounce (default 80 мс)
  butt1.setTimeout(1000);      // settings of holding timeout (default 500 мс)
  butt1.setClickTimeout(600);   // settings of timeout between clicks (default 300 мс)
  if (EEPROM[0] == 255 || EEPROM.get(0, setLev) != SETLEV_AMOUNT)
  {
    setLev = 0;
    EEPROM.update(0, setLev);
    print(F("EEPROM.get(0, setLev) = "), &setLev);
    waiting = 2;
    EEPROM.update(2, waiting);
    print(F("EEPROM.get(2, waiting) = "), &waiting);
  }
}

void loop()
{
  if (butt1.isHolded())
  {
    if (setLev == 1)
    {
      EEPROM.update(2, waiting);
      ++setLev;
      print(F("Holded; setLev = "), &setLev);
    }
    else if (setLev == 0)
    {
      ++setLev;
      print(F("Holded; setLev = "), &setLev);
    }
  }
  if (setLev > 0 && setLev < 8)
  {
    if (switchCounter < EEPROM.get(2, waiting))
    {
      if (millis() - timeCounter >= 250)
      {
        digitalWrite(LED_BUILTIN, LEDflag); // turn on or turn off LED
        timeCounter = millis();  // assigning the last millis() value
        if (!LEDflag) ++switchCounter;
        LEDflag = !LEDflag;  // inverting of flag
      }
    }
    else if (millis() - timeCounter >= 1000)
    {
      switchCounter = 0;
    }
  }
  if (butt1.isDouble())
  {
    if (setLev == 1)
    {
      print(F("waiting before = "), &waiting);
      --waiting;
      print(F("waiting after = "), &waiting);
      Serial.println(F("hold the button to save waiting variable"));
      if (waiting <= 0) waiting = 1;  // guard from assigning variable 0 value
    }
  }
  if (butt1.isTriple())
  {
    if (setLev == 1)
    {
      print(F("waiting before = "), &waiting);
      ++waiting;
      print(F("waiting after = "), &waiting);       // Triple click check. If true it raises of current value.
      if (waiting > 5) waiting = 5;  // guard from assigning variable big value
      Serial.println(F("hold the button to save waiting variable"));
    }
  }
  if (butt1.isClick())
  {
    if (setLev > 1)
    {
      nextLev(F("Click. setLev = "), &setLev);
    }
  }
  switch (setLev)
  {
    case 3:
      Serial.println(F("case 3"));
      nextLev(F("Case is over. setLev = "), &setLev);
      break;
    case 5:
      Serial.println(F("case 5"));
      nextLev(F("Case is over. setLev = "), &setLev);
      break;
    case 7:
      Serial.println(F("case 7"));
      nextLev(F("Case is over. setLev = "), &setLev);
      break;
    case 9:
      Serial.println(F("case 9"));
      nextLev(F("Case is over. setLev = "), &setLev);
      break;
    case 11:
      Serial.println(F("case 11"));
      nextLev(F("Case is over. setLev = "), &setLev);
      break;
    case 13:
      Serial.println(F("case 13"));
      nextLev(F("Case is over. setLev = "), &setLev);
      break;
    case 14:
      Serial.println(F("case 9"));
      nextLev(F("Case is over. setLev = "), &setLev);
      break;
  }
}

It looks like you only update the EEPROM copy of 'waiting' when (butt1.isHolded()) and (setLev == 1).

If 'setLev' is between 1 and 7 you read 'waiting' from EEPROM. That is why it keeps going back to 2.

The code is so hard to follow I'm not sure what it is supposed to do. I would suggest removing functionality and debugging it in stages.

I observe that waiting only gets saved to EEPROM if setLev == 1. However, I also observe that in the following code segment if setLev is 1-7 then the waiting value will be read from EEPROM in order to evaluate the conditional. I suspect that is where it is getting reset.

 if (setLev > 0 && setLev < 8) {
    if (switchCounter < EEPROM.get(2, waiting)) {
      if (millis() - timeCounter >= 250) {
        digitalWrite(LED_BUILTIN, LEDflag); // turn on or turn off LED
        timeCounter = millis();  // assigning the last millis() value
        if (!LEDflag) ++switchCounter;
        LEDflag = !LEDflag;  // inverting of flag
      }
    }
    else if (millis() - timeCounter >= 1000) {
      switchCounter = 0;
    }
  }

UKHeliBob:
Where did you get the GyverButton library from and which Arduino board are you running this on ?

The GyverButton library I took here: GyverLibs/GyverButton at master · AlexGyver/GyverLibs · GitHub

I use Arduino Nano. Moreover I checked code on two different Arduino Nano boards.

UKHeliBob:
OP please note !

Sorry, I didn't understand it. What do you mean?

Sorry, I didn't understand it. What do you mean?

I mean that I posted your whole program, as you should have done, instead of just a snippet of it.

UKHeliBob:
I mean that I posted your whole program, as you should have done, instead of just a snippet of it.

Thank you!

johnwasser:
It looks like you only update the EEPROM copy of 'waiting' when (butt1.isHolded()) and (setLev == 1).

If 'setLev' is between 1 and 7 you read 'waiting' from EEPROM. That is why it keeps going back to 2.

You absolutely right! I changed statement:

if (switchCounter < EEPROM.get(2, waiting))

to this:

if (switchCounter < waiting)

Now code works properly. Thank you so much!

ToddL1962:
The code is so hard to follow I'm not sure what it is supposed to do. I would suggest removing functionality and debugging it in stages.

I observe that waiting only gets saved to EEPROM if setLev == 1. However, I also observe that in the following code segment if setLev is 1-7 then the waiting value will be read from EEPROM in order to evaluate the conditional. I suspect that is where it is getting reset.

 if (setLev > 0 && setLev < 8) {

if (switchCounter < EEPROM.get(2, waiting)) {
     if (millis() - timeCounter >= 250) {
       digitalWrite(LED_BUILTIN, LEDflag); // turn on or turn off LED
       timeCounter = millis();  // assigning the last millis() value
       if (!LEDflag) ++switchCounter;
       LEDflag = !LEDflag;  // inverting of flag
     }
   }
   else if (millis() - timeCounter >= 1000) {
     switchCounter = 0;
   }
 }

Thank you so much!

DigFor:
Thank you so much!

Glad it worked out for you!