Hey, I'm doing some fairly simple button prototyping on a bread board, but im really struggling to get my head around the logic of this problem I have.
I have two switches, call them ButtonUp and ButtonDown, each connected to the Arduino between ground and the built in pullup resistor. I then have two output pins connected to two LEDs, Call them Up and Down.
What I am trying to do is:
-Have Down set to HIGH when neither buttons are pressed
-Have Up and Down set to HIGH when ButtonUp is pressed
-Have Up set HIGH and Down set LOW when ButtonDown is pressed
I have it all working so far, but I am only getting 3v from the Up LED when ButtonDown is pressed. I believe this is due to two IF statements that are conflicting, as I have tried removing them and each in turn and I get the full 5v when tested.
My problem is I cannot work out the logic to separate these two IF statements or combine the statements to overcome this problem.
Code Below:
int DownButton = 3;
int UpButton = 4;
int MotorUp = 5;
int MotorDown = 2;
void setup() {
pinMode(DownButton, INPUT_PULLUP);
pinMode(UpButton, INPUT_PULLUP);
pinMode(MotorUp, OUTPUT);
pinMode(MotorDown, OUTPUT);
}
void loop() {
int Up = digitalRead(UpButton);
int Down = digitalRead(DownButton);
if (Up == LOW) digitalWrite(MotorUp, HIGH);
else digitalWrite(MotorUp, LOW);
if (Down == LOW) {
digitalWrite(MotorDown, LOW);
digitalWrite(MotorUp, HIGH);
}
else {digitalWrite(MotorDown, HIGH);
}
}
Have you looked at state machines, switch case and enums for getting very readable code that will do this. Also look at button code with debouncing unless you want to hold the button down
Your two buttons are independent of each other. So when Down is pressed (low) and you make the down led high, Up is not pressed (high) so you're making the down led low. It's zooming around loop() so fast, that the led is blinking way faster than you can see, and not recovering between each change, so it's just appearing as partly on.
I'd draw up a truth table of the possibilities available between the 2 buttons (lo/lo, lo/hi, hi/lo and hi/hi) and then and them together and explicitly set the 2 outputs as you need them in each of the 4 possibilities.
You can’t do an else unless you mean “in all other circumstances” which you dont. Decide on the states eg waiting, up and down. Set a variable to hold the states eg int state =0. If buttonup pressed then state = 1. If state == 1 run your up function
Etc
Or do switch case
Case 1 waiting
Case 2 up
Case 3 down
Consider enum
Eg enum waiting = 0 etc
All code pseudo code
Understand the loop. This is the fundamental concept in arduino. It goes round and round really fast and will do what your code says again and again. The way to keep in one state is to use a state machine, remember from one loop to another what state you are in and only run the code relating to this state
You can also use enum to make the button logic seem better eg enum on = LOW. Then you just write in your code if button on etc
Thanks for the suggestion, I don't have any experience with state machines or switch cases but they look like they could be useful in this case so Ill gave a read and try to get something together, thanks !
Here is a version which defines the logic as you have actually stated it. The only difference is that it only changes the outputs if the inputs changed. I assumed both buttons pressed is "undefined" but you can change that easily if you like.
const int DownButton = 3;
const int UpButton = 4;
const int MotorUp = 5;
const int MotorDown = 2;
void setup()
{
pinMode(DownButton, INPUT_PULLUP);
pinMode(UpButton, INPUT_PULLUP);
pinMode(MotorUp, OUTPUT);
pinMode(MotorDown, OUTPUT);
}
void loop()
{
const int lastUp = LOW;
const int lastDown = LOW;
int Up = digitalRead(UpButton);
int Down = digitalRead(DownButton);
if (Up != lastUp || Down != lastDown)
{
lastUp = Up;
lastDown = Down;
if (Up == HIGH && Down == HIGH ) // neither button pressed
{
digitalWrite(MotorDown, HIGH);
digitalWrite(MotorUp, LOW);
}
else if (Up == LOW && Down == HIGH) // UpButton pressed
{
digitalWrite(MotorDown, HIGH);
digitalWrite(MotorUp, HIGH);
}
else if (Up == HIGH && Down == LOW) // DownButton pressed
{
digitalWrite(MotorDown, LOW);
digitalWrite(MotorUp, HIGH);
}
else // Both buttons pressed
{
// undefined, no effect
}
}
}
Hey, this worked right away! thanks. Ill go through it to understand myself else it'll feel like cheating, but it certainly seems easier than switch cases.
If you just leave them as int then they get created and initialized to LOW every time through loop() defeating the purpose of tracking the last read value of the UpButton and DownButton inputs. In other words the "lifetime" of variables declared in a function without the static keyword is for the duration of the function execution. The "lifetime" of a variable declared in a function with the static keyword is for the duration of the program. Therefore, when loop() is entered again lastUp and lastDown actually contain the values that were read from the UpButton and DownButton inputs the last time the loop() function was executed.