BOOLEAN STATES

  This page is part of my Model Remodel series of articles and a subset of my Arduino section.

DISCLAIMER: If you choose to attempt any of these modifications, you assume all risks thereof. I just wanted to share my experiences here. Neither Eaglemoss, nor myself, are responsible for any damages that may occur.


The final sketch I created for my Enterprise model controls many different events, from turning on and off various lights, to playing sounds, to triggering timed effect sequences. In order to track which events are active at any time, I frequently use boolean variables to store their current state (either active/on or inactive/off). I will first explain how booleans can be used to track states, and then I will demonstrate a second method of using booleans to control our two LEDs in a different way.

Booleans as States

As I described before in my Variables article, boolean variables are binary and can only store a value of 0 or 1. The nice thing about booleans is that the Arduino also sees a boolean value as true (1) or false (0). Our recent sketches actually use a boolean with the digitalRead command to tell us whether a DIGITAL pin is HIGH (1 = true) or LOW (0 = false) so it can change that LED to the opposite state.

Let’s say we want to add a feature to our sketch that acts as a main ‘power’ switch. While we could easily add a ‘hard’ physical switch that controls power to the entire model, I chose to use the red Power button on my IR Remote Control to serve this purpose in a ‘soft’ manner.

To do this, we need to know the state of every function our sketch controls so this ‘power’ feature can override those states. Here, I have added a boolean to store the overall power state as well as two additional booleans to store the current state of our two LEDs. All three booleans are declared with an initial default value of false.

TIP: When assigning a value to a boolean, we can use a 0 or the word false, as well as a 1 or the word true. The words take up more program storage space, but may make your code easier to follow. It is entirely up to you.

...
// Create a LEDPin variable and set its value to 3
const byte LEDPin = 3;
// Create a LEDPin2 variable and set its value to 4
const byte LED2Pin = 4;
// Create booleans to store feature states
bool pwrState = false;
bool LEDPinState = false;
bool LED2PinState = false;
void setup() {
...

Next, we need to add the code that will capture the Power button press on the IR Remote Control and switch the state of the new pwrState boolean variable. This code uses an if/else statement to check the value of pwrState and performs the following:

  • If pwrState is true (ON), it turns off the two LEDs and sets the pwrState to false (OFF)
  • If pwrState is false (OFF), it sets the pwrState to true (ON)

NOTE: With my IR remote, the power button sends a Command= value of 0x45 – your remote codes may be different.

...
// Check the received IR code
switch (IrReceiver.decodedIRData.command) {
  // If the received IR Command= value is for Power
  case 0x45:
    //Change Power State
    if (pwrState) {
      digitalWrite(LEDPin, LOW);
      digitalWrite(LED2Pin, LOW);
      pwrState = false;
    } else {
      pwrState = true;
    }
    break;
  // If the received IR Command= value is for Button 1
  case 0xC:
    //Change LED 1 State
...

Then, we need our sketch to update the appropriate LED state boolean values when the associated LED pin is changed between HIGH (ON = true) and LOW (OFF = false). We can assign this value to the boolean by using the digitalRead command after we call the changeLEDState function each time:

...
// If the received IR Command= value is for Button 1
case 0xC:
  //Change LED 1 State
  changeLEDState(LEDPin);
  LEDPinState = digitalRead(LEDPin);
break;
// If the received IR Command= value is for Button 2
case 0x18:
  //Change LED 2 State
  changeLEDState(LED2Pin);
  LED2PinState = digitalRead(LED2Pin);
break;
...

Finally, we will make it so the LEDs cannot be activated unless the ‘power’ is turned on with the Power remote button first. This can be easily done inside our Custom Function by wrapping the previous code inside a new if/else statement that checks to see if the pwrState value is true:

...
// Custom Function to change LED state by pin number
void changeLEDState (byte Pin) {
  if (pwrState) {
    if (digitalRead(Pin)) {
      digitalWrite(Pin, LOW);
    } else {
      digitalWrite(Pin, HIGH);
    }
  }
}

That’s it! Verify and upload this sketch to your Arduino and we should be able to test our boolean state functionality:

  • Pressing Button 1 on the remote before pressing the Power button – nothing happens because the pwrState is false
  • Pressing Button 2 on the remote before pressing the Power button – nothing happens because the pwrState is false
  • Pressing the Power button – nothing happens, but internally the pwrState variable is now set to true
  • Pressing Button 1 on the remote after pressing the Power button – LED #1 turns on
  • Pressing Button 1 on the remote again – LED #1 turns off
  • Pressing Button 2 on the remote – LED #2 turns on
  • Pressing Button 2 on the remote again – LED #2 turns off
  • Pressing Button 1 on the remote again – LED #1 turns back on
  • Pressing Button 2 on the remote again – LED #2 turns back on
  • Pressing the Power button – both LEDs turn off, pwrState is set to false, and we are back where we started

Download my Sketch

I have shared this updated version of our main sketch via the Arduino Editor. Simply click the Open Code or Download buttons!

Using Booleans to Trigger Events

I mentioned early in this article that I would share how to use booleans in a different way. Here, we will tell our Arduino to keep doing something as long as a specific boolean value is true.

For example, instead of our remote buttons triggering a digitalWrite command to a LED pin, we could use the remote to change the value of the LED State booleans directly. Then, for each pass through loop() function, we tell the Arduino set the DIGITAL pin states according to the current boolean states. This method requires a few changes to our sketch, but the end result functionality will be exactly the same:

...
      // If the received IR Command= value is for Button 1
      case 0xC:
        //Change LED 1 State
        LEDPinState = changeLEDState(LEDPinState);
        break;
      // If the received IR Command= value is for Button 2
      case 0x18:
        //Change LED 2 State
        LED2PinState = changeLEDState(LED2PinState);
        break;
      }
    }
    // Resume receiving IR signals
    IrReceiver.resume();
  }
  // Update LED Pins
  digitalWrite(LEDPin, LEDPinState);
  digitalWrite(LED2Pin, LED2PinState);
}
// Custom Function to change LED state by boolean value
bool changeLEDState (bool State) {
  bool result;
  result = State;
  if (pwrState) {
    if (State) {
      result = false;
    } else {
      result = true;
    }
  }
  return result;
}

How this Sketch Works

A Modified changeLEDState Function

First, I modified how our changeLEDState function works. I want this function to change the state of a boolean from true to false, or vice versa. Since I need the function to return or ‘reply’ with this updated boolean value, I changed the modifier in front of the changeLEDState function name to bool. I also updated the function’s ‘parameters’ field to accept an incoming boolean local variable named State.

The bool result and result = State commands create a temporary outgoing boolean local variable named result and assigns it the current incoming value of State. If I call this function and send it a boolean value parameter of true, these command assign the value true to the result variable. These are placed before any other work is done inside the function so the incoming State value will be returned untouched if the following code does not get executed.

The if/else statement should look familiar. It checks to see if the pwrState is true (ON), then checks the value of the State parameter passed (sent) to this function. If the State value is true, make the outgoing result value false, and if State value is false, make the outgoing result value true. It basically sets the outgoing result value to be the opposite of the incoming State value.

Finally, the value of the result variable is returned to the code that called the function in the first place.

The Remote Control Commands

Under the sections of our sketch where the IR Remote Control commands are processed, I assigned the value of the respective LED State booleans to be the result of calling the modified changeLEDState function and passing it the current LED State boolean value.

For example, if I send the current LEDPinState value to our function as the parameter, it will return (reply) with the opposite boolean state. This value is then assigned back to the LEDPinState variable, overwriting what it was before.

The digitalWrite Commands

At the end of our loop() function, after all of the IR Remote Control processing is complete, we use digitalWrite commands to tell the Arduino to update the LED pins to match the current values of our LED state booleans (even if the state hasn’t changed).

One thing to know about the digitalWrite command is that it is relatively slow. Every time our loop() function runs, these commands make the Arduino lookup internal registers for the pin, port register/bit, etc. and that takes some time. We may not notice this delay, but it does occur.

Download my Sketch

While I will not keep this code in our main sketch going forward, I have shared the sketch via the Arduino Editor. Simply click the Open Code or Download buttons!

Which Method to Use?

Both methods of using booleans I have shown here work fine, but the second method calls digitalWrite way more than necessary. By design, the digitalWrite command sets a DIGITAL pin to be HIGH (ON = true) or LOW (OFF = false) and that pin will stay that way until another digitalWrite command changes it. For this reason alone, never mind how slow the command itself is, the first method is likely the better way to go.

There are other situations where the second method would be a better choice, just not when using the digitalWrite command inside the loop() function. I just wanted to show you multiple ways of controlling events with booleans.

Next Arduino Page


DIMMING LEDs – Changing the brightness of LEDs with Arduino