I defined a set of classes for controlling the LED lights. The base class is called Flasher which will cycle an LED on and off at a specified rate. The Pulser class will slowly brighten and dim an LED using a PWM output pin. Finally the RGB_Pulser class will work on a set of three PWM pins.
I use these classes to control the various lights as follows:
// Flasher ctor takes led, on perid and off period
Flasher builtin_led(LED_BUILTIN, 10, 1000); // flash power light at a steady interval
// Pulser ctor takes pin, interval, maxValue, initial, increment, offset
Pulser roof_light(ROOF_LIGHT, 5, 63, 20, 10, 0);
//Flasher roof_light(ROOF_LIGHT, 100, 50);
//Pulser cabinet_light(CABINET_LIGHT, 5, 63, 20, 10, 0);
Flasher cabinet_light(CABINET_LIGHT);
// RGB_Pulser ctor takes pins for red green and blue
RGB_Pulser sign_color(SIGN_RED_LED, SIGN_GREEN_LED, SIGN_BLUE_LED);
// Flasher -- based on tutorial from Adafruit
// https://learn.adafruit.com/multi-tasking-the-arduino-part-1
#ifndef _Flasher_h_
#define _Flasher_h_
#define FLASHER_VERSION "$Id: Flasher.h 2 2018-08-29 07:08:22Z cafelizardo $"
enum { DISABLED = -1, OFF=LOW, ON=HIGH } LED_STATE;
class Flasher
{
protected:
// configuration variables
int ledPin; // number of the LED pin
long onTime; // milliseconds of on-time
long offTime; // milliseconds of off-time
bool inverted; // invert output
// state variables
int ledState; // current value: DISABLED, OFF or ON
unsigned long previousMillis; // last time LED was last updated
public:
// constructor -- creates a Flasher object
// and initialized the member variables and state
Flasher(int pin = 0, long on = 0, long off = 0)
{
this->ledPin = pin;
pinMode(ledPin, OUTPUT);
this->onTime = on;
this->offTime = off;
this->inverted = false;
this->ledState = OFF;
this->previousMillis = 0;
} // ctor
// modifiers
Flasher& setOnTime(long onTime) {
this->onTime = onTime;
return *this;
}
Flasher& setOffTime(long offTime) {
this->offTime = offTime;
return *this;
}
Flasher& setInvert(bool invert) {
this->inverted = invert;
return *this;
}
virtual Flasher& output(int value)
{
if (this->ledState == DISABLED) {
digitalWrite(this->ledPin, this->inverted ? HIGH : LOW);
} else {
digitalWrite(this->ledPin, constrain(this->inverted ? 255 - value : value, 0, 255) );
}
return *this;
}
virtual Flasher& output()
{
//Serial.print("Flasher.output "); Serial.print(this->ledPin, DEC); Serial.println("");
this->output(this->ledState);
return *this;
}
virtual Flasher& disable() {
//Serial.print("disabling "); Serial.print(this->ledPin, DEC); Serial.println("");
this->ledState = DISABLED;
this->output();
return *this;
}
virtual Flasher& enable() {
//Serial.print("enabling "); Serial.print(this->ledPin, DEC); Serial.println("");
this->ledState = OFF;
this->previousMillis = 0;
this->output();
return *this;
}
virtual Flasher& update()
{
if (this->ledState == DISABLED) return *this;
//Serial.print("flasher update "); Serial.print(this->ledPin, DEC); Serial.println("");
// check to see if it's tme to change the state of the LED
unsigned long currentMillis = millis();
bool toggle = false;
if ( (this->ledState == ON) && (currentMillis - this->previousMillis >= this->onTime) )
toggle = true;
else if ( (this->ledState == OFF) && (currentMillis - this->previousMillis >= this->offTime) )
toggle = true;
if (toggle)
{
this->ledState = !this->ledState;
this->output();
this->previousMillis = currentMillis;
}
return *this;
} // update
}; // class Flasher
#endif // _flasher_h_
// Pulser -- extends Flasher by gradually increasing brightness then back down again
// initial version using cosine function.
#ifndef _Pulser_h_
#define _Pulser_h_
#include "Flasher.h"
#define PULSER_VERSION "$Id: Pulser.h 9 2018-10-01 07:19:06Z cafelizardo $"
class Pulser : public Flasher
{
long interval;
long offset; // offset to be applied after computing value to force clipping either low or high
long increment; // increment on step_angle
long maxValue; // max brightness
int step_angle;
public:
// constructor -- creates a Pulser object
Pulser() : Flasher() {}
Pulser(int pin, long interval = 0, long maxValue = 255, long initial = 0, long increment = 1, long offset = 0)
: Flasher(pin, interval, offset)
{
this->interval = interval;
this->offset = offset;
this->increment = max(1, increment);
this->maxValue = maxValue;
this->step_angle = initial;
} // ctor
// modifiers
Pulser& setInterval(long interval) {
this->interval = interval;
return *this;
}
Pulser& setMaxValue(long maxValue) {
this->maxValue = maxValue;
return *this;
}
Pulser& setInitial(long initial) {
this->step_angle = initial;
return *this;
}
Pulser& setIncrement(long increment) {
this->increment = increment;
return *this;
}
Pulser& setOffset(long offset) {
this->offset = offset;
return *this;
}
virtual Pulser& output(int value)
{
//Serial.print("Pulser.output "); Serial.print(this->ledPin, DEC); Serial.print(" "); Serial.print(value, HEX); Serial.println("");
if (this->ledState == DISABLED) {
digitalWrite(this->ledPin, this->inverted ? HIGH : LOW);
} else {
analogWrite(this->ledPin, constrain(this->inverted ? 255 - value : value, 0, 255) );
}
return *this;
}
virtual Pulser& output()
{
//Serial.print("Pulser.output "); Serial.print(this->ledPin, DEC); Serial.print(" ledState="); Serial.print(this->ledState, DEC); Serial.println("");
this->output(this->ledState);
return *this;
}
// update -- uses sin function to slowly ramp up and down
virtual Pulser& update()
{
if (this->ledState == DISABLED) return *this;
//Serial.print("pulser update "); Serial.print(this->ledPin, DEC); Serial.print(" ledState="); Serial.print(this->ledState, DEC); Serial.println("");
// get current time
unsigned long currentMillis = millis();
if ( currentMillis - this->previousMillis >= this->interval )
{
//convert 0-360 angle to radian (needed for cos function)
float rad = DEG_TO_RAD * this->step_angle + this->offTime;
//calculate cosine of angle as number between 0 and maxvalue
this->ledState = constrain((-cos(rad) * this->maxValue + this->maxValue) + this->offset, 0, this->maxValue);
this->step_angle += this->increment;
while (this->step_angle > 360) step_angle -= 360;
this->previousMillis = currentMillis;
}
this->output();
return *this;
} // update
virtual int step(const int dir = 1)
{
this->ledState += dir;
if (this->ledState > this->maxValue) this->ledState = this->maxValue;
if (this->ledState < 0) this->ledState = 0;
this->output();
return this->ledState;
} // step
}; // class Pulser
#endif // _Pulser_h
// RGB_Pulser -- combines 3 Pulser's which extends the basic Flasher interface
#ifndef _RGB_Pulser_h_
#define _RGB_Pulser_h_
#include "Flasher.h"
#include "Pulser.h"
#define RGB_PULSER_VERSION "$Id: RGB_Pulser.h 9 2018-10-01 07:19:06Z cafelizardo $"
class RGB_Pulser : public Pulser
{
Pulser *red_led, *green_led, *blue_led;
public:
// ctor
RGB_Pulser(int red_pin, int green_pin, int blue_pin, int interval = 0, int maxValue = 255)
{
this->red_led = new Pulser(red_pin, interval, maxValue);
this->green_led = new Pulser(green_pin, interval, maxValue);
this->blue_led = new Pulser(blue_pin, interval, maxValue);
}
// access functions for Pulser objects
Pulser* red() { return this->red_led; }
Pulser* green() { return this->green_led; }
Pulser* blue() { return this->blue_led; }
virtual RGB_Pulser& output(int red, int green, int blue) {
this->red_led->output(red);
this->green_led->output(blue);
this->blue_led->output(green);
}
virtual RGB_Pulser& output(long rgb) {
#if 0
Serial.print(F("RGB_Pulser.output "));
Serial.print(rgb, HEX); Serial.print(F(" "));
Serial.print((rgb & 0xff0000) >> 16, HEX); Serial.print(F(" "));
Serial.print((rgb & 0x00ff00) >> 8, 16); Serial.print(F(" "));
Serial.print(rgb & 0x0000ff, 16);
Serial.println();
#endif
this->red_led->output((rgb & 0xff0000) >> 16);
this->green_led->output((rgb & 0x00ff00) >> 8);
this->blue_led->output(rgb & 0x0000ff);
return *this;
}
virtual RGB_Pulser& disable() {
Serial.println("RGB_light.disable ");
this->red_led->disable(); this->red_led->output(255);
this->green_led->disable(); this->green_led->output(255);
this->blue_led->disable(); this->blue_led->output(255);
return *this;
}
virtual RGB_Pulser& enable() {
Serial.println("RGB_light.enable ");
this->red_led->enable();
this->green_led->enable();
this->blue_led->enable();
return *this;
}
virtual RGB_Pulser& update()
{
//Serial.println("RGB_light.update ");
this->red_led->update();
this->green_led->update();
this->blue_led->update();
return *this;
}
}; // class RGB_Pulser
#endif // _RGB_Pulser_h
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.