Delicious Bookmark this on Delicious      HOME > > ARDUINO LANGUAGE COURSE  t.o.c.

Second tutorial on switches as inputs

Boolean variables. Boolean operators: AND and OR.

This is one of a collection of pages which, together, attempt to show you "everything" about the Arduino's programming language.

There is a page for you with more information about the project in general, and the way these pages are organized, if you want that.

Please visit my page about power browsing notes sometime.

This page, and the software it references, ©TK Boyd, 1/2010.

More on switches for input

Further adventures with switches... first steps with complex conditions.... and a new data type.

Remember, please, that these exercises are designed to give you a whirlwind tour through the Arduino's programming language. If the programs developed are sometimes trivial, that is the price of rapid progress.

The application here will light one LED, depending on what switch or switches are closed. It may seem trivial and artificial, but in fact the program will be using things that are remarkably pervasive in many real applications built on microprocessors. But you don't need to see that. Just read on; the bits you do need should be clear.

In the last program, we had two switches, two LEDs. If switch "A" was closed, LED "A" lit, and if switch "B" was closed LED "B" lit.

We're going to work through a series of exercises in this tutorial which use switches and one or more LEDs, but the rules connecting "switch(es) closed" and "LED(s) lit" will be more complex.

For the first program, we are going to build a device with two switches and one LED. If either switch is closed, the LED will go on.

In the previous exercise, the switch/ LED code was essentially independent... each switch and LED were dealt with in isolation.

In this exercise, we are going to start by "looking" at the state of each switch, saving what we "see" in a variable, and THEN we are going to deal with turning the LED on or off.

Now, we COULD use the sort of variables we've used before, and use a "code" that says "put a one in the variable if the switch is closed, and put a zero in it if it isn't." That would work. But there's a better way. "Better"? More clear, less susceptible to programmer mental lapses, and anyway the way we are going to do it "fits" really neatly into the needs of the "if" statements we will use.

There is a data type you haven't met yet called "boolean". A variable of type boolean can hold "true" or "false".

Have a look at the following. It doesn't, yet, do anything with the LED. Nor much with one of the switches. I've used "Green" and "Yellow" in my variable names because my switches are on green and yellow wires. It makes it REALLY EASY to know which switch goes with which variable. Either mark your switches "Green" and "Yellow", or "A" and "B", and then change the variable names. Always strive to make anything you can EASY... there will be plenty of things to make your programming life hard without adding confusion over "which switch was that?"

/*FEAa1BooleanSimpleStart
29 Dec 09

Needs inputs on pins 4 and 5,
LED on pin 13*/

const byte bInGreen=4;//Pin number where "Green" input connected
const byte bInYellow=5;//Pin number where "Yellow" input connected

const byte LED=13;//Pin with LED

boolean boGreenWasClosed;//Create variable to hold memory of state
             //of switch at most recent examination.
boolean boYellowWasClosed;

void setup()
{ Serial.begin(9600);//Prepare serial port for use
  pinMode(bInGreen,INPUT);
  pinMode(bInYellow,INPUT);
  pinMode(LED,OUTPUT);
}

void loop()
{
  if (digitalRead(bInGreen)==LOW)
        {boGreenWasClosed=true;}
          else {boGreenWasClosed=false;};

  if (boGreenWasClosed) {Serial.println("Green was closed");}
    else {Serial.println("Green open");};

  delay(200);//To slow things down, so system doesn't trip
  //over itself trying to get things out on the serial
  //port fast enough.
}

Run the program, and open up the serial monitor. On the serial monitor, you should be seeing "Green open" over and over. Close the green switch, and you should see "Green was closed". If you don't, try the yellow switch. If that makes your program say "Green was closed", then all you need to do is to change....

const byte bInGreen=4;
const byte bInYellow=5;

... to ....

const byte bInGreen=5;
const byte bInYellow=4;

Because you did the program the SMART way, that ONE change fixes everything throughout the program. If the software is written properly, it is often easier to make a change in the software than to make changes to the hardware. (You could, of course, have fixed the switch reversal by changing where they connect to the Arduino... but isn't it easier just to edit the code?)

Now... that little program does almost nothing... but it still took me a few tries to get it JUST right. I didn't, initially, even try to do the code for detecting and reporting the state of the other switch. I began working towards that by creating bInYellow and boYellowWasClosed alongside the variables for the green switch, but that was trivial.

Now that the code for the green switch is working well, it is really easy, especially if you use copy/paste, to add the code for checking the yellow switch, and reporting its state.

If you are programming well, you will often find that one bit of code (e.g. that for the green switch) gives you most of what you need for other bits of code.

/*FEAa1BooleanSimple
29 Dec 09

Needs inputs on pins 4 and 5,
LED on pin 13*/

const byte bInGreen=4;//Pin number where "Green" input connected
const byte bInYellow=5;//Pin number where "Yellow" input connected

const byte LED=13;//Pin with LED

boolean boGreenWasClosed;//Create variable to hold memory of state
             //of switch at most recent examination.
boolean boYellowWasClosed;

void setup()
{ Serial.begin(9600);//Prepare serial port for use
  pinMode(bInGreen,INPUT);
  pinMode(bInYellow,INPUT);
  pinMode(LED,OUTPUT);
}

void loop()
{
  //First check both switches, remember their states
  if (digitalRead(bInGreen)==LOW)
        {boGreenWasClosed=true;}
          else {boGreenWasClosed=false;};

  if (digitalRead(bInYellow)==LOW)
        {boYellowWasClosed=true;}
          else {boYellowWasClosed=false;};

  //Take action(s) depending on what the switch states were
  if (boGreenWasClosed) {Serial.println("Green was closed");}
    else {Serial.println("Green open");};

  if (boYellowWasClosed) {Serial.println("Yellow was closed");}
    else {Serial.println("Yellow open");};

  delay(200);//To slow things down, so system doesn't trip
  //over itself trying to get things out on the serial
  //port fast enough.
}

Note the use of comments to help any reader keep track of what is being done in different sections of the code. ADD COMMENTS LIBERALLY. What is "obvious" to you now may not be obvious later.

That code "works"... but reading the information appearing in the serial monitor isn't as easy as it might be.

Time to learn the first of two computer meanings for the word "AND".

If I say I want fish AND chips, I'm not going to be completely happy. If I say "I will go swimming if I have time AND the weather is nice, there will be times when the weather is nice that I don't go swimming.

One of the computer's uses of "AND" is as above. In the Arduino, we write that "AND" as &&.

In the following code, the LED is turned OFF at the start of each pass through the loop, but sometimes, just before the delay at the end of the loop, it is turned on. Look at the following code before playing with it, and try to guess or work out what it will take to turn the LED on. Run the program, see if you are right!

/*FEAa1BooleanSimple
29 Dec 09

Needs inputs on pins 4 and 5,
LED on pin 13*/

const byte bInGreen=4;//Pin number where "Green" input connected
const byte bInYellow=5;//Pin number where "Yellow" input connected

const byte LED=13;//Pin with LED

boolean boGreenWasClosed;//Create variable to hold memory of state
             //of switch at most recent examination.
boolean boYellowWasClosed;

void setup()
{ Serial.begin(9600);//Prepare serial port for use
  pinMode(bInGreen,INPUT);
  pinMode(bInYellow,INPUT);
  pinMode(LED,OUTPUT);
}

void loop()
{
  //First check both switches, remember their states
  if (digitalRead(bInGreen)==LOW)
        {boGreenWasClosed=true;}
          else {boGreenWasClosed=false;};

  if (digitalRead(bInYellow)==LOW)
        {boYellowWasClosed=true;}
          else {boYellowWasClosed=false;};

  //Take action(s) depending on what the switch states were

  if (boGreenWasClosed) {Serial.println("Green was closed");}
    else {Serial.println("Green open");};

  if (boYellowWasClosed) {Serial.println("Yellow was closed");}
    else {Serial.println("Yellow open");};

  digitalWrite(LED,LOW);//Turn LED off, always, at least for a moment.

  /*Now, maybe, turn LED on. If you turn it on here, it will stay on
  for a moment, while the following "delay" passes, and the eye will
  register that. The eye will not register the brief moment of being
  off which arose due to the earlier line of code, unless the LED stays
  off for several cycles, due to the following evaluating as "false"
  overall*/

  if (boGreenWasClosed && boYellowWasClosed)
    {digitalWrite(LED,HIGH);};

  delay(200);//To slow things down, so system doesn't trip
  //over itself trying to get things out on the serial
  //port fast enough.
}

Scroll down only when you are ready to check your answer....

v


v


v

v


v


v

What happens with this program is that the LED goes on if BOTH switches are closed, if the green switch AND (&&) the yellow switch are closed.

If you wanted to "fancy up" the messages to the serial monitor, one way to do that would be to modify the part that writes to the serial monitor, making it....

  if (boGreenWasClosed && boYellowWasClosed)
                   {Serial.println("Both were closed");};

  if (boGreenWasClosed && !boYellowWasClosed)
                   {Serial.println("Green was closed; Yellow was closed");};

  if (!boGreenWasClosed && boYellowWasClosed)
                   {Serial.println("Green was open; Yellow was closed");};

  if (!boGreenWasClosed && !boYellowWasClosed)
                  {Serial.println("Both were open");};

The "secret" in the above is that the exclamation mark (!) says "not". It takes a little practice with the mental gymnastics of double negatives but, for instance...

"If ((not)Green Closed) AND ((not)Yellow Closed)..."

... actually means "if Green AND Yellow open..."!

---

Here's a moment to show you a useful programmer trick....

Put a "/*" (no quotation marks) in front of the "if (boGreenWasClosed)..." in your program, and a "*/" after the....

...else {Serial.println("Yellow open");};

... and you will have "remmed out" the lines sending things to the serial monitor. ("Remmed out" is, of course, dreadful English, but it is established. Sorry. Do watch out for places where nouns are being used as verbs, and vice versa, and eschew the new use of the old word. The practice is degrading our language. The word impact does not impact as clearly as it once did, for instance, as our brain scrabbles to decide what does it mean HERE. Once upon a time, "impact" was just a noun, and you didn't have to consider the alternative meaning.)

Why "rem out" code? It is a quick, tidy way of "removing" it from the program when it isn't... for the moment... needed. To put it back, we just remove the /* and */ which did the remming out.

With that code remmed out, you can remove (or rem out) the "delay(200);" If you look for it, you will see that the program is more responsive now. Previously, there were sometimes tiny delays before the LED went on or off when it should have.

---

Another little "aside"... but still important... just tangential to some of the rest of what we are doing. What's with all the semi-colons and brackets in the following???

if (boGreenWasClosed) {Serial.println("Green was closed");}
    else {Serial.println("Green open");};

Getting them right can be a pain for a beginner, but there IS a logic to it all.

The "if... else..." statement must end with a semi colon. That's the one at the very end. (I should admit here that there are various forms of the "if..." statement... but it is still true that there is always a semicolon to end it.)

The form of "if.. else..." we used in this program boils down to....

if (CONDITION) {STATEMENTs}
   else {STATEMENTs};

In that, "CONDITION" gets replaced by something that is either true or false, in our case the nice simple "boGreenWasClosed"

"STATEMENTs" gets replaced by a statement or statements. In our case, it was a single statement inside each set of curly braces... but each (always) needs its own semicolon, and in our case, the statement involved something in parentheses, adding to the punctuation confusion.

It sometimes helps to build things thus....

First type the container, e.g....

if () {}
  else {};

Then go back, and "fill in" the "stuff" that finishes the line, taking care to put a complete condition between the parentheses, and complete statement(s), with their semicolons, between the curly braces.

When you are really perplexed it can help to rem stuff out, and substitute something simple that MUST work....

if (boVeryComplex&&!NotWorking) {b1=5;}
      else {b1=7;};

... can be "tamed" thus....

if (true/*boVeryComplex&&!NotWorking*/) {/*b1=5;*/}
      else {/*b1=7;*/};

That won't "work"... but it will compile. Once you have something which will at least compile, you can start taking out some of the /*... */ pairs, (and the temporary "true", which, happily, "boils down" to "true"... i.e. it is acceptable to the "if..." statement as a condition) and getting individual parts right. If you divide your challenges thus, you will eventually conquer!

---

Whew! Lots of "odds and ends" getting dealt with along the way in this lesson.

To finish off, AND's cousin OR, and then something simple and fun, at least compared to the material of the past few paragraphs.

Here's a really crude program to turn the LED on if the green switch OR the yellow switch is closed....

/*FEAa1BooleanCrudeOr
29 Dec 09

Needs inputs on pins 4 and 5,
LED on pin 13*/

const byte bInGreen=4;//Pin number where "Green" input connected
const byte bInYellow=5;//Pin number where "Yellow" input connected

const byte LED=13;//Pin with LED

boolean boGreenWasClosed;//Create variable to hold memory of state
             //of switch at most recent examination.
boolean boYellowWasClosed;

void setup()
{ Serial.begin(9600);//Prepare serial port for use
  pinMode(bInGreen,INPUT);
  pinMode(bInYellow,INPUT);
  pinMode(LED,OUTPUT);
}

void loop()
{
  //First check both switches, remember their states
  if (digitalRead(bInGreen)==LOW)
        {boGreenWasClosed=true;}
          else {boGreenWasClosed=false;};

  if (digitalRead(bInYellow)==LOW)
        {boYellowWasClosed=true;}
          else {boYellowWasClosed=false;};

  //Take action(s) depending on what the switch states were

  digitalWrite(LED,LOW);//Turn LED off, always, at least for a moment.

  //Now, maybe, turn LED on....

  if (boGreenWasClosed)
    {digitalWrite(LED,HIGH);};

  if (boYellowWasClosed)
    {digitalWrite(LED,HIGH);};
}

You can make that a little more elegant by using, in place of....

  if (boGreenWasClosed)
    {digitalWrite(LED,HIGH);};

  if (boYellowWasClosed)
    {digitalWrite(LED,HIGH);};

.... one line, using the "OR" operator, which is two vertical lines: "||"....

  if (boGreenWasClosed || boYellowWasClosed)
    {digitalWrite(LED,HIGH);};

You can do things like....

if (boGreenWasClosed == boYellowWasClosed)
    {digitalWrite(LED,HIGH);};

... which would ask "Is what's in the variables the same?" and if the answer was yes, the LED would be turned on. In other words, it would turn on if both switches were open, or if both were closed, and it would be off otherwise.

You should also... pay attention!... know about the "!=" comparison operator.

If you had....

if (boGreenWasClosed != boYellowWasClosed)
    {digitalWrite(LED,HIGH);};

... then the LED would be on when one, and only one of the switches was closed. The LED would be on if only the green switch was closed. It would be on if only the yellow switch was closed. But not on if both were closed, or both open. (This is called an XOR, for "eXclusive OR"... it is like an OR, eXcluding the case when both inputs are true.)

Summary:

The Arduino's logical, aka Boolean, operators are...

If you want to skip the rest of this tutorial, you can! But it will appeal to some people... people who appreciated the Byzantine?

There is a whole "arithmetic" which can be applied to Boolean entities, to things which "boil down" to "true" or "false".

In the following, I'm not going to be clever, I'm not going to try to trick you. If you see "Mary is a boy", you can assume that is false. If you see "The lion was dangerous", you can assume that is true.

So... .consider... is the following true or false, overall?

The lion is dangerous and Mary is a boy.

False. It started well enough, but then we said "AND... something false". The whole thing is true only if both parts are true, if they are joined with an AND.

What about...

The lion is dangerous or Mary is a boy.

Overall: True. Because the two parts were joined by OR. Only one had to be true for the whole thing to be true.

Moving away from Boolean logic for a moment, just remind yourself that the following are both correct, the asterisk ("*") standing for multiplication:

(4+2)*3=18
4+(2*3)=24

The parentheses tell you the order to do things in. In the first equation, the 4 and 2 are added before the result is multiplied by 3. In the second, the 2 and 3 are multiplied, and then the result added to 4.

Parentheses can be used in the same way in boolean logic.

Consider:

The driver will drive at the speed limit if:
(The driver is law-abiding OR A policeman is behind him) AND the speed limit is 30mph.

Do you think that the driver will drive at 30mph?

Now replace parts of that with variables which can hold "true" or "false"

(boDriverLawful OR boPoliceBehind) AND boLimit30

Suppose we have a driver who is NOT lawful. Further suppose there is no policeman. Also, the limit is 30.

That would make the expression equivalent to....

(false OR false) AND true

... and thus, overall, FALSE... the driver might drive over 30!

If EITHER we change to a lawful driver, or a policeman turns up, the whole expression turns to something "true".

On the other hand, JUST changing boLimit30 to false means that regardless of the driver's morality or the presence of the police, the driver might drive faster than 30mph.

Call back to mind our Arduino connected to two switches and one LED. I worked quite hard to come up with this bit of "cleverness"... I've written it out with lots of new lines, to help you see the different levels of parentheses and how the bits fit together....

if (
      (boGreenWasClosed || boYellowWasClosed)
          &&
      (boGreenWasClosed != boYellowWasClosed)
   )
    {digitalWrite(LED,HIGH);};

Can you see what it does? Do you see that part of it is superfluous?

v

v

Scroll down when ready for answer....

v

v

v

It is an overly complicated "answer" to the XOR question. Sigh.

That code could be written as....

if ((boGreenWasClosed || boYellowWasClosed)
  &&(boGreenWasClosed != boYellowWasClosed))
        {digitalWrite(LED,HIGH);};

It would still "work", but maybe it isn't as clear? Never hesitate to spread things out, and use multiple lines, and use indents to make things more clear.


   Search this site or the web      powered by FreeFind

Site search Web search
Site Map    What's New    Search

The search engine is not intelligent. It merely seeks the words you specify. It will not do anything sensible with "What does the 'could not compile' error mean?" It will just return references to pages with "what", "does", "could", "not".... etc.

SPELL your search term properly. When I review search logs, it is amazing how many people ask the engine to search for something meaningless.


Why does this site cause a script to run? I have my web-traffic monitored for me by eXTReMe tracker. They offer a free tracker. If you want to try it, check out their site. And if there are Google ads on the page, they are run with scripts, too.


Click here to return to Arduino COURSE table of contents.
Click here to go to the author's home page.

Ad from page's editor: Yes.. I do enjoy compiling these things for you... hope they are helpful. However.. this doesn't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!
Click here to visit editor's freeware, shareware page.


Here is how you can contact this page's editor. This page, and the software it references, ©TK Boyd, 1/2010.

Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org