Firefly Lantern
A glowy Arduino + TLC5940 decoration/convention prop
Description
A portable lantern running off a standard 9V battery that simulates glowing fireflies. Four different modes accessible by a pushbutton switch enable dimming and calmer fireflies.
The Finished Lantern
The Innards
The Code
/*
* Added button to pin 0 to change modes -- writes to EEPROM to preserve setting during power loss.
*/
#include "Tlc5940.h"
#include <EEPROM.h>
#define NO_OF_PINS 16
#define buttonPin 0
#define EEPROMlocation 1
int mode;
int maxMode = 3;
void setup() {
Tlc.init(0); // Initiates the TLC5940 and set all channels off
pinMode(buttonPin, INPUT);
}
void loop() {
mode = EEPROM.read(EEPROMlocation);
if ((mode < 0) || (mode > maxMode)) {
EEPROM.write(EEPROMlocation, 0);
mode = 0;
}
int buttonState;
int MAX_LED_BRIGHTNESS = 4095; // 4095
int MAX_FADERS = 16; // 16
int MIN_IDLE_BRIGHTNESS = 50; // 0
int MAX_IDLE_BRIGHTNESS = 300; // 300
int brightnessUpDelta = 300; // 300
int brightnessDownDelta = 100; // 100
int activeFaders = 0; // 0
int wiggleLethargy = 50; // 50
int fireflySleepinessLevel = 20; // 15
bool flare = true;
int outputPins[NO_OF_PINS] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int brightness[NO_OF_PINS] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
int fadeState[NO_OF_PINS] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 0 = idle, 1 = fade down, 2 = fade up, 3 = idle down, 4 = idle up
// Set initial brightness to random
for(int i = 0; i < NO_OF_PINS; i++) {
brightness[i] = random(MIN_IDLE_BRIGHTNESS, MAX_IDLE_BRIGHTNESS);
}
while (true) {
buttonState = digitalRead(buttonPin);
// Increment our mode
if (buttonState == LOW) // button pressed
{
if (mode == maxMode) {mode = 0;}
else {mode++;}
EEPROM.write(EEPROMlocation, mode);
delay(500);
for(int i = 0; i < NO_OF_PINS; i++) {
brightness[i] = 1;
}
}
switch (mode) { // These are all the lighting profiles you can switch to.
case 0: // Full brightness with firefly "flares"
MAX_LED_BRIGHTNESS = 4095; // 4095
MAX_FADERS = 16; // 16
MIN_IDLE_BRIGHTNESS = 50; // 0
MAX_IDLE_BRIGHTNESS = 300; // 300
brightnessUpDelta = 300; // 300
brightnessDownDelta = 100; // 100
activeFaders = 0; // 0
wiggleLethargy = 50; // 50
fireflySleepinessLevel = 20; // 15
flare = true;
break;
case 1: // Around half brightness with firefly "flares"
MAX_LED_BRIGHTNESS = 300; // 4095
MAX_FADERS = 16; // 16
MIN_IDLE_BRIGHTNESS = 50; // 0
MAX_IDLE_BRIGHTNESS = 300; // 300
brightnessUpDelta = 30; // 300
brightnessDownDelta = 10; // 100
activeFaders = 0; // 0
wiggleLethargy = 100; // 50
fireflySleepinessLevel = 50; // 15
flare = true;
break;
case 2: // Full brightness with light "warble", no flares.
MAX_LED_BRIGHTNESS = 4095; // 4095
MAX_FADERS = 16; // 16
MIN_IDLE_BRIGHTNESS = 50; // 0
MAX_IDLE_BRIGHTNESS = 700; // 300
brightnessUpDelta = 300; // 300
brightnessDownDelta = 100; // 100
activeFaders = 0; // 0
wiggleLethargy = 50; // 50
fireflySleepinessLevel = 20; // does not apply here as 'flare' is false
flare = false;
break;
case 3: // Half brightness with light "warble", no flares.
MAX_LED_BRIGHTNESS = 300; // 4095
MAX_FADERS = 16; // 16
MIN_IDLE_BRIGHTNESS = 50; // 0
MAX_IDLE_BRIGHTNESS = 300; // 300
brightnessUpDelta = 30; // 300
brightnessDownDelta = 10; // 100
activeFaders = 0; // 0
wiggleLethargy = 100; // 50
fireflySleepinessLevel = 100; // does not apply here as 'flare' is false
flare = false;
break;
}
// Random selection
if (activeFaders < MAX_FADERS) {
int selectAPin = random(0,fireflySleepinessLevel);
if (selectAPin == 1) {
int randomPin = random(0, NO_OF_PINS);
if (fadeState[randomPin] == 0 || fadeState[randomPin] == 4) {
fadeState[randomPin] = 2;
activeFaders = activeFaders + 1;
}
}
}
for(int i = 0; i < NO_OF_PINS; i++) {
switch (fadeState[i]) {
case 0: // Idle
if (random(0,wiggleLethargy) == 1) {
fadeState[i] = 4;
}
break;
case 1: // Fade down
if (flare) {
if (brightness[i] <= MIN_IDLE_BRIGHTNESS) { // At the bottom!
fadeState[i] = 0;
activeFaders = activeFaders - 1;
}
else {
brightness[i] = brightness[i] - brightnessDownDelta;
if (brightness[i] < MIN_IDLE_BRIGHTNESS) {
brightness[i] = MIN_IDLE_BRIGHTNESS;
}
}
}
break;
case 2: // Fade up
if (flare) {
if (brightness[i] >= MAX_LED_BRIGHTNESS) { // Maxed out!
fadeState[i] = 1;
}
else {
brightness[i] = brightness[i] + brightnessUpDelta;
if (brightness[i] > MAX_LED_BRIGHTNESS) {
brightness[i] = MAX_LED_BRIGHTNESS;
}
}
}
break;
case 3: // Idle down
if (brightness[i] <= MIN_IDLE_BRIGHTNESS) {
fadeState[i] = 0;
}
else {
brightness[i] = brightness[i] - 1;
}
break;
case 4: // Idle up
if (brightness[i] >= MAX_IDLE_BRIGHTNESS) {
fadeState[i] = 3;
}
else {
brightness[i] = brightness[i] + 1;
}
break;
}
Tlc.set(outputPins[i], brightness[i]);
Tlc.update();
delay(1);
}
}
}
Last modified on 2022-05-11