From fa144c9a87cd74776b24374443e104e004067c3c Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Tue, 10 Apr 2012 13:00:47 +1000 Subject: [PATCH] Support class for blinking LED's --- StarTrek/StarTrek.pde | 28 ++--- doc/Doxyfile | 2 +- libraries/BlinkLED/BlinkLED.cpp | 192 ++++++++++++++++++++++++++++++++ libraries/BlinkLED/BlinkLED.h | 55 +++++++++ libraries/BlinkLED/keywords.txt | 12 ++ 5 files changed, 270 insertions(+), 19 deletions(-) create mode 100644 libraries/BlinkLED/BlinkLED.cpp create mode 100644 libraries/BlinkLED/BlinkLED.h create mode 100644 libraries/BlinkLED/keywords.txt diff --git a/StarTrek/StarTrek.pde b/StarTrek/StarTrek.pde index d9af5110..aee6d15c 100644 --- a/StarTrek/StarTrek.pde +++ b/StarTrek/StarTrek.pde @@ -27,6 +27,8 @@ Nacelle lights with a 3 LED chase will have 4 LED's on each output - two in each nacelle. */ +#include + #define NAV_LIGHTS A2 // Red/green navigational lights #define STROBE_LIGHT A3 // Strobe light #define NACELLE_1 3 // Nacelle twirl chase LED 1 @@ -37,11 +39,10 @@ each nacelle. #define NACELLE_6 11 // Nacelle twirl chase LED 6 #define NACELLE_RATE A0 // Analog input that defines the rate of the nacelle chase -#define NAV_LIGHTS_PERIOD 2000 +#define NAV_LIGHTS_ON 1000 #define NAV_LIGHTS_OFF 1000 -#define STROBE_LIGHT_PERIOD 900 +#define STROBE_LIGHT_ON 70 #define STROBE_LIGHT_OFF 830 -#define NACELLE_PERIOD 500 #define NACELLE_MIN_PERIOD 25 #define NACELLE_MAX_PERIOD 250 #define NACELLE_DIM_VALUE 32 // Value for dimming previous LED in chase, 0..255 @@ -61,12 +62,11 @@ unsigned long lastNacelleTime = 0; unsigned long nacellePeriod = 0; byte index = 0; +BlinkLED navLights(NAV_LIGHTS, NAV_LIGHTS_ON, NAV_LIGHTS_OFF); +BlinkLED strobeLight(STROBE_LIGHT, STROBE_LIGHT_ON, STROBE_LIGHT_OFF); + void setup() { // Configure the outputs and set them to be initially LOW. - pinMode(NAV_LIGHTS, OUTPUT); - digitalWrite(NAV_LIGHTS, LOW); - pinMode(STROBE_LIGHT, OUTPUT); - digitalWrite(STROBE_LIGHT, LOW); for (int index = 0; index < nacelleChaseLen; ++index) { byte pin = nacelleChase[index]; pinMode(pin, OUTPUT); @@ -93,17 +93,9 @@ void loop() { // How long since the application started? unsigned long sinceStart = millis() - startTime; - // Update the navigation lights. - if ((sinceStart % NAV_LIGHTS_PERIOD) >= NAV_LIGHTS_OFF) - digitalWrite(NAV_LIGHTS, HIGH); - else - digitalWrite(NAV_LIGHTS, LOW); - - // Update the strobe light. - if ((sinceStart % STROBE_LIGHT_PERIOD) >= STROBE_LIGHT_OFF) - digitalWrite(STROBE_LIGHT, HIGH); - else - digitalWrite(STROBE_LIGHT, LOW); + // Update the navigation and strobe lights. + navLights.loop(); + strobeLight.loop(); // Update the nacelle lights - uniform LED chase of length 1 to 6. if ((sinceStart - lastNacelleTime) >= nacellePeriod) { diff --git a/doc/Doxyfile b/doc/Doxyfile index 8d69b2cf..6ef89ddd 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -610,7 +610,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../libraries/FreetronicsLCD . +INPUT = ../libraries/FreetronicsLCD ../libraries/BlinkLED . # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is diff --git a/libraries/BlinkLED/BlinkLED.cpp b/libraries/BlinkLED/BlinkLED.cpp new file mode 100644 index 00000000..3ff990a9 --- /dev/null +++ b/libraries/BlinkLED/BlinkLED.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2012 Southern Storm Software, Pty Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "BlinkLED.h" +#include + +/** + * \class BlinkLED BlinkLED.h + * \brief Blink a LED on a digital output pin. + * + * BlinkLED simplies the process of blinking a LED by encapsulating the + * control logic into a single class. The following example strobes the + * status LED on D13 with a period of 70 milliseconds on, 930 milliseconds off + * (the LED is initially off): + * + * \code + * #include + * + * BlinkLED statusBlink(13, 70, 930); + * + * void setup() {} + * + * void loop() { + * statusBlink.loop(); + * } + * \endcode + * + * The current state() of the LED can be changed immediately by calling + * setState(). The blink rate can be modified with setBlinkRate(). + * And the blink cycle can be suspended and restarted with pause() + * and resume(). + */ + +/** + * \brief Initialize a blinking LED on the specified \a pin. + * + * The LED will blink with a rate defined by \a onTime and \a offTime + * (in milliseconds). Initially the LED's state is given by \a initialState, + * where true means initially on and false means initially off. + */ +BlinkLED::BlinkLED(uint8_t pin, unsigned long onTime, unsigned long offTime, bool initialState) + : _pin(pin) + , _state(initialState) + , _paused(false) + , _onTime(onTime) + , _offTime(offTime) +{ + pinMode(pin, OUTPUT); + digitalWrite(pin, initialState ? HIGH : LOW); + _lastChange = millis(); +} + +/** + * Perform a single iteration of the blink loop for this LED. + */ +void BlinkLED::loop() +{ + if (_paused) + return; + unsigned long currentTime = millis(); + if (_state) { + if ((currentTime - _lastChange) >= _onTime) { + digitalWrite(_pin, LOW); + _lastChange += _onTime; + _state = false; + } + } else { + if ((currentTime - _lastChange) >= _offTime) { + digitalWrite(_pin, HIGH); + _lastChange += _offTime; + _state = true; + } + } +} + +/** + * \fn unsigned long BlinkLED::onTime() const + * \brief Returns the number of milliseconds the LED will be on. + * + * \sa offTime(), setBlinkRate() + */ + +/** + * \fn unsigned long BlinkLED::offTime() const + * \brief Returns the number of milliseconds the LED will be off. + * + * \sa onTime(), setBlinkRate() + */ + +/** + * \brief Sets the \a onTime and \a offTime (in milliseconds). + * + * The change takes effect immediately. If the current onTime() or + * offTime() has now expired, then the LED will immediately switch to + * the opposite state(). + * + * \sa onTime(), offTime() + */ +void BlinkLED::setBlinkRate(unsigned long onTime, unsigned long offTime) +{ + _onTime = onTime; + _offTime = offTime; +} + +/** + * \fn bool BlinkLED::state() const + * \brief Returns the current state of the LED; true is on, false is off. + * + * \sa setState() + */ + +/** + * \brief Sets the current \a state of the LED, where true is on, false is off. + * + * If the LED is already set to \a state, then it will complete its current + * cycle of onTime() or offTime(). Otherwise the LED is immediately set to + * \a state and a new cycle begins. + * + * \sa state() + */ + +void BlinkLED::setState(bool state) +{ + if (_state != state) { + digitalWrite(_pin, state ? HIGH : LOW); + _state = state; + _lastChange = millis(); + } +} + +/** + * \fn void BlinkLED::pause() + * \brief Pauses the LED blink cycle in its current state(). + * + * \sa resume(), isPaused() + */ + +/** + * \brief Resumes the LED blink cycle after a pause(). + * + * The LED will complete its current onTime() or offTime() and then + * will switch to the opposite state(). If onTime() or offTime() has + * already expired, then the LED will immediately switch state. + * + * \sa pause(), isPaused() + */ +void BlinkLED::resume() +{ + if (_paused) { + _paused = false; + unsigned long currentTime = millis(); + if (_state) { + if ((currentTime - _lastChange) >= _onTime) { + digitalWrite(_pin, LOW); + _lastChange = currentTime; + _state = false; + } + } else { + if ((currentTime - _lastChange) >= _offTime) { + digitalWrite(_pin, HIGH); + _lastChange = currentTime; + _state = true; + } + } + } +} + +/** + * \fn bool BlinkLED::isPaused() + * \brief Returns true if the LED blink cycle is paused; false otherwise. + * + * \sa pause(), resume() + */ diff --git a/libraries/BlinkLED/BlinkLED.h b/libraries/BlinkLED/BlinkLED.h new file mode 100644 index 00000000..da5b6dfc --- /dev/null +++ b/libraries/BlinkLED/BlinkLED.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 Southern Storm Software, Pty Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef BlinkLED_h +#define BlinkLED_h + +#include + +class BlinkLED +{ +public: + BlinkLED(uint8_t pin, unsigned long onTime, unsigned long offTime, bool initialState = false); + + void loop(); + + unsigned long onTime() const { return _onTime; } + unsigned long offTime() const { return _offTime; } + void setBlinkRate(unsigned long onTime, unsigned long offTime); + + bool state() const { return _state; } + void setState(bool state); + + void pause() { _paused = true; } + void resume(); + bool isPaused() const { return _paused; } + +private: + uint8_t _pin; + bool _state; + bool _paused; + unsigned long _onTime; + unsigned long _offTime; + unsigned long _lastChange; +}; + +#endif diff --git a/libraries/BlinkLED/keywords.txt b/libraries/BlinkLED/keywords.txt new file mode 100644 index 00000000..5b1365f3 --- /dev/null +++ b/libraries/BlinkLED/keywords.txt @@ -0,0 +1,12 @@ +BlinkLED KEYWORD1 + +onTime KEYWORD2 +offTime KEYWORD2 +setBlinkRate KEYWORD2 + +state KEYWORD2 +setState KEYWORD2 + +pause KEYWORD2 +resume KEYWORD2 +isPaused KEYWORD2