Tested and Runs on Gemma M0 - Ported to CircuitPython
This commit is contained in:
parent
b2ce1ae854
commit
ca538a8381
5 changed files with 296 additions and 0 deletions
BIN
LED_Candles/LED_Candles-fritzing.png
Normal file
BIN
LED_Candles/LED_Candles-fritzing.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
BIN
LED_Candles/LED_Candles.fzz
Normal file
BIN
LED_Candles/LED_Candles.fzz
Normal file
Binary file not shown.
165
LED_Candles/LED_Candles.ino
Normal file
165
LED_Candles/LED_Candles.ino
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
#include <Adafruit_NeoPixel.h>
|
||||
|
||||
// The onboard red LED's pin
|
||||
#define REDLED_PIN 1
|
||||
// The data-in pin of the NeoPixel
|
||||
#define WICK_PIN 0
|
||||
// Any unconnected pin, to try to generate a random seed
|
||||
#define UNCONNECTED_PIN 2
|
||||
|
||||
// The LED can be in only one of these states at any given time
|
||||
#define BRIGHT 0
|
||||
#define UP 1
|
||||
#define DOWN 2
|
||||
#define DIM 3
|
||||
|
||||
#define BRIGHT_HOLD 4
|
||||
#define DIM_HOLD 5
|
||||
|
||||
// Percent chance the LED will suddenly fall to minimum brightness
|
||||
#define INDEX_BOTTOM_PERCENT 10
|
||||
// Absolute minimum red value (green value is a function of red's value)
|
||||
#define INDEX_BOTTOM 128
|
||||
// Minimum red value during "normal" flickering (not a dramatic change)
|
||||
#define INDEX_MIN 192
|
||||
// Maximum red value
|
||||
#define INDEX_MAX 255
|
||||
|
||||
// Decreasing brightness will take place over a number of milliseconds in this range
|
||||
#define DOWN_MIN_MSECS 20
|
||||
#define DOWN_MAX_MSECS 250
|
||||
// Increasing brightness will take place over a number of milliseconds in this range
|
||||
#define UP_MIN_MSECS 20
|
||||
#define UP_MAX_MSECS 250
|
||||
// Percent chance the color will hold unchanged after brightening
|
||||
#define BRIGHT_HOLD_PERCENT 20
|
||||
// When holding after brightening, hold for a number of milliseconds in this range
|
||||
#define BRIGHT_HOLD_MIN_MSECS 0
|
||||
#define BRIGHT_HOLD_MAX_MSECS 100
|
||||
// Percent chance the color will hold unchanged after dimming
|
||||
#define DIM_HOLD_PERCENT 5
|
||||
// When holding after dimming, hold for a number of milliseconds in this range
|
||||
#define DIM_HOLD_MIN_MSECS 0
|
||||
#define DIM_HOLD_MAX_MSECS 50
|
||||
|
||||
#define MINVAL(A,B) (((A) < (B)) ? (A) : (B))
|
||||
#define MAXVAL(A,B) (((A) > (B)) ? (A) : (B))
|
||||
|
||||
Adafruit_NeoPixel *wick;
|
||||
byte state;
|
||||
unsigned long flicker_msecs;
|
||||
unsigned long flicker_start;
|
||||
byte index_start;
|
||||
byte index_end;
|
||||
|
||||
void set_color(byte index)
|
||||
{
|
||||
index = MAXVAL(MINVAL(index, INDEX_MAX), INDEX_BOTTOM);
|
||||
if (index >= INDEX_MIN)
|
||||
wick->setPixelColor(0, index, (index * 3) / 8, 0);
|
||||
else if (index < INDEX_MIN)
|
||||
wick->setPixelColor(0, index, (index * 3.25) / 8, 0);
|
||||
|
||||
wick->show();
|
||||
return;
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
// There is no good source of entropy to seed the random number generator,
|
||||
// so we'll just read the analog value of an unconnected pin. This won't be
|
||||
// very random either, but there's really nothing else we can do.
|
||||
//
|
||||
// True randomness isn't strictly necessary, we just don't want a whole
|
||||
// string of these things to do exactly the same thing at the same time if
|
||||
// they're all powered on simultaneously.
|
||||
randomSeed(analogRead(UNCONNECTED_PIN));
|
||||
|
||||
// Turn off the onboard red LED
|
||||
pinMode(REDLED_PIN, OUTPUT);
|
||||
digitalWrite(REDLED_PIN, LOW);
|
||||
|
||||
wick = new Adafruit_NeoPixel(1, WICK_PIN, NEO_RGB + NEO_KHZ800);
|
||||
// wick = new Adafruit_NeoPixel(1, WICK_PIN); // for RGBW, if you see green uncomment this line
|
||||
|
||||
wick->begin();
|
||||
wick->show();
|
||||
|
||||
set_color(255);
|
||||
index_start = 255;
|
||||
index_end = 255;
|
||||
state = BRIGHT;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
unsigned long current_time;
|
||||
|
||||
current_time = millis();
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case BRIGHT:
|
||||
flicker_msecs = random(DOWN_MAX_MSECS - DOWN_MIN_MSECS) + DOWN_MIN_MSECS;
|
||||
flicker_start = current_time;
|
||||
index_start = index_end;
|
||||
if ((index_start > INDEX_BOTTOM) &&
|
||||
(random(100) < INDEX_BOTTOM_PERCENT))
|
||||
index_end = random(index_start - INDEX_BOTTOM) + INDEX_BOTTOM;
|
||||
else
|
||||
index_end = random(index_start - INDEX_MIN) + INDEX_MIN;
|
||||
|
||||
state = DOWN;
|
||||
break;
|
||||
case DIM:
|
||||
flicker_msecs = random(UP_MAX_MSECS - UP_MIN_MSECS) + UP_MIN_MSECS;
|
||||
flicker_start = current_time;
|
||||
index_start = index_end;
|
||||
index_end = random(INDEX_MAX - index_start) + INDEX_MIN;
|
||||
state = UP;
|
||||
break;
|
||||
case BRIGHT_HOLD:
|
||||
case DIM_HOLD:
|
||||
if (current_time >= (flicker_start + flicker_msecs))
|
||||
state = (state == BRIGHT_HOLD) ? BRIGHT : DIM;
|
||||
|
||||
break;
|
||||
case UP:
|
||||
case DOWN:
|
||||
if (current_time < (flicker_start + flicker_msecs))
|
||||
set_color(index_start + ((index_end - index_start) * (((current_time - flicker_start) * 1.0) / flicker_msecs)));
|
||||
else
|
||||
{
|
||||
set_color(index_end);
|
||||
|
||||
if (state == DOWN)
|
||||
{
|
||||
if (random(100) < DIM_HOLD_PERCENT)
|
||||
{
|
||||
flicker_start = current_time;
|
||||
flicker_msecs = random(DIM_HOLD_MAX_MSECS - DIM_HOLD_MIN_MSECS) + DIM_HOLD_MIN_MSECS;
|
||||
state = DIM_HOLD;
|
||||
}
|
||||
else
|
||||
state = DIM;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (random(100) < BRIGHT_HOLD_PERCENT)
|
||||
{
|
||||
flicker_start = current_time;
|
||||
flicker_msecs = random(BRIGHT_HOLD_MAX_MSECS - BRIGHT_HOLD_MIN_MSECS) + BRIGHT_HOLD_MIN_MSECS;
|
||||
state = BRIGHT_HOLD;
|
||||
}
|
||||
else
|
||||
state = BRIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
127
LED_Candles/LED_Candles.py
Normal file
127
LED_Candles/LED_Candles.py
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
import board
|
||||
import neopixel
|
||||
import time
|
||||
from analogio import AnalogIn
|
||||
|
||||
try:
|
||||
import urandom as random
|
||||
except ImportError:
|
||||
import random
|
||||
|
||||
wick_pin = board.D0 # The data-in pin of the NeoPixel
|
||||
unconnected_pin = board.A0 # Any unconnected pin, to try to generate a random seed
|
||||
|
||||
# The LED can be in only one of these states at any given time
|
||||
bright = 0
|
||||
up = 1
|
||||
down = 2
|
||||
dim = 3
|
||||
bright_hold = 4
|
||||
dim_hold = 5
|
||||
|
||||
index_bottom_percent = 10 # Percent chance the LED will suddenly fall to minimum brightness
|
||||
index_bottom = 128 # Absolute minimum red value (green value is a function of red's value)
|
||||
index_min = 192 # Minimum red value during "normal" flickering (not a dramatic change)
|
||||
index_max = 255 # Maximum red value
|
||||
|
||||
# Decreasing brightness will take place over a number of milliseconds in this range
|
||||
down_min_msecs = 20
|
||||
down_max_msecs = 250
|
||||
|
||||
# Increasing brightness will take place over a number of milliseconds in this range
|
||||
up_min_msecs = 20
|
||||
up_max_msecs = 250
|
||||
|
||||
# Percent chance the color will hold unchanged after brightening
|
||||
bright_hold_percent = 20
|
||||
|
||||
# When holding after brightening, hold for a number of milliseconds in this range
|
||||
bright_hold_min_msecs = 0
|
||||
bright_hold_max_msecs = 100
|
||||
|
||||
# Percent chance the color will hold unchanged after dimming
|
||||
dim_hold_percent = 5
|
||||
|
||||
# When holding after dimming, hold for a number of milliseconds in this range
|
||||
dim_hold_min_msecs = 0
|
||||
dim_hold_max_msecs = 50
|
||||
|
||||
numpix = 1 # Number of NeoPixels
|
||||
pixpin = board.D0 # Pin where NeoPixels are connected
|
||||
strip = neopixel.NeoPixel(pixpin, numpix, brightness=1, auto_write=True) # initialize strip
|
||||
|
||||
# Random number generator is seeded from an unused 'floating'
|
||||
# analog input - this helps ensure the random color choices
|
||||
# aren't always the same order.
|
||||
pin = AnalogIn(unconnected_pin)
|
||||
random.seed(pin.value)
|
||||
pin.deinit()
|
||||
|
||||
index_start = 255
|
||||
index_start = 255
|
||||
index_end = 255
|
||||
state = bright
|
||||
|
||||
def set_color(index):
|
||||
index = max(min(index,index_max), index_bottom)
|
||||
if ( index >= index_min ):
|
||||
strip[0] = [index, int ( (index * 3) / 8 ), 0]
|
||||
elif ( index < index_min ):
|
||||
strip[0] = [index, int ( (index * 3.25) / 8 ) , 0]
|
||||
|
||||
set_color(255)
|
||||
|
||||
while True:
|
||||
|
||||
current_time = time.monotonic()
|
||||
|
||||
# BRIGHT
|
||||
if ( state == bright ):
|
||||
flicker_msecs = random.randint(0, down_max_msecs - down_min_msecs) + down_min_msecs
|
||||
flicker_start = current_time
|
||||
index_start = index_end
|
||||
|
||||
if (( index_start > index_bottom ) and ( random.randint(0, 100) < index_bottom_percent)):
|
||||
index_end = random.randint(0, index_start - index_bottom) + index_bottom
|
||||
else:
|
||||
index_end = random.randint(0, index_start - index_min) + index_min
|
||||
|
||||
state = down
|
||||
|
||||
# DIM
|
||||
elif ( state == dim ):
|
||||
flicker_msecs = random.randint(0, up_max_msecs - up_min_msecs) + up_min_msecs
|
||||
flicker_start = current_time
|
||||
index_start = index_end
|
||||
index_end = random.randint(0, (index_max - index_start) ) + index_min
|
||||
state = down
|
||||
|
||||
# DIM_HOLD
|
||||
elif ( state == dim_hold ):
|
||||
if (current_time >= ( flicker_start + ( flicker_msecs / 1000) ) ): # dividing flicker_msecs by 1000 to convert to milliseconds
|
||||
if ( state == bright_hold ):
|
||||
state = bright
|
||||
else:
|
||||
state = dim
|
||||
|
||||
# DOWN
|
||||
elif ( state == down ):
|
||||
if (current_time < (flicker_start + ( flicker_msecs / 1000 ) )): # dividing flicker_msecs by 1000 to convert to milliseconds
|
||||
set_color(index_start + int ( ((index_end - index_start) * (((current_time - flicker_start) * 1.0) / flicker_msecs))) )
|
||||
else:
|
||||
set_color(index_end)
|
||||
|
||||
if (state == down):
|
||||
if (random.randint(0,100) < dim_hold_percent):
|
||||
flicker_start = current_time
|
||||
flicker_msecs = random.randint(0, dim_hold_max_msecs - dim_hold_min_msecs) + dim_hold_min_msecs
|
||||
state = dim_hold
|
||||
else:
|
||||
state = dim
|
||||
else:
|
||||
if (random.randint(0,100) < bright_hold_percent):
|
||||
flicker_start = current_time
|
||||
flicker_msecs = random.randint(0, bright_hold_max_msecs - bright_hold_min_msecs) + bright_hold_min_msecs
|
||||
state = bright_hold
|
||||
else:
|
||||
state = bright
|
||||
4
LED_Candles/README.md
Normal file
4
LED_Candles/README.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# LED_Candles
|
||||
|
||||
Code to accompany this tutorial:
|
||||
https://learn.adafruit.com/led-candles-simple-easy-cheap
|
||||
Loading…
Reference in a new issue