- Installation
- Quick start
- Core
- State Control
- Getter methods
- Event functions and callbacks
- Full example usage
To install the library, follow these steps:
- Access
Sketch→Include Library→Manage Libraries... (Ctrl + Shift + I) - Install
SmartTrafficLightby Raphael Vicente de Oliveira - Include it in your code
- Clone this repository (or download
.zip):git clone https://github.com/vicenteraphael/SmartTrafficLight.git
- Move it to your
Arduino/libraries/folder - Restart the Arduino IDE
- Include it in your code
- Open
platformio.ini, a project configuration file located in the root of PlatformIO project. - Add the following line to the lib_deps option of
[env:]section:vicenteraphael/SmartTrafficLight@^2.0.1 - Build a project, PlatformIO will automatically install dependencies.
- Include it in your code
- Open PlatformIO Core CLI
- Change directory (
cd) to the PlatformIO project whereplatformio.iniis located. - Copy the following
pio pkg installcommand and paste into the CLI shell, press Enter:pio pkg install --library "vicenteraphael/SmartTrafficLight@^2.0.1" - Include it in your code
SmartTrafficLight library provides the following header files that can be included in your project:
#include <SmartTrafficLight.h>The example below shows the minimal setup required to run the traffic light:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight(12, 11, 10, 9);
void setup() {
trafficLight.begin();
trafficLight.enable();
}
void loop() {
trafficLight.update();
}Or with attach():
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void setup() {
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.enable();
}
void loop() {
trafficLight.update();
}Typical usage flow:
- Instantiate the object
- (Optional) Configure pins with
attach() - (Optional) Configure intervals with
setIntervals() - Call
begin() - Enable the system with
enable()(Required to start operation) - Call
update()continuously insideloop()
Common mistakes:
- Forgetting to call
begin() - Forgetting to call
enable() - Not calling
update()insideloop() - Calling
attach()afterbegin() - Forgetting to set the pins in the constructor or
attach()
Description:
Important
Used to instantiate the class and, optionally, configure the LED pins
Creates an instance of SmartTrafficLight and, optionally, configures the pins to be used. Must be used before calling any other method. If the parameters are omitted, the pins can also be configured later by attach().
Definition:
SmartTrafficLight() = default
SmartTrafficLight(const uint8_t gPin, const uint8_t yPin, const uint8_t rPin, const uint8_t bPin = NO_PIN)Note
NO_PIN is an internal macro with value 255, which literally means "no pin"
Parameters:
voidor:gPin: Digital pin for the green LEDyPin: Digital pin for the yellow LEDrPin: Digital pin for the red LEDbPin: Digital pin for the pedestrian button pin (OPTIONAL)
Returns:
SmartTrafficLight
Syntax:
SmartTrafficLight();
SmartTrafficLight(12, 8, 7);
SmartTrafficLight(12, 8, 7, 2);In the first case, the constructor will only create an instance of SmartTrafficLight and return it. Therefore, the pins configuration will need to be done by using attach().
In the second case, the LED pins are being configured, except for the button pin, that is passed on in the third case.
Example:
#include <SmartTrafficLight.h>
#define GREEN_PIN 12
#define YELLOW_PIN 11
#define RED_PIN 10
#define BUTTON_PIN 9
SmartTrafficLight trafficLight(GREEN_PIN, YELLOW_PIN, RED_PIN, BUTTON_PIN);
void setup(){}
void loop(){}If the parameters are omitted, creates the instance without reference to the pins, attach() is then required for setting up the pins.
Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void setup() {}
void loop() {}Description:
Important
CONDITIONALLY REQUIRED - This method must be called and only if the pins were not set in the constructor, aka SmartTrafficLight()
Configures the pins to be used. Can be called to configure the pins instead of SmartTrafficLight()
Definition:
void attach(const uint8_t gPin, const uint8_t yPin, const uint8_t rPin, const uint8_t bPin = NO_PIN)Note
NO_PIN is an internal macro with value 255, which literally means "no pin"
Parameters:
gPin: Digital pin for the green LEDyPin: Digital pin for the yellow LEDrPin: Digital pin for the red LEDbPin: Digital pin for the pedestrian button pin (OPTIONAL)
Returns:
void
Syntax:
trafficLight.attach(12, 8, 7);
trafficLight.attach(12, 8, 7, 2);Example:
#include <SmartTrafficLight.h>
#define GREEN_PIN 12
#define YELLOW_PIN 11
#define RED_PIN 10
#define BUTTON_PIN 9
SmartTrafficLight trafficLight{};
void setup() {
trafficLight.attach(GREEN_PIN, YELLOW_PIN, RED_PIN, BUTTON_PIN);
}
void loop() {}Description:
Configures each individual LED display timing, along with the minimum green time for the button timeout. If not called, the values are defined by default:
- Green interval = 10000 milliseconds
- Yellow interval = 2000 milliseconds
- Red interval = 5000 milliseconds
- Minimum green time = 5000 milliseconds
Definition:
void setIntervals(const unsigned long gInterval, const unsigned long yInterval, const unsigned long rInterval, const unsigned long minGTime = DEFAULT_MIN_GREEN_TIME)Parameters:
gInterval: Amount of time, in milliseconds, in which the green pin shall beHIGHyInterval: Amount of time, in milliseconds, in which the yellow pin shall beHIGHrInterval: Amount of time, in milliseconds, in which the red pin shall beHIGHminGTime: (OPTIONAL) Minimum amount of time, in milliseconds, in which the green pin shall beHIGHbefore triggering the button. DEFAULT VALUE: 5000 milliseconds.
Note
DEFAULT_MIN_GREEN_TIME is an internal macro for the default minimum green time (5000 milliseconds). The other literals are:
#define DEFAULT_GREEN_INTERVAL (10000)
#define DEFAULT_YELLOW_INTERVAL (2000)
#define DEFAULT_RED_INTERVAL (5000)
#define DEFAULT_MIN_GREEN_TIME (5000)
#define BLINKING_INTERVAL (1000) // For ERROR_STATE and BLINKING_YELLOW_STATEReturns:
void
Syntax:
trafficLight.setIntervals(10000, 2000, 5000);
trafficLight.setIntervals(10000, 2000, 5000, 3000);
Example:
#include <SmartTrafficLight.h>
#define GREEN_TIME 60000
#define YELLOW_TIME 5000
#define RED_TIME 30000
#define MIN_GREEN_TIME 30000
SmartTrafficLight trafficLight{};
void setup() {
trafficLight.setIntervals(GREEN_TIME, YELLOW_TIME, RED_TIME, MIN_GREEN_TIME);
}
void loop() {}Description:
Important
REQUIRED - This method must be called before using the traffic light
Warning
Initializes the system and checks if the pins were configured successfully. If not, the following message is displayed on the serial monitor (if Serial.begin() was previously called) and the program enters ERROR_STATE, which is a non-blocking state that triggers a constant blinking on the LED_BUILTIN pin (usually digital pin nº 13 or nº 2).
Fatal: uninitialized...
Use attach() to configure the pins
Use setIntervals() to customize the traffic light intervals
Use begin() to start the traffic light
Note
The library is fail-safe: calling any public method before begin() will automatically trigger ERROR_STATE
Definition:
void begin()Parameters:
void
Returns:
void
Syntax:
trafficLight.begin();Example:
#include <SmartTrafficLight.h>
#define GREEN_PIN 12
#define YELLOW_PIN 11
#define RED_PIN 10
#define BUTTON_PIN 9
SmartTrafficLight trafficLight{};
void setup() {
trafficLight.attach(GREEN_PIN, YELLOW_PIN, RED_PIN, BUTTON_PIN);
trafficLight.begin();
}
void loop() {}Description:
Important
REQUIRED - This method must be called as often as possible in order for the traffic light logic to work. The library is non-blocking and relies on millis(), so update() drives the internal state machine.
Updates the current state of the traffic light FSM using millis(). Needs to be continuously called inside loop()
Definition:
void update()Parameters:
void
Returns:
void
Syntax:
trafficLight.update();Example:
#include <SmartTrafficLight.h>
#define GREEN_PIN 12
#define YELLOW_PIN 11
#define RED_PIN 10
#define BUTTON_PIN 9
SmartTrafficLight trafficLight(GREEN_PIN, YELLOW_PIN, RED_PIN, BUTTON_PIN);
void setup() {
trafficLight.begin();
}
void loop() {
trafficLight.update();
}The methods in this section allow changing the current state of the traffic light FSM without interrupting its behaviour. The states are in the following format:
enum State {
GREEN_STATE, // Green light is active
YELLOW_STATE, // Yellow light is active (transition before red)
RED_STATE, // Red light is active
BLINKING_YELLOW_STATE, // Blinking mode (night mode)
DISABLED_STATE, // System is inactive (out of service)
ERROR_STATE // For handling initialization error
};In practice, the states can be represented by the following schema:
Solid line= automatic transition (timeout)
Dashed line= method call (user-triggered)
ANY STATE→BLINKING_YELLOW_STATE=startBlinking()
ANY STATE→DISABLED_STATE=disable()
By default, the system starts on DISABLED_STATE
Description:
Important
REQUIRED - This method must be called to start operation
Changes the current state from DISABLED_STATE to GREEN_STATE (or any other specified state), enabling the traffic light for use. If the current state is different from DISABLED_STATE, the call is ignored.
Definition:
void enable(State initialState = GREEN_STATE)Parameters:
void
Returns:
void
Syntax:
trafficLight.enable();
trafficLight.enable(YELLOW_STATE);
trafficLight.enable(RED_STATE);Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void setup() {
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.enable();
}
void loop() {
trafficLight.update();
}Description:
Changes the current state, whatever it may be, to DISABLED_STATE, taking the entire traffic light out of service.
Note
This is the default state in which the system starts
Definition:
void disable()Parameters:
void
Returns:
void
Syntax:
trafficLight.disable();Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight(12, 11, 10, 9);
void setup() {
trafficLight.begin();
trafficLight.enable();
}
void loop() {
trafficLight.update();
if (millis() >= 10000) {
trafficLight.disable(); // Disables the traffic light after 10 seconds of service
}
}Description:
Changes the current state, whatever it may be, to BLINKING_YELLOW_STATE, also known as night or nocturnal mode.
Definition:
void startBlinking()Parameters:
void
Returns:
void
Syntax:
trafficLight.startBlinking();Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void setup() {
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.startBlinking();
}
void loop() {
trafficLight.update();
}Description:
Changes the current state from BLINKING_YELLOW_STATE to GREEN_STATE, stopping the blinking mode. If the current state is different from BLINKING_YELLOW_STATE, the call is ignored.
Definition:
void stopBlinking()Parameters:
void
Returns:
void
Syntax:
trafficLight.stopBlinking();Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight(12, 11, 10, 9);
void setup() {
trafficLight.begin();
trafficLight.startBlinking();
}
void loop() {
trafficLight.update();
if (millis() >= 10000) { // stops blinking after 10 seconds
trafficLight.stopBlinking();
}
}Description:
Changes the current state from RED_STATE to GREEN_STATE. If the current state is different from RED_STATE, the call is ignored.
Definition:
void turnGreen()Parameters:
void
Returns:
void
Syntax:
trafficLight.turnGreen();Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void setup() {
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.enable();
}
void loop() {
trafficLight.update();
// The first cycle will have only 2 seconds of red interval
if (millis() >= 14000) {
trafficLight.turnGreen();
}
}Description:
If the current state is GREEN_STATE or YELLOW_STATE, starts transition to RED_STATE. If on GREEN_STATE, the transition mandatorily passes by YELLOW_STATE. If the current state is different from those, the call is ignored.
Definition:
void turnRed()Parameters:
void
Returns:
void
Syntax:
trafficLight.turnRed();Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight(12, 11, 10, 9);
void setup() {
trafficLight.begin();
trafficLight.enable();
}
void loop() {
trafficLight.update();
// The first cycle will have only 2 seconds of green interval
if (millis() >= 20000) {
trafficLight.turnRed();
}
}The system has built-in getter functions that allow accessing state-related attributes
Description:
Returns the current HIGH LED pin. If no pin is currently HIGH, returns NO_PIN (255)
Definition:
uint8_t getPinOn() constParameters:
void
Returns:
uint8_t: currentHIGHLED pin. If no pin isHIGH, returns 255
Syntax:
trafficLight.getPinOn();Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void setup() {
Serial.begin(9600);
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.startBlinking();
// Outputs 11
Serial.println(trafficLight.getPinOn());
}
void loop() {
trafficLight.update();
}Description:
Returns the current state of the FSM, an enum State variable
Definition:
State getState() constParameters:
void
Returns:
enum State: current state of the State Machine
Syntax:
trafficLight.getState();Example:
#include <SmartTrafficLight.h>
#define GREEN_PIN 12
#define YELLOW_PIN 11
#define RED_PIN 10
#define BUTTON_PIN 9
SmartTrafficLight trafficLight(12, 11, 10, 9);
void setup() {
Serial.begin(9600);
trafficLight.begin();
// Outputs: Disabled... Call enable()
if (trafficLight.getState() == DISABLED_STATE) {
Serial.println("Disabled... Call enable()");
}
else {
Serial.println("Enabled");
}
trafficLight.enable();
}
void loop() {
trafficLight.update();
}Description:
Returns the current state of the FSM as a string (const char*)
Definition:
const char *getStateToString() constParameters:
void
Returns:
const char*: current state of the State Machine converted to string format
Syntax:
trafficLight.getStateToString();Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void setup() {
Serial.begin(9600);
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.startBlinking();
// Outputs: BLINKING_YELLOW_STATE
Serial.println(trafficLight.getStateToString());
}
void loop() {
trafficLight.update();
}The system has various built-in event functions that allow attaching custom callbacks are triggered after some specific changes of state happens. These functions should be called once and only accept pointers to functions or lambda functions (which requires C++11 support). If an event function is not set up, no callbacks are dispatched when the event occurs.
Description:
Dispatches its callback function when the state is changed to GREEN_STATE, that is, when the traffic light turns green.
Definition:
void onTurnGreen(void (*func)())Parameters:
void (*func)(): Pointer to a function (callback)
Returns:
void
Syntax:
trafficLight.onTurnGreen(my_func);
trafficLight.onTurnGreen([]() {
doSomething(); // Requires C++11 support
});Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight(12, 11, 10, 9);
void print_green_light() {
Serial.println("Green light!");
}
void setup() {
Serial.begin(9600);
trafficLight.begin();
trafficLight.enable();
trafficLight.onTurnGreen(print_green_light);
// trafficLight.onTurnGreen([]() {
// Serial.println("Green light!");
// })
}
void loop() {
trafficLight.update();
}Description:
Dispatches its callback function when the state is changed to YELLOW_STATE, that is, when the traffic light turns yellow.
Definition:
void onTurnYellow(void (*func)())Parameters:
void (*func)(): Pointer to a function (callback)
Returns:
void
Syntax:
trafficLight.onTurnYellow(my_func);
trafficLight.onTurnYellow([]() {
doSomething(); // Requires C++11 support
});Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void print_yellow_light() {
Serial.println("Yellow light!");
}
void setup() {
Serial.begin(9600);
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.enable();
trafficLight.onTurnYellow(print_yellow_light);
// trafficLight.onTurnYellow([]() {
// Serial.println("Yellow light!");
// })
}
void loop() {
trafficLight.update();
}Description:
Dispatches its callback function when the state is changed to RED_STATE, that is, when the traffic light turns red.
Definition:
void onTurnRed(void (*func)())Parameters:
void (*func)(): Pointer to a function (callback)
Returns:
void
Syntax:
trafficLight.onTurnRed(my_func);
trafficLight.onTurnRed([]() {
doSomething(); // Requires C++11 support
});Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight(12, 11, 10, 9);
void print_red_light() {
Serial.println("Red light!");
}
void setup() {
Serial.begin(9600);
trafficLight.begin();
trafficLight.enable();
trafficLight.onTurnRed(print_red_light);
// trafficLight.onTurnRed([]() {
// Serial.println("Red light!");
// })
}
void loop() {
trafficLight.update();
}Description:
Dispatches its callback function when the enable() method is called; that is, when the state is changed from DISABLED_STATE to GREEN_STATE.
Definition:
void onEnable(void (*func)())Parameters:
void (*func)(): Pointer to a function (callback)
Returns:
void
Syntax:
trafficLight.onEnable(my_func);
trafficLight.onEnable([]() {
doSomething(); // Requires C++11 support
});Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void print_enable() {
Serial.println("Enabling...");
}
void setup() {
Serial.begin(9600);
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.onEnable(print_enable);
// trafficLight.onEnable([]() {
// Serial.println("Enabling...");
// })
}
void loop() {
trafficLight.update();
if (millis() >= 5000) {
trafficLight.enable();
}
}Description:
Dispatches its callback function when the state is changed to DISABLED_STATE, that is, when the disable() method is called.
Definition:
void onDisable(void (*func)())Parameters:
void (*func)(): Pointer to a function (callback)
Returns:
void
Syntax:
trafficLight.onDisable(my_func);
trafficLight.onDisable([]() {
doSomething(); // Requires C++11 support
});Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight(12, 11, 10, 9);
void print_disable() {
Serial.println("Disabling...");
}
void setup() {
Serial.begin(9600);
trafficLight.begin();
trafficLight.enable();
trafficLight.onDisable(print_disable);
// trafficLight.onDisable([]() {
// Serial.println("Disabling...");
// })
}
void loop() {
trafficLight.update();
if (millis() >= 5000) {
trafficLight.disable();
}
}Description:
Dispatches its callback function when the state is changed to BLINKING_YELLOW_STATE, that is, when the startBlinking() method is called.
Definition:
void onStartBlinking(void (*func)())Parameters:
void (*func)(): Pointer to a function (callback)
Syntax:
trafficLight.onStartBlinking(my_func);
trafficLight.onStartBlinking([]() {
doSomething(); // Requires C++11 support
});Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void print_start_blinking() {
Serial.println("Starting blinking...");
}
void setup() {
Serial.begin(9600);
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.enable();
trafficLight.onStartBlinking(print_start_blinking);
// trafficLight.onStartBlinking([]() {
// Serial.println("Starting blinking...");
// })
}
void loop() {
trafficLight.update();
if (millis() >= 5000) {
trafficLight.startBlinking();
}
}Description:
Dispatches its callback function when the state is changed from BLINKING_YELLOW_STATE to GREEN_STATE; that is, when the stopBlinking() method is called.
Definition:
void onStopBlinking(void (*func)())Parameters:
void (*func)(): Pointer to a function (callback)
Returns:
void
Syntax:
trafficLight.onStopBlinking(my_func);
trafficLight.onStopBlinking([]() {
doSomething(); // Requires C++11 support
});Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight(12, 11, 10, 9);
void print_stop_blinking() {
Serial.println("Stopping blinking...");
}
void setup() {
Serial.begin(9600);
trafficLight.begin();
trafficLight.startBlinking();
trafficLight.onStopBlinking(print_stop_blinking);
// trafficLight.onStopBlinking([]() {
// Serial.println("Stopping blinking...");
// })
}
void loop() {
trafficLight.update();
if (millis() >= 5000) {
trafficLight.stopBlinking();
}
}Description:
Dispatches its callback function when the current state is changed (to any other state).
Definition:
void onStateChanged(void (*func)())Parameters:
void (*func)(): Pointer to a function (callback)
Returns:
void
Syntax:
trafficLight.onStateChanged(my_func);
trafficLight.onStateChanged([]() {
doSomething(); // Requires C++11 support
});Example:
#include <SmartTrafficLight.h>
SmartTrafficLight trafficLight{};
void print_state_changed() {
Serial.println("State has been changed!");
}
void setup() {
Serial.begin(9600);
trafficLight.attach(12, 11, 10, 9);
trafficLight.begin();
trafficLight.enable();
trafficLight.onStateChanged(print_state_changed);
// trafficLight.onStateChanged([]() {
// Serial.println("State has been changed!");
// })
}
void loop() {
trafficLight.update();
if (millis() >= 15000) {
trafficLight.disable();
}
else if (millis() >= 10000) {
trafficLight.startBlinking();
}
}#include <SmartTrafficLight.h>
#define GREEN_PIN (12)
#define YELLOW_PIN (8)
#define RED_PIN (7)
#define BUTTON_PIN (2)
#define GREEN_INTERVAL (5000)
#define YELLOW_INTERVAL (1000)
#define RED_INTERVAL (2000)
#define MIN_GREEN_TIME (2000)
SmartTrafficLight trafficLight{};
void print_green_yellow_red() {
switch(trafficLight.getState()) {
case GREEN_STATE:
Serial.println("Turning Green...");
break;
case YELLOW_STATE:
Serial.println("Turning Yellow...");
break;
case RED_STATE:
Serial.println("Turning Red...");
break;
}
Serial.print("Pin on: ");
Serial.println(trafficLight.getPinOn());
}
void print_enable() {
Serial.println("Enabling...");
}
void print_disable() {
Serial.println("Disabling...");
}
void print_start_blinking() {
Serial.println("Starting blinking...");
}
void print_stop_blinking() {
Serial.println("Stopping blinking...");
}
void setup() {
Serial.begin(9600);
trafficLight.attach(GREEN_PIN, YELLOW_PIN, RED_PIN, BUTTON_PIN);
trafficLight.setIntervals(GREEN_INTERVAL, YELLOW_INTERVAL, RED_INTERVAL, MIN_GREEN_TIME);
trafficLight.onEnable(print_enable);
trafficLight.onDisable(print_disable);
trafficLight.onStartBlinking(print_start_blinking);
trafficLight.onStopBlinking(print_stop_blinking);
trafficLight.onStateChanged(print_green_yellow_red);
trafficLight.begin();
trafficLight.enable();
}
void loop(){
trafficLight.update();
if (millis() >= 15000) {
trafficLight.stopBlinking();
}
else if (millis() >= 10000) {
trafficLight.startBlinking();
}
else if (millis() >= 5000) {
trafficLight.disable();
}
}See also:
"'I Dig a Pygmy', by Charles Hawtrey and the Deaf Aids... Phase One, in which Doris gets her oats!"
