1 //neopixel flame effect from https://github.com/schnoggo/jack-o-candle
2 //everything else, do as you wish at your own risk
4 #include <Adafruit_NeoPixel.h>
11 #define NUMBER_OF_FLAMES 7
13 #define FLICKER_CHANCE 3
16 unsigned long ledstringtimer;
17 unsigned long previousMillis = 0;
19 Adafruit_NeoPixel strip = Adafruit_NeoPixel(14, PIN, NEO_GRB + NEO_KHZ800);
21 uint32_t rez_range = 256*3;
30 } flames[NUMBER_OF_FLAMES];
32 int new_brightness = 0;
33 unsigned long rgb[3]; //reusable temporary array
34 uint8_t scaleD_rgb[3];
37 #define SCALERVAL 256*3
38 const int flamecolors[22][3] = {
47 { SCALERVAL, SCALERVAL*.4, },
48 { SCALERVAL, SCALERVAL*.4, 0},
49 { SCALERVAL, SCALERVAL*.4, 0},
50 { SCALERVAL, SCALERVAL*.4, 0},
51 { SCALERVAL, SCALERVAL*.3, 0},
52 { SCALERVAL, SCALERVAL*.3, 0},
53 { SCALERVAL, SCALERVAL*.3, 0},
54 { SCALERVAL, SCALERVAL*.3, 0},
55 { SCALERVAL, SCALERVAL*.3, 0},
56 { SCALERVAL, SCALERVAL*.3, 0},
57 { SCALERVAL, SCALERVAL*.3, },
58 { SCALERVAL, SCALERVAL*.3, SCALERVAL}, // white
59 { 0, SCALERVAL*.2, SCALERVAL}, // that one blue flame
60 { SCALERVAL, SCALERVAL*.3, SCALERVAL*.5}
65 ledstringtimer = millis() + 5000;
67 strip.show(); // Initialize all pixels to 'off'
68 randomSeed(analogRead(0));
74 if (((signed long)(millis() - ledstringtimer)) > 0) {
76 ledstringtimer = millis() + 3000;
77 long dice = random(1000);
80 } else if (dice<100) {
89 unsigned long currentMillis = millis();
90 while (fadeValue <= fade) {
91 currentMillis = millis();
92 if (currentMillis - previousMillis >= 30) {
93 previousMillis = currentMillis;
95 analogWrite(PWM, fadeValue);
99 while (fadeValue > 0) {
100 currentMillis = millis();
101 if (currentMillis - previousMillis >= 30) {
102 previousMillis = currentMillis;
104 analogWrite(PWM, fadeValue);
111 for(uint16_t t=0; t<255; t++) {
112 for (uint16_t i=0; i<strip.numPixels(); i++) {
113 strip.setPixelColor(i, strip.Color(0, t, 0));
118 for(uint16_t t=255; t>0; t--) {
119 for (uint16_t i=0; i<strip.numPixels(); i++) {
120 strip.setPixelColor(i, strip.Color(0, t, 0));
128 for(uint16_t t=0; t<255; t++) {
129 for (uint16_t i=0; i<strip.numPixels(); i++) {
130 strip.setPixelColor(i, strip.Color(t, 0, 0));
135 for(uint16_t t=255; t>0; t--) {
136 for (uint16_t i=0; i<strip.numPixels(); i++) {
137 strip.setPixelColor(i, strip.Color(t, 0, 0));
145 for(byte flame_count=0; flame_count<NUMBER_OF_FLAMES; flame_count++) {
146 switch(flames[flame_count].state){
148 CreateNewFlame(flame_count);
152 new_brightness = flames[flame_count].brightness + flames[flame_count].step;
153 if (new_brightness > flames[flame_count].max_brightness){
154 UpdateFlameColor(flame_count, flames[flame_count].max_brightness);
155 flames[flame_count].brightness = flames[flame_count].max_brightness;
156 flames[flame_count].step = GetStepSize(); // pick a different speed for flame going out
157 flames[flame_count].state = 2;
159 UpdateFlameColor(flame_count, new_brightness);
160 flames[flame_count].brightness = new_brightness;
166 new_brightness = flames[flame_count].brightness - flames[flame_count].step;
167 // chance to flicker/rekindle:
168 if (random(new_brightness) < FLICKER_CHANCE){
170 flames[flame_count].state = 1; //increase again
171 flames[flame_count].brightness = max(GetMaxBrightness(), flames[flame_count].brightness);
172 flames[flame_count].step = GetStepSize();
174 if (new_brightness <1){
175 flames[flame_count].state = 0; // bottomed out - reset to next flame
176 flames[flame_count].brightness = 0;
177 UpdateFlameColor(flame_count, 0);
179 UpdateFlameColor(flame_count, new_brightness);
180 flames[flame_count].brightness = new_brightness;
190 for(byte i=0; i<NUMBER_OF_FLAMES; i++) {
195 void UpdateFlameColor(byte flame_num, int new_brightness){
197 uint32_t color_channel_value;
200 new_brightness = min(new_brightness, flames[flame_num].max_brightness);
202 for(byte rgb_channel=0; rgb_channel<3; rgb_channel++) {
203 color_channel_value = flames[flame_num].rgb[rgb_channel];
204 color_channel_value = color_channel_value * (uint32_t)new_brightness; // keep it long
205 color_channel_value = color_channel_value/(uint32_t)rez_range;
206 rgb[rgb_channel] = max(0L,color_channel_value);
207 } // step through R G B
209 // spread possible values of 0 -768 across 3 pixels
210 for(byte sub_pixel=0; sub_pixel<FLAME_WIDTH; sub_pixel++) {
211 for(byte i=0; i<3; i++) { // rgb
219 c = strip.Color(scaleD_rgb[0],scaleD_rgb[1], scaleD_rgb[2]);
220 strip.setPixelColor(flame_num * FLAME_WIDTH + sub_pixel, c);
224 void CreateNewFlame(byte flame_num){
225 flames[flame_num].step = GetStepSize();
226 flames[flame_num].max_brightness = GetMaxBrightness();
227 flames[flame_num].brightness = 0;
228 flames[flame_num].state = 1;
229 byte color_index = random(22);
230 for(byte i=0; i<3; i++) {
231 flames[flame_num].rgb[i] = flamecolors[color_index][i];
239 int GetMaxBrightness(){
241 retVal = random(rez_range/2) + rez_range/2;