Let's take another look at that last sketch. As you can see, it is very repetitive. The same code is duplicated almost verbatim for each flashing LED. The only thing that changes (slightly) is the variable names.
This code is a prime candidate for a little Object Oriented Programming (OOP).
Put a little OOP in your loop.
The Arduino Language is a variant of C++ which supports Object Oriented Programming. Using the OOP features of the language we can gather together all of the state variables and functionality for a blinking LED into a C++ class.
This isn’t very difficult to do. We already have written all the code for it. We just need to re-package it as a class.
Then we add in all the variables from FlashWithoutDelay. Since they are part of the class, they are known as member variables.
class Flasher { // Class Member Variables // These are initialized at startup int ledPin; // the number of the LED pin long OnTime; // milliseconds of on-time long OffTime; // milliseconds of off-time // These maintain the current state int ledState; // ledState used to set the LED unsigned long previousMillis; // will store last time LED was updated };
Next we add a constructor. The constructor has the same name as the class and its job is to initialize all the variables.
class Flasher { // Class Member Variables // These are initialized at startup int ledPin; // the number of the LED pin long OnTime; // milliseconds of on-time long OffTime; // milliseconds of off-time // These maintain the current state int ledState; // ledState used to set the LED unsigned long previousMillis; // will store last time LED was updated // Constructor - creates a Flasher // and initializes the member variables and state public: Flasher(int pin, long on, long off) { ledPin = pin; pinMode(ledPin, OUTPUT); OnTime = on; OffTime = off; ledState = LOW; previousMillis = 0; } };
Finally we take our loop and turn it into a member function called “Update()”. Note that this is identical to our original void loop(). Only the name has changed.
class Flasher { // Class Member Variables // These are initialized at startup int ledPin; // the number of the LED pin long OnTime; // milliseconds of on-time long OffTime; // milliseconds of off-time // These maintain the current state int ledState; // ledState used to set the LED unsigned long previousMillis; // will store last time LED was updated // Constructor - creates a Flasher // and initializes the member variables and state public: Flasher(int pin, long on, long off) { ledPin = pin; pinMode(ledPin, OUTPUT); OnTime = on; OffTime = off; ledState = LOW; previousMillis = 0; } void Update() { // check to see if it's time to change the state of the LED unsigned long currentMillis = millis(); if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) { ledState = LOW; // Turn it off previousMillis = currentMillis; // Remember the time digitalWrite(ledPin, ledState); // Update the actual LED } else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime)) { ledState = HIGH; // turn it on previousMillis = currentMillis; // Remember the time digitalWrite(ledPin, ledState); // Update the actual LED } } };
By simply re-arranging our existing code into the Flasher class, we have encapsulated all of the variables (the state) and the functionality (the machine) for flashing a LED.
Now lets use it:
Now, for every LED that we want to flash, we create an instance of the Flasher class by calling the constructor. And on every pass through the loop we just need to call Update() for each instance of Flasher.
There is no need to replicate the entire state machine code anymore. We just need to ask for another instance of the Flasher class!
class Flasher { // Class Member Variables // These are initialized at startup int ledPin; // the number of the LED pin long OnTime; // milliseconds of on-time long OffTime; // milliseconds of off-time // These maintain the current state int ledState; // ledState used to set the LED unsigned long previousMillis; // will store last time LED was updated // Constructor - creates a Flasher // and initializes the member variables and state public: Flasher(int pin, long on, long off) { ledPin = pin; pinMode(ledPin, OUTPUT); OnTime = on; OffTime = off; ledState = LOW; previousMillis = 0; } void Update() { // check to see if it's time to change the state of the LED unsigned long currentMillis = millis(); if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) { ledState = LOW; // Turn it off previousMillis = currentMillis; // Remember the time digitalWrite(ledPin, ledState); // Update the actual LED } else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime)) { ledState = HIGH; // turn it on previousMillis = currentMillis; // Remember the time digitalWrite(ledPin, ledState); // Update the actual LED } } }; Flasher led1(12, 100, 400); Flasher led2(13, 350, 350); void setup() { } void loop() { led1.Update(); led2.Update(); }
Page last edited March 08, 2024
Text editor powered by tinymce.