In the last post I briefly presented the hardware of the LedStripShow. This post sheds some light on the software part and outlines the core design principles and the basic components of the solution.
While the project was just for fun, I had the ambition to learn something about programming and improve my skills. Driven by this ambition I decided to define some design principles – the application shall…
- …be easy to use, implement and operate
- …run on an Arduino UNO or equivalent
- …be adaptable to drive LedStrips with various number of LEDs
- …be well structured and extendable
- …follow good practice and apply common software patters
In addition the implemented components shall be reusable where appropriate.
CORE APPLICATION COMPONENTS
The application comprises of the following core components (classes):
Main application class, initializes the application objects, orchestrates the program flow, stores the configuration, selects effects and reacts on user input.
Base class for all the effects, defines the interface for the effect handling and implements some standard behaviour.
The actual effects are defined as sub-classes derived from TLedEffects and define the detailed behaviour.
Interrupt Service Routine
Handles the rotary encoder and triggers updates in the current effect configuration
The following helper classes are used, packaged as libraries (including some examples):
Provides the functionality of a constraint counter (lower and upper boundery), which counts up or down in predefinable steps, signals if a boundery is reached and has a predefined behaviour regarding the action it takes when the boundery is reached (up-down counting, cycling counting)
Provides basic timer functionality. The timer has to be polled and as soon as the configured time has passed it signals the event and calls the configured call back function.
Maintains a buffer for each LED and provides buffer manipulation routines such as copying, shifting, rotating, filling, filtering, etc.
It is capable to deal with RGB (Red-Green-Blue) as well as with HSV (Hue-Luminance-Value) encoded color data.
Debounces the switches, determine the state and signal changes.
All the classes above are available here
In addition I borrowed the following two libraries from the open source community:
Rotary available here
Handles rotary controller in a solid manner
FastSPI_LED2 available here
Fast SPI interface to push the led data buffer to an attached ledstrip supporting different LED pwm controllers.
The figure illustrates which class is calling which other class. As shown the application is based on the Model-View-Controller pattern where the TLedStripShow and the Interrup Service Routine form the controller, TLedStrip the view and TLedEffect the model component.
One special point to mention is the use of the call back adapter. In order to build a reusable TTimer class I used a generic way to pass the callback routine rather than passing a member of an observer class and derive the calling classes from that one.
The implementation works and the design doesn’t look too strange (at least not to me). I can add and remove effects easily without breaking the design or the flow of the program. From this project I made some observations:
- The application became larger than expected (14kB) even there is no use of the floating point library
- The missing new and delete in the Arduino C++ flavour is limiting and has impact on the application design
- The way the Arduino IDE inserts automatically function prototypes and definitions can cause strange messages and errors
There also things I would do differently or I might enhance in future:
- Add the option to let TTimer be interrupt driven
- Add the option to let TSwitch be timer driven
- Try to use the observer pattern
Planned additions in functionality
- Add a factory reset function to erase the configuration
- Store the number of LEDs in the EEPROM and make it configurable
- Add new effects
- Make effects sensitive to audio events
- Make effects sensitive to surrounding light condition
- whatever you tell me or comes to my mind
If you are interested in more details how the code is made please consult the code which can be found here.