Trying to use ezButton to cycle between values

So I've been working on a closed-loop height control system for my car that uses stepper motors to change the lengths of the lever arms the factory system uses as height sensors. I'm using one motor and one potentiometer (as a height sensor) per wheel. I've built a testing configuration for one wheel and all of it has been working, but I ran into a problem trying to cycle between two target height values with a button. From an initial 0 value, I want the "target" to switch between the high and low targets when the button is pressed (the value is read from the potentiometer position sensor), and the initial button press works as intended to set "target" to the high value, but will not switch after that. I've copied my code below (sorry if the formatting sucks I've never posted here before). If anybody has suggestions for how to fix this (or do it better lol) I would love some input!

#include <ezButton.h>

const int buttonPin = 9;
const int LED = 13;
const int lowTarget = 625;
const int highTarget = 775;

ezButton button(buttonPin);
int ledState = LOW;

void setup() {
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  button.setDebounceTime(100);
}

void loop() {
  button.loop();
  int target = 0;

  //rotate target value
  if (button.isPressed())
  {
    if(target == 0)
    {
      Serial.println("button pressed, target -> high (initial)");
      ledState = !ledState;
      digitalWrite(LED, ledState);
      target = highTarget;
      Serial.println(target);
      delay(1);
    }
    
    else if(target == highTarget)
    {
      Serial.println("button pressed, target -> low");
      ledState = !ledState;
      digitalWrite(LED, ledState);
      target = lowTarget;
      Serial.println(target);
      delay(1);
    }
    
    else if(target == lowTarget)
    {
      Serial.println("button pressed, target -> high");
      ledState = !ledState;
      digitalWrite(LED, ledState);
      target = highTarget;    
      Serial.println(target);
      delay(1);
    }
  }
}

How is the button wired? It should be between GND and pin 9.

int target = 0; should be put outside loop() function. It should be a global variable.

The button is wired between pin 9 and GND. It prints to the serial monitor every time it is pressed, but it prints "button pressed, target -> high (initial)" over and over rather than cycling.

That fixed it! Thank you!
Why does it make a difference if the variable is global?

Firstly, please mark it as solution, so anther people can find it quickly.

Secondly, for your question, see Arduino variable scope

You have these sprinkled about your sketch. They serve no purpose, remove them. If you put them in there for some reason, visit that reasoning again.

If it was superstition, there is no place for that in programming!

Also, debounce of 100 ms is plenty very long, unless you have some very bad switches. Even my crappy arcade pushbuttons settle down in that time.

Your target variable was, as you learned, the problem. It would work as a global variable or a static local variable.

The article @IoT_hobbyist links doesn't appear to mention static variables, so after you absorb that material, search further for more complete information.

 C++ variable scope

should turn up some things.

The article also advises "avoid beginning variable names with numeral characters", which is just funny because... they are simply not allowed in C/C++ and would keep your code from compiling.

a7

Marked and noted, thank you for the concision!

ahh the delay(1); was in the example I was working off of for what they called "stability", I was just blindly following lol.

I read a little bit into static variables, from what I gathered they're mostly useful when previous states of the variable need to be stored... is there any benefit in using them if I just need the target variable to change values?

That is what making it global did for you, and here it is necessary to assure, one way or the other, that the value you carefully set remains unchanged.

The plain local declaration always set it back to zero.

    int target = 0;  // new loop pass, new variable, new value

For this to work

   else if (target == highTarget)… 

you need target to persist. Global or local static both do the trick; if target is not needed outside the function a local static declaration is preferred, as it will mean no possible use or collision with another variable with the same name.

In small sketches it makes little difference. In larger projects, everything that can be hidden should be considered for hiding, it makes reading, modifying and fixing things easier, and it makes breaking things harder.

a7

It definitely makes sense to minimize variable clashing, thanks for the explanation! When I start reworking the code to accommodate the other three wheels I will definitely need that safety net.

OK.

Just in case you haven't learned about arrays yet, any time someone hints that something accomplished once is now going to be triplicated or quadriplicated I am compelled to recommend…

...a step back from the project to look into array variables in C/C++.

Arrays are one of a handful of simple programming concepts that really help make code shorter and easier to maintain and enhance, if it is a little bit harder to write using arrays in the first place.

Guaranteed.

a7

hahaha yeah arrays are gonna be a life saver, I have lots of experience using arrays and dataframes in python for data manipulation so it'll just be a matter of translating between the languages.

Thank you for the tip!

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