Adventures in Science: Arduino Logic Operators

Building on our last Arduino programming episode, we look at creating compound conditional statements using logic operators.

Favorited Favorite 0

On this week’s “Adventures in Science,” we look at creating compound conditional statements. But in order to do that, we first cover the basics of Boolean logic (or Boolean algebra).

There are three main operators in Boolean algebra: NOT, AND, OR. From these, we can make any number of logic statements, but for now, we will only cover these three and exclusive OR. Boolean algebra follows its own set of rules, but the most important one to remember is that variables can only have one of two values: true or false. From there, we can show how the different operators work.

The first, and probably easiest, is the NOT or negation operator. It simply returns the opposite value of the variable it modifies (P, in this case).

P !P
False True
True False

The second is the AND operator, which is more formally known as logical conjunction. With it, both variables (P and Q) must be true for the result to be true.

P Q P && Q
False False False
False True False
True False False
True True True

Next, we have the OR operator (logical disjunction). We know this in English as “inclusive or,” which means that either P, Q or both can be true for the result to be true.

P Q P || Q
False False False
False True True
True False True
True True True

Finally, we have exclusive OR (exclusive disjunction), where only one of P or Q can be true for the result to be true. If both are true, the result is false. Exclusive OR is not considered a fundamental logic operator, as you can construct the operation from the other three:

P ⊕ Q = (P || Q) && !(P && Q)

One possible operator for exclusive OR is a plus enclosed in a circle, ⊕. There’s no Boolean operator for exclusive OR C, but it’s important enough in programming and electronics that I felt the need to introduce it.

P Q P ⊕ Q
False False False
False True True
True False True
True True False

Using logical operators, we can create compound conditional statements that make doing things like detecting a button push edge much easier:

const int btn_pin = 7;
const int led_pin = 13;

int btn_prev = HIGH;
int btn_state;

void setup() {
  pinMode(btn_pin, INPUT_PULLUP);
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, LOW);
}

void loop() {
  btn_state = digitalRead(btn_pin);
  if ( (btn_state == LOW) && (btn_prev == HIGH) ) {
    digitalWrite(led_pin, HIGH);
    delay(500);
    digitalWrite(led_pin, LOW);
  }
  btn_prev = btn_state;
}

Are there any other slick uses for Boolean operators and compound conditional statements that you can offer or would want a new programmer to know? Please share your ideas in the comments below.


Comments 10 comments

  • Nice write up, but I want to pick on one thing. You said exclusive OR is not considered a fundamental logic operator because it can be written in terms of AND, OR, and NOT. If we follow that logic (see what I did there!), however, then AND and OR cannot both be fundamental logic operators because De Morgan’s laws provide a relationship between AND, OR, and NOT:

    NOT A AND B equals NOT A OR NOT B

    NOT A OR B equals NOT A AND NOT B

    So AND can be written in terms of OR and NOT, or OR could be written in terms of AND and NOT. We can also go one step further. If you write the truth table for a NAND gate, you’ll see that it contains the logic for NOT if the inputs are connected together. So it’s possible to construct AND, OR, and NOT from just NAND gates (you can do the same with NOR), meaning NAND is really the only fundamental logic operator.

    • Cases in point - the Apollo Guidance Computer (AGC) used only NAND gates, as did the CRAY 1 supercomputer. AGC did it because of the available IC technology, Cray because of the desire to have uniform propagation times through the array processor.

    • You’re right that the choice of basis operators is arbitrary. (A common basis choice in high-level languages is AND, OR, and NOT.) You’re also right that NAND and NOR are the only operators that can be a basis by themselves. (A common basis choice in semiconductor design is NAND by itself.)

      But there isn’t anything about NAND that is more fundamental than NOR, and arguably there isn’t anything about NAND that is more fundamental than the combination of AND, OR, and NOT. They are just different choices of basis that are more useful in some applications than others.

      • I agree completely and that is the point I was attempting to make (perhaps not as clearly as possible). Shawn stated that XOR isn’t fundamental because it can be written in terms of AND, OR, and NOT thereby implying that those operators are in a sense fundamental. My post was trying to show that those operators can also be written in terms of other logic operators, thereby highlighting the fallacy in trying to label certain operators as fundamental. I think your use of the term basis is much more accurate.

  • There is no need to teach people obtuse punctuation like “&&” and “||” when C++ (and, by extension, Arduino) has perfectly reasonable “and”, “or”, and “not” keywords. You can — and, I think, especially in beginner tutorials, should — just write “P and Q” instead of “P && Q”, perhaps with a sidenote telling people that, for historical reasons, && is a common synonym for it.

    Also, while expressing XOR is “(P or Q) and not (P and Q)” is perfectly valid (and, as someone else pointed out, well-suited to gate-level optimization), I’ve found the form “(P and not Q) or (Q and not P)” is easier for beginners to understand, mainly because — by being an or of ands — it can very easily be related to a logic table.

    • Obtuse is as obtuse does. Hopper took the same point of view with COBOL and we ended up with the abomination of ADD A TO B GIVING C instead of c = a + b. Trying to make a piece of code look like English to make the code more understandable is a futile exercise for at least 2 reasons - first, anyone listening to the President’s concatenations of English words should realize that just because the symbols are English the semantics are not automatically comprehensible; second, there are now a lot of non-English-speaking software writers out there. “&&” looks the same in all languages, whereas “and” does not. It’s the same reason we use emojis - universal communication through universal symbols. So just think of “&&” as the emoji for ‘and" and you’ll be happy :-)

    • There is no need to teach people obtuse punctuation like “&&” and “||” when C++ (and, by extension, Arduino) has perfectly reasonable “and”, “or”, and “not” keywords. You can — and, I think, especially in beginner tutorials, should — just write “P and Q” instead of “P && Q”, perhaps with a sidenote telling people that, for historical reasons, && is a common synonym for it.

      I hadn’t realized that there are keywords for “and”, “or”, and “not” in C++. I’m just so used to using symbols for each. When I approach a new language I search for symbols instead of keywords for simple operators so I never looked for the keywords when introduced to C++ in the guise of Arduino. (I had so far avoided anything more C-like than Pascal up to then.)

      Also, most demo and publicly shared Arduino code uses the symbols instead of the keywords. So, while keywords can be easier for the novice to immediately read and learn from, they will be totally unprepared for the rest of the world.

      I would disagree (mostly for semantic reasons) with you calling “&&” as synonym for “and”. I think it should be better described as the symbol for “and”. On the similar reasoning that “+” is the symbol for “plus” (within an algebraic context).

      • Sure, but today’s novices will be writing tomorrow’s tutorials, and if we tell them today that “and” is a thing, whereas “&&” is a historical synonym/symbol for the same thing, then maybe ten years from now we’ll have more readable tutorial code.

        I CAN DREAM.

  • It’s interesting that you expressed the XOR as: P ⊕ Q = (P || Q) && !(P && Q)

    The classical expression for XOR is P ⊕ Q = (P && !Q) || (!P && Q)

    Interestingly, your expression is more “elegant”, involving only 4 logic operators instead of the 5 logic operators in the classic expression.

  • SparkFun’s tutorials are really fun and easily accessible. Thank you so much for sharing

Related Posts

Gravatar!

Recent Posts

Liquidation Sale

Tags


All Tags