Arduino if, else if and else, on three lamps and a button
Or see every lesson.
- 455parts on the bench
- 43boards running now
- 1.00xreal time, on every board
if (condition) { ... } else { ... } runs the first block when the condition is true and the second block when it is false. Add else if for more choices. The chain is checked from the top, the first condition that is true wins, and every branch below it is skipped, so exactly one block runs.
The circuit above is an Uno with three lamps and a button on pin 2. Press Run. The red lamp and the yellow lamp take turns, one second each, and the serial monitor prints "branch: even second" and "branch: odd second". Hold the button and the green lamp lights instead, with "branch: pressed". One if, one else if and one else decide which.
Below is how the chain reads, how to write conditions, and the five mistakes that make an if do the wrong thing without an error, each run on an Uno with what it printed.
Want the step-by-step version? The lesson "One branch runs" walks through this with checkpoints.
Open the lessonHow the chain reads
Here is the decision in the sketch running above. pressed is true while the button is held, and seconds % 2 == 0 is true in every even second. The chain asks about the button first, so while you hold it the second does not matter: the first branch runs and the other two are skipped. Let go and the chain falls through to the clock.
Swap the first two branches and press Run again. Now the even seconds win even while you hold the button, and the green lamp only lights in odd seconds. Nothing else changed. The order of an if chain is part of what it means.
A press can print "branch: pressed" more than once. That is not the if; it is the button. Its contacts bounce for a few milliseconds and the chain sees every bounce. The button debounce page shows the fix.
bool pressed = digitalRead(BUTTON_PIN) == LOW;
unsigned long seconds = millis() / 1000;
int branch;
if (pressed) {
branch = 2;
} else if (seconds % 2 == 0) {
branch = 0;
} else {
branch = 1;
}Writing a condition
A condition compares two things. == is equal to, != is not equal, and <, >, <= and >= are what they look like. Join two with && (and) or || (or), and turn one around with ! (not). The sketch below sorts three temperatures with one chain and printed "hot", "warm" and "cold".
An else is optional. An if on its own runs its block or skips it. An else if is only reached when everything above it was false, which is why the second test below can say t > 20 and still mean "over 20 but not over 30".
void setup() {
Serial.begin(9600);
int temps[] = {35, 25, 10};
for (int i = 0; i < 3; i++) {
int t = temps[i];
if (t > 30) {
Serial.println("hot");
} else if (t > 20) {
Serial.println("warm");
} else {
Serial.println("cold");
}
}
}
void loop() {
}The biggest test goes first
Turn that chain upside down and it breaks. With if (t > 20) first and else if (t > 30) second, a temperature of 35 printed "warm". 35 is over 20, so the first branch won, and the hot branch can never run: anything over 30 is also over 20. When the tests overlap, put the narrowest one at the top.
One = where you meant two
One equals sign sets a variable; two compare. if (x = 0) does not ask whether x is 0. It sets x to 0, and then tests the 0, which is false. With x at 5, the sketch below printed "not zero" and then 0, because the if had changed it.
It builds, so it is easy to miss. Mokxi’s clang warns: using the result of an assignment as a condition without parentheses. The Arduino IDE’s GCC says suggest parentheses around assignment used as truth value, and only if warnings are switched on in its preferences. Read the warnings in the build tab; this one is always a bug.
void setup() {
Serial.begin(9600);
int x = 5;
if (x = 0) {
Serial.println("zero");
} else {
Serial.println("not zero");
}
Serial.println(x);
}
void loop() {
}Conditions that do not mean what they say
if (x == 1 || 2) reads like "if x is 1 or 2", but the compiler reads it as "x is 1, or 2", and 2 on its own is true. With x at 3 it printed "one or two". Write the variable out twice: if (x == 1 || x == 2).
if (5 < y < 10) is the same kind of trap. The compiler works out 5 < y first, which is true or false, so 1 or 0, and both are less than 10. With y at 20 it printed "between". Clang warned: result of comparison of constant 10 with expression of type 'bool' is always true. The way to say it is if (y > 5 && y < 10), which stayed quiet for 20.
Braces, and the semicolon that lies
Without braces, an if controls the one statement after it and nothing more, however the lines are indented. Below, x is 3, so "big" is skipped, and "very big" printed anyway, because it was never part of the if. Clang said so: misleading indentation; statement is not part of the previous 'if'. Always use braces and it cannot happen.
A semicolon straight after the condition is worse, because nothing warns. if (x > 10); is a whole if statement with an empty body. The block in braces on the next line is just a block, and it always runs: with x at 3, it printed "big". And a semicolon after the closing brace, }; before else, cuts the else off from its if, so the build stops. Clang says expected expression, pointing at the else; GCC says 'else' without a previous 'if'.
void setup() {
Serial.begin(9600);
int x = 3;
if (x > 10)
Serial.println("big");
Serial.println("very big");
}
void loop() {
}true, false and the ? shortcut
Any number works as a condition: 0 is false and everything else is true. So if (n) with n at 0 printed "n is false", and a bool reads naturally as if (ready) or if (!ready).
For a choice between two values there is a one-line form. score >= 50 ? "pass" : "fail" is "pass" when the test is true and "fail" when it is not; with a score of 72 it printed "pass". The sketch running above uses it to light each lamp: branch == 0 ? HIGH : LOW.
When one variable is checked against a list of fixed values, a mode number or a letter, a switch says it more neatly than a long else if chain. The switch case page has it on a light show.
Questions
What is the difference between if and else if in Arduino?
An if starts a chain and is always checked. An else if is only checked when every test above it in the same chain was false, so at most one block of the chain runs. A second plain if starts a new chain and is checked as well.
Why does my Arduino if statement always run?
Usually a semicolon straight after the condition, as in if (x > 10); which ends the if there and leaves the block below it to run every time. Also check for one = where you meant ==, and for conditions such as x == 1 || 2, which is always true.
How do I check two conditions in one if?
Join them with && for and, or || for or: if (t > 20 && t < 30). Write each comparison in full; if (5 < t < 10) does not mean "between".
Do I need braces after an if?
Only for more than one statement, but use them every time. Without braces the if controls only the next statement, and a second line that looks indented under it runs whatever the condition says.
Should I use if else or switch case?
Use if for ranges, several variables, or anything that is not a whole number. Use switch when one whole number or letter is compared with a list of fixed values, such as a mode or a menu choice.
Can I write an if else on one line?
For a choice between two values, yes: `score >= 50 ? "pass" : "fail"` is the whole if and else, and with a score of 72 it printed "pass". For anything more than picking a value, write the if and the else out in full, with braces.
Keep going
Where the facts on this page come from
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.