Flag variables are great, and totally not evil, when you just have two states: ON or OFF. What about when you have multiple states? Is there an option better than creating multiple flag variables? The C-language has a declaration type just for this purpose. It is called an enumeration, or enum. Setting up a state machine with enum is a surprisingly simple. Arduino and embedded programmers should use them! All you need to do is create descriptive tag names, and let the compiler assign them an integer value. Unlike a #define which is just a macro replacement, the compiler treats an enum as your personal variable type. This behavior comes in handy when you’re creating states for a state machine. I show how to create a simple state machine with enum, to blink an LED with millis(), in this post. [shareable]Using an enum is like making your own personal variable. See how in this tutorial.[/shareable]

Creating States

Start by thinking about the “states” that this LED will go through. We want it to blink. So that means either it’ll be blinking or not blinking. How many states can you count? You might think, “that’s easy, it’s 2! BLINK and NOT_BLINK.” That is true, but only half of them. What about the actual blinking? When the LED should be “blinking”, in code that means the LED itself will be ON and OFF. So that’s two more states for our LED.

Creating an enum

Here are the four states the LED can exist in: Blinking_enabled, Blinking_disabled, LED_on, and LED_off. Here is how to create the enum, named “blinkStates”, with those 4 states.

enum blinkStates {
  BLINK_DIS, // blink disable
  BLINK_EN, // blink enable
  LED_ON, // we want the led to be on for interval
  LED_OFF // we want the led to be off for interval
};
Just like the compiler knows what an “int” or “float” is, now it knows what a “blinkStates” variable type is. This new variable type isn’t very useful yet, because we need to create a variable of this type.

enum blinkStates ledState;

Example State Machine with enum Code

Now that we’ve defined our state machine and enum, we need some code to go with it. Here’s a relatively simple example. One character Serial commands will control whether or not to blink the LED. Using millis() to control the rate of blinking, mean we will never miss a command. You could easily swap out the serial code for push buttons. (This is why millis() makes it appear like you can multitask on an Arduino.)

enum blinkStates {
  BLINK_DIS, // blink disable
  BLINK_EN, // blink enable
  LED_ON, // we want the led to be on for interval
  LED_OFF // we want the led to be off for interval
};

enum blinkStates ledState;
const int ledPin = 13;
long interval = 1000;
unsigned long previousMillis = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  unsigned long currentMillis = millis();

  // use ! and + characters to control the blinking.
  if (Serial.available() > 0) {
    char incomingByte = Serial.read();
    // turn off LED
    if (incomingByte == '!')
      ledState = BLINK_DIS;

    // turn on LED
    if (incomingByte == '+')
      ledState = BLINK_EN;
  }

  // enums are just integers, so let's see if
  // it has been enabled.
  if (ledState > BLINK_DIS) {
    if ((unsigned long)(currentMillis - previousMillis >= interval)) {
      // enough time has passed, let's change the state of the LED.
      if (ledState == LED_ON) {
        // time to turn off the LED
        ledState = LED_OFF;
        digitalWrite(ledPin, LOW);
      } else {
        // time to turn on the LED
        ledState = LED_ON;
        digitalWrite(ledPin, HIGH);
      }
      // reset our timer
      previousMillis = currentMillis;
    }
  } else if (ledState == BLINK_DIS) {
    // blinking is disabled, so turn off LED
    digitalWrite(ledPin, LOW);
  }
}
// Code by [email protected]
// More at: [permalink]

Looking deeper at our enum

One line of code in this program is critical to understand, and it is this if-statement:

if (ledState > BLINK_DIS) {
Remember that enums are just integers. So we can use them as if we assigned each of our “states” an integer number. Since BLINK_DIS appears first in the enum’s list, it is assigned the lowest integer. The simple if-statement just checks if the LED is active. The code’s logic assumes that if the state is not BLINK_DIS, something should be happening.

What is inside of an enum

This code example illustrates the simplicity of an enum. We will print out the values for each of our states.

enum blinkStates {
  BLINK_DIS, // blink disable
  BLINK_EN, // blink enable
  LED_ON, // we want the led to be on for interval
  LED_OFF // we want the led to be off for interval
};

enum blinkStates ledState;

void setup() {
  delay(1000);
  Serial.begin(9600);
  Serial.println(F("---------"));
  Serial.print(F("BLINK_DIS = "));
  Serial.println(BLINK_DIS);

  Serial.print(F("BLINK_EN = "));
  Serial.println(BLINK_EN);

  Serial.print(F("LED_ON = "));
  Serial.println(LED_ON);

  Serial.print(F("LED_OFF = "));
  Serial.println(LED_OFF);
}

void loop() { }
// Code by [email protected]
// More at: [permalink]
When I run it on my Arduino Uno and my MSP430 based Launchpad, I get the following results.

---------
BLINK_DIS = 0
BLINK_EN = 1
LED_ON = 2
LED_OFF = 3
So what you can see with this example is that C is using integers to represent our simple to use names. [shareable]Using an enum is like making your own personal variable. See how in this tutorial.[/shareable]
What is a coding situation you could have used an enum to simply your logic?
Author

Fan of making things beep, blink and fly. Created AddOhms. Stream on Twitch. Video Host on element14 Presents and writing for Hackster.IO. Call sign KN6FGY.

10 Comments

  1. David Stonier-Gibson Reply

    Hi,

    I applaud your use of names, via an enum, for various FSM states. In my own neary 50 year career in the controls field I gave up on naming states. Some FSMs have many states, often very transitory ones (think contact debounce) that thinking up meaningful names became a major block to creative flow. So I would *always* draw a good state chart and simply number the states. Just about the only time I have used names is for a LED flasher in Arduino 😉

  2. Hello James, I have been attempting to utilize your code for my own nefarious schemes. I used the code snippet from your flash an LED with a variable on and off time with some success. I am now trying to expand on that concept by adding another delay after the LED turns off before turning on another output. This is all in aid of automating a green house. I would like to: 1st, enable the watering system, 2nd look at the soil moisture sensor value trigger point ( I have this sorted out). If both are met/enabled then 3rd turn on the water pump for ‘on time’ and then pump off. 4th wait for a ‘off time’ to see what the feedback from the soil sensor is and if the sensor is still dry repeat the pump on/off cycle and wait again. This would repeat until the soil sensor is satisfied.
    Your code virtually satisfies this scenario with a bit of additions for the soil sensor/enable.
    I run into problems when I try to incorporate my last delay in which, after the soil sensor is satisfied, I would like to wait for an additional period of time, then check my water reservoir level and replenish as required.
    As I write this, I think I see how I can solve the problem, maybe.
    I was trying to include the last delay as part of the ‘blink’ code and I should just use the soil sensor as the trigger for last delay.
    My understanding of coding is more ‘mechanical’ than finesse, and I can’t seem to convert your code to straight up ‘digitalWrite(4,HIGH)’ from something like ‘LEDstate !=…’
    Anyway, feel free to comment. I did not post code as I am not good at it and it is likely looks like some of the wiring I have seen on projects :). ve7bul

    • David Stonier-Gibson Reply

      Adafruit have an excellent tutorial on multitasking and state machines.

  3. Another tip.

    You can also set the values of the enum items to specific values if you wish, i.e.
    [arduino]
    enum blinkStates {
    BLINK_DIS = 1,
    BLINK_EN = 10,
    LED_ON,
    LED_OFF
    };
    [/arduino]

    This is handy if you have a group of specific values you need to use. Probably more related to enums in general than states.

    The other good thing about using enums/states is that it makes you consider all states and transitions which are easily missed if done otherwise.

  4. There is a typo in the title … you have “Micrcontroller” instead of “Micorcontroller” … I thought that you would want to correct that – then delete this comment ;~)

    • If I had a dollar for everytime I spelled microcontroller that way, I’d have a lot more money than I get from banner ads! Thanks.

  5. I’ve used enum to represent a state machine and that made the flow logic simpler and clearer to read. I also seen it used for representing different colours.
    When you say “Remember that enums are just integers” does the complier find the smallest integer type that the enum will fit into? Would I be correct in thinking that there’s no bounds checking so I could assign an invalid value?

    • Good questions. I don’t know the C-standards well enough to know if the compiler will change variable types on an out of bounds condition. Would be interesting to do some experiments.

      • The Arduino compiler lets you put whatever value you like into the variable – not just the listed Enum values – as long as it’s integer.

        This kind of defeats some of the value of using it over just defining a list of “states” in “#Define” or “const” statements.

Write A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.