Arduino项目|仿真蜡烛
“Keith's Test Garage”想要一支LED蜡烛。虽然已经有了一些很逼真的项目,而且很容易找到,但他正在寻找更像实际的东西,经过几年的工作后,他们想出了一个相当惊人的复制品。
该设备的蜡嵌入式玻璃外壳内装有Arduino,内置一系列六个RGBW LED,随机闪烁以模拟火焰。
https://v.qq.com/x/page/q0851j3uiqu.html
下面把原作者的相关代码和连线图分享出来了
代码:
<p>// FIRST TEST OF MIC AND FLAME SENSOR<br>// Keith Kelly 2019-03-04 <a href="http://www.KeithsTestGarage.com"> www.KeithsTestGarage.com
</a>
// Milestone 1 of 3</p><p>#define MIC_PIN A1 // Microphone Pin
#define FLAME_PIN A3 // IR Sensor Pin</p><p>#define FLAME_DURATION 2000 // millis- duration of flame before lighting candle
#define FLAME_THRESHOLD 800 // 0...1023 - analog reading of FLAME value to detect
#define MIC_THRESHOLD 950 // 0...1023 - analog reading of MIC value to detect</p><p>// Vars to keep track of things
bool smoking = false;
bool flaming = false;</p><p>bool lit = false;
int flame_val = 0;
int mic_val = 0;</p><p>// Vars for tracking pseudo-async times
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long flameStartedMillis = 0; // will store last time LED was updated</p><p>void setup(){</p><p> Serial.begin(9600); // uncomment this to figure sensor readings.</p><p> // initialize pins
pinMode(FLAME_PIN, INPUT);
pinMode(MIC_PIN, INPUT);
pinMode(LED_BUILTIN, OUTPUT); </p><p> digitalWrite(LED_BUILTIN, LOW); // Turn OFF built-in LED</p><p> blowOutCandle();// Make sure candle is off (but don't smoke)</p><p>}</p><p>void loop(){
checkSensors(); // Check for fire and strong winds
}</p><p>// Checks for fire and strong winds every 50 milliseconds
void checkSensors(){
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 50) { // only check every 50ms
flame_val = analogRead( FLAME_PIN );
mic_val = analogRead( MIC_PIN );
previousMillis = currentMillis;
//Uncomment below to check sensor readings.
Serial.print(mic_val);
Serial.print(" : ");
Serial.println(flame_val);
}</p><p>if (lit && mic_val > MIC_THRESHOLD){ // MIC REGISTERED SOUND.BLOW OUT.
blowOutCandle(); // Turn off light (and start SMOKING!)
lit = false;
}</p><p>if (!lit){ // if candle isn't lit
if (flame_val > FLAME_THRESHOLD){ // if flame is detected
// record the starting time (if flame not yet detected)
if (!flaming){// if not flaming
flaming = true;
flameStartedMillis = millis();// record time that flaming begins
}
else if (checkFlame()){ // has flame been flaming long enough?
lightCandle(); // ok finally light it up.
lit = true;
}
}
else{ // no flame detected
flaming = false;
}
}
}</p><p>// Check if flame has been detected long enough.
bool checkFlame(){
unsigned long currentMillis = millis(); // get current time
if (currentMillis - flameStartedMillis >= FLAME_DURATION) {
return true;
}
else
return false;
}</p><p>// (pseudo)ASYNC light the candle by starting the animations
void lightCandle(){
digitalWrite(LED_BUILTIN, HIGH);
}</p><p>void blowOutCandle(){
digitalWrite(LED_BUILTIN, LOW);
}</p>
// Using technique from herehttps://learn.adafruit.com/multi-tasking-the-ardu...
// see link above for a good tutorial on this multi-task-ish way of doing things.
// Flicker Realistic Candle
// Keith Kelly 2019-03-04www.KeithsTestGarage.com
// Milestone 2 of 3
#ifdef __AVR__
#include
#endif
// NeoPatterns will require the Adafruit NeoPixel library.Be sure to install that.
#include "NeoPatterns.h"
#define NEO_PIN 5 // First RGBW Strip Pin
#define NEO2_PIN 9 // Second RGBW Strip Pin
#define NEO_COUNT 3// First RGBW Strip Count
#define NEO2_COUNT 3 // Second RGBW Strip Count
#define MIC_PIN A1 // Microphone Pin
#define FLAME_PIN A3 // IR Sensor Pin
#define FLAME_DURATION 2000 // millis- duration of flame before lighting candle
#define FLAME_THRESHOLD 800 // 0...1023 - analog reading of FLAME value to detect
#define MIC_THRESHOLD 950 // 0...1023 - analog reading of MIC value to detect
void Strip1Complete();
void Strip2Complete();
NeoPatterns Strip1(NEO_COUNT, NEO_PIN, NEO_RGBW + NEO_KHZ800, &Strip1Complete);
NeoPatterns Strip2(NEO_COUNT, NEO2_PIN, NEO_RGBW + NEO_KHZ800, &Strip2Complete);
uint32_t baseColor; // What is the ON resting color?
uint32_t offColor;// What is the OFF resting color?
// Vars to keep track of things
bool flaming = false;
bool lit = false;
int flame_val = 0;
int mic_val = 0;
byte rnd = 0;
// Vars for tracking pseudo-async times
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long flameStartedMillis = 0; // will store last time LED was updated
void setup(){
//Serial.begin(9600); // uncomment this to figure sensor readings.
// initialize pins
pinMode(FLAME_PIN, INPUT);
pinMode(MIC_PIN, INPUT);
pinMode(LED_BUILTIN, OUTPUT);
// Make sure the following pins are OFF
digitalWrite(LED_BUILTIN, LOW);
// Initialize NeoPixel Strip 1
Strip1.begin();
Strip1.show();
baseColor = Strip1.Color(2, 110, 0, 100);// GRBW
Strip1.Color1 = baseColor;
// Initialize NeoPixel Strip 2
Strip2.begin();
Strip2.show();
baseColor = Strip2.Color(2, 110, 0, 100);// GRBW
Strip2.Color1 = baseColor;
blowOutCandle();// Make sure candle is off
}
void loop(){
checkSensors(); // Check for fire and strong winds
Strip1.Update();
Strip2.Update();
}
// Checks for fire and strong winds every 50 milliseconds
void checkSensors(){
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 50) { // only check every 50ms
flame_val = analogRead( FLAME_PIN );
mic_val = analogRead( MIC_PIN );
previousMillis = currentMillis;
//Uncomment below to check sensor readings.
// Serial.print(mic_val);
// Serial.print(" : ");
// Serial.println(flame_val);
}
if (lit && mic_val > MIC_THRESHOLD){ // MIC REGISTERED SOUND.BLOW OUT.
blowOutCandle(); // Turn off light
lit = false;
}
if (!lit){ // if candle isn't lit
if (flame_val > FLAME_THRESHOLD){ // if flame is detected
// record the starting time (if flame not yet detected)
if (!flaming){// if not flaming
flaming = true;
flameStartedMillis = millis();// record time that flaming begins
}
else if (checkFlame()){ // has flame been flaming long enough?
lightCandle(); // ok finally light it up.
lit = true;
}
}
else{ // no flame detected
flaming = false;
}
}
}
// Check if flame has been detected long enough.
bool checkFlame(){
unsigned long currentMillis = millis(); // get current time
if (currentMillis - flameStartedMillis >= FLAME_DURATION) {
return true;
}
else
return false;
}
//------------------------------------------------------------
//Completion Routines - get called on completion of a pattern
//------------------------------------------------------------
// The below configuration routines are the same except for the strip
// being used.I kept them separate so the strips can be configured
// with different ranges if desired.
void Strip1Complete(){
Strip1.Reverse();
if (Strip1.Direction == REVERSE){ // go back down
Strip1.Interval = random(5,22); // choose random speed in range
}
else{// pattern ended.Stop, then trigger re-flicker
/*This needs an explanation:
rnd = random(random(45,55),random(80,255));
You'd think that we could just do random(45,255), right?
Selecting the low and high randoms first helps make sure that
the ending random number is *more likely* to fall within a limited range.
When observing the flickering of a real candle, the flame generally bounces
around in a certain range.But, every once in a while, it spikes high or low.
This random(random, random) solves that problem!#proudnerddadmoment
*/
rnd = random(random(45,55),random(80,255));
Strip1.Pixel = random(0,Strip1.numPixels()); // pick a random Pixel
Strip1.Interval = 1;
Strip1.Color2 = Strip1.Color(2,rnd,0,rnd-10); //GRBW random red and random white-10
}
}
void Strip2Complete(){
Strip2.Reverse();
if (Strip2.Direction == REVERSE){ // go back down
Strip2.Interval = random(5,22); // choose random speed in range
}
else{// pattern ended.Stop, then trigger re-flicker
rnd = random(random(45,55),random(80,255)); // see explanation in Strip1Complete().
Strip2.Pixel = random(0,Strip2.numPixels()); // pick a random Pixel
Strip2.Interval = 1;
Strip2.Color2 = Strip2.Color(2,rnd,0,rnd-10); //GRBW random red and random white-10
}
}
// (pseudo)ASYNC light the candle by starting the animations
void lightCandle(){
Strip1.Flicker(Strip1.Color1, Strip1.Color2, 20, 5);
Strip2.Flicker(Strip2.Color1, Strip2.Color2, 20, 5);
}
void blowOutCandle(){
cWipe(offColor, 10); // synchronously turn the candle off.
// We don't want no stinking patterns.
Strip1.ActivePattern = NONE;
Strip2.ActivePattern = NONE;
}
// synchronous color wipe
void cWipe(uint32_t c, uint8_t wait) {
for (uint16_t i = 0; i < Strip1.numPixels(); i++) {
Strip1.setPixelColor(i, c);
Strip1.show();
delay(wait);
}
for (uint16_t i = 0; i < Strip2.numPixels(); i++) {
Strip2.setPixelColor(i, c);
Strip2.show();
delay(wait);
}
}
// *****************************************
// START Custom animation for LED candle
// *****************************************
// Initialize for a Flicker
void Flicker(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
{
ActivePattern = FLICKER;
Interval = interval;
TotalSteps = steps;
Color1 = color1;
Color2 = color2;
Index = 0;
Direction = dir;
Pixel = random(0,numPixels()); // random(min,max) --max is EXCLUSIVE
}
// Initialize for a Flicker
void FlickerUpdate()
{
// Calculate linear interpolation between Color1 and Color2
// Optimize order of operations to minimize truncation error
uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;
uint8_t white = ((White(Color1) * (TotalSteps - Index)) + (White(Color2) * Index)) / TotalSteps;
setPixelColor(Pixel,Color(red, green, blue, white));
show();
Increment();
}
// *****************************************
// END Custom animation for LED candle
// *****************************************
Attachments
KeithsCandle_M2_NoSmoke.inoKeithsCandle_M2_NoSmoke.ino
// Using technique from herehttps://learn.adafruit.com/multi-tasking-the-ardu...
// see link above for a good tutorial on this multi-task-ish way of doing things.
// Flicker Realistic Candle
// Keith Kelly 2019-03-04www.KeithsTestGarage.com
// Milestone 2 of 3
#ifdef __AVR__
#include
#endif
// NeoPatterns will require the Adafruit NeoPixel library.Be sure to install that.
#include "NeoPatterns.h"
#define NEO_PIN 5 // First RGBW Strip Pin
#define NEO2_PIN 9 // Second RGBW Strip Pin
#define NEO_COUNT 3// First RGBW Strip Count
#define NEO2_COUNT 3 // Second RGBW Strip Count
#define MIC_PIN A1 // Microphone Pin
#define FLAME_PIN A3 // IR Sensor Pin
#define FLAME_DURATION 2000 // millis- duration of flame before lighting candle
#define FLAME_THRESHOLD 800 // 0...1023 - analog reading of FLAME value to detect
#define MIC_THRESHOLD 950 // 0...1023 - analog reading of MIC value to detect
void Strip1Complete();
void Strip2Complete();
NeoPatterns Strip1(NEO_COUNT, NEO_PIN, NEO_RGBW + NEO_KHZ800, &Strip1Complete);
NeoPatterns Strip2(NEO_COUNT, NEO2_PIN, NEO_RGBW + NEO_KHZ800, &Strip2Complete);
uint32_t baseColor; // What is the ON resting color?
uint32_t offColor;// What is the OFF resting color?
// Vars to keep track of things
bool flaming = false;
bool lit = false;
int flame_val = 0;
int mic_val = 0;
byte rnd = 0;
// Vars for tracking pseudo-async times
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long flameStartedMillis = 0; // will store last time LED was updated
void setup(){
//Serial.begin(9600); // uncomment this to figure sensor readings.
// initialize pins
pinMode(FLAME_PIN, INPUT);
pinMode(MIC_PIN, INPUT);
pinMode(LED_BUILTIN, OUTPUT);
// Make sure the following pins are OFF
digitalWrite(LED_BUILTIN, LOW);
// Initialize NeoPixel Strip 1
Strip1.begin();
Strip1.show();
baseColor = Strip1.Color(2, 110, 0, 100);// GRBW
Strip1.Color1 = baseColor;
// Initialize NeoPixel Strip 2
Strip2.begin();
Strip2.show();
baseColor = Strip2.Color(2, 110, 0, 100);// GRBW
Strip2.Color1 = baseColor;
blowOutCandle();// Make sure candle is off
}
void loop(){
checkSensors(); // Check for fire and strong winds
Strip1.Update();
Strip2.Update();
}
// Checks for fire and strong winds every 50 milliseconds
void checkSensors(){
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 50) { // only check every 50ms
flame_val = analogRead( FLAME_PIN );
mic_val = analogRead( MIC_PIN );
previousMillis = currentMillis;
//Uncomment below to check sensor readings.
// Serial.print(mic_val);
// Serial.print(" : ");
// Serial.println(flame_val);
}
if (lit && mic_val > MIC_THRESHOLD){ // MIC REGISTERED SOUND.BLOW OUT.
blowOutCandle(); // Turn off light
lit = false;
}
if (!lit){ // if candle isn't lit
if (flame_val > FLAME_THRESHOLD){ // if flame is detected
// record the starting time (if flame not yet detected)
if (!flaming){// if not flaming
flaming = true;
flameStartedMillis = millis();// record time that flaming begins
}
else if (checkFlame()){ // has flame been flaming long enough?
lightCandle(); // ok finally light it up.
lit = true;
}
}
else{ // no flame detected
flaming = false;
}
}
}
// Check if flame has been detected long enough.
bool checkFlame(){
unsigned long currentMillis = millis(); // get current time
if (currentMillis - flameStartedMillis >= FLAME_DURATION) {
return true;
}
else
return false;
}
//------------------------------------------------------------
//Completion Routines - get called on completion of a pattern
//------------------------------------------------------------
// The below configuration routines are the same except for the strip
// being used.I kept them separate so the strips can be configured
// with different ranges if desired.
void Strip1Complete(){
Strip1.Reverse();
if (Strip1.Direction == REVERSE){ // go back down
Strip1.Interval = random(5,22); // choose random speed in range
}
else{// pattern ended.Stop, then trigger re-flicker
/*This needs an explanation:
rnd = random(random(45,55),random(80,255));
You'd think that we could just do random(45,255), right?
Selecting the low and high randoms first helps make sure that
the ending random number is *more likely* to fall within a limited range.
When observing the flickering of a real candle, the flame generally bounces
around in a certain range.But, every once in a while, it spikes high or low.
This random(random, random) solves that problem!#proudnerddadmoment
*/
rnd = random(random(45,55),random(80,255));
Strip1.Pixel = random(0,Strip1.numPixels()); // pick a random Pixel
Strip1.Interval = 1;
Strip1.Color2 = Strip1.Color(2,rnd,0,rnd-10); //GRBW random red and random white-10
}
}
void Strip2Complete(){
Strip2.Reverse();
if (Strip2.Direction == REVERSE){ // go back down
Strip2.Interval = random(5,22); // choose random speed in range
}
else{// pattern ended.Stop, then trigger re-flicker
rnd = random(random(45,55),random(80,255)); // see explanation in Strip1Complete().
Strip2.Pixel = random(0,Strip2.numPixels()); // pick a random Pixel
Strip2.Interval = 1;
Strip2.Color2 = Strip2.Color(2,rnd,0,rnd-10); //GRBW random red and random white-10
}
}
// (pseudo)ASYNC light the candle by starting the animations
void lightCandle(){
Strip1.Flicker(Strip1.Color1, Strip1.Color2, 20, 5);
Strip2.Flicker(Strip2.Color1, Strip2.Color2, 20, 5);
}
void blowOutCandle(){
cWipe(offColor, 10); // synchronously turn the candle off.
// We don't want no stinking patterns.
Strip1.ActivePattern = NONE;
Strip2.ActivePattern = NONE;
}
// synchronous color wipe
void cWipe(uint32_t c, uint8_t wait) {
for (uint16_t i = 0; i < Strip1.numPixels(); i++) {
Strip1.setPixelColor(i, c);
Strip1.show();
delay(wait);
}
for (uint16_t i = 0; i < Strip2.numPixels(); i++) {
Strip2.setPixelColor(i, c);
Strip2.show();
delay(wait);
}
}
// *****************************************
// START Custom animation for LED candle
// *****************************************
// Initialize for a Flicker
void Flicker(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
{
ActivePattern = FLICKER;
Interval = interval;
TotalSteps = steps;
Color1 = color1;
Color2 = color2;
Index = 0;
Direction = dir;
Pixel = random(0,numPixels()); // random(min,max) --max is EXCLUSIVE
}
// Initialize for a Flicker
void FlickerUpdate()
{
// Calculate linear interpolation between Color1 and Color2
// Optimize order of operations to minimize truncation error
uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;
uint8_t white = ((White(Color1) * (TotalSteps - Index)) + (White(Color2) * Index)) / TotalSteps;
setPixelColor(Pixel,Color(red, green, blue, white));
show();
Increment();
}
// *****************************************
// END Custom animation for LED candle
// *****************************************
// Using technique from herehttps://learn.adafruit.com/multi-tasking-the-ardu...
// see link above for a good tutorial on this multi-task-ish way of doing things.
// Flicker/Smoke Realistic Candle
// Keith Kelly 2019-03-04www.KeithsTestGarage.com
// Milestone 3 of 3
#ifdef __AVR__
#include
#endif
// NeoPatterns will require the Adafruit NeoPixel library.Be sure to install that.
#include "NeoPatterns.h"
#define NEO_PIN 5 // First RGBW Strip Pin
#define NEO2_PIN 9 // Second RGBW Strip Pin
#define NEO_COUNT 3// First RGBW Strip Count
#define NEO2_COUNT 3 // Second RGBW Strip Count
#define MIC_PIN A1 // Microphone Pin
#define FLAME_PIN A3 // IR Sensor Pin
#define SMOKE_PIN 3// Smoke Pin
#define SMOKE_TIME_MILLIS 1200 // How long should smoke wire be heated?
#define FLAME_DURATION 2000 // millis- duration of flame before lighting candle
#define FLAME_THRESHOLD 800 // 0...1023 - analog reading of FLAME value to detect
#define MIC_THRESHOLD 950 // 0...1023 - analog reading of MIC value to detect
void Strip1Complete();
void Strip2Complete();
NeoPatterns Strip1(NEO_COUNT, NEO_PIN, NEO_RGBW + NEO_KHZ800, &Strip1Complete);
NeoPatterns Strip2(NEO_COUNT, NEO2_PIN, NEO_RGBW + NEO_KHZ800, &Strip2Complete);
uint32_t baseColor; // What is the ON resting color?
uint32_t offColor;// What is the OFF resting color?
// Vars to keep track of things
bool smoking = false;
bool flaming = false;
bool lit = false;
int flame_val = 0;
int mic_val = 0;
byte rnd = 0;
// Vars for tracking pseudo-async times
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long smokeStartedMillis = 0; // time smoking started
unsigned long flameStartedMillis = 0; // will store last time LED was updated
void setup(){
//Serial.begin(9600); // uncomment this to figure sensor readings.
// initialize pins
pinMode(FLAME_PIN, INPUT);
pinMode(MIC_PIN, INPUT);
pinMode(SMOKE_PIN, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
// Make sure the following pins are OFF
digitalWrite(SMOKE_PIN, LOW);
digitalWrite(LED_BUILTIN, LOW);
// Initialize NeoPixel Strip 1
Strip1.begin();
Strip1.show();
baseColor = Strip1.Color(2, 110, 0, 100);// GRBW
Strip1.Color1 = baseColor;
// Initialize NeoPixel Strip 2
Strip2.begin();
Strip2.show();
baseColor = Strip2.Color(2, 110, 0, 100);// GRBW
Strip2.Color1 = baseColor;
blowOutCandle(false);// Make sure candle is off (but don't smoke)
}
void loop(){
smokeCheck(); // Check if we should stop smoking.
checkSensors(); // Check for fire and strong winds
Strip1.Update();
Strip2.Update();
}
// Checks for fire and strong winds every 50 milliseconds
void checkSensors(){
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 50) { // only check every 50ms
flame_val = analogRead( FLAME_PIN );
mic_val = analogRead( MIC_PIN );
previousMillis = currentMillis;
//Uncomment below to check sensor readings.
// Serial.print(mic_val);
// Serial.print(" : ");
// Serial.println(flame_val);
}
if (lit && mic_val > MIC_THRESHOLD){ // MIC REGISTERED SOUND.BLOW OUT.
blowOutCandle(true); // Turn off light (and start SMOKING!)
lit = false;
}
if (!lit){ // if candle isn't lit
if (flame_val > FLAME_THRESHOLD){ // if flame is detected
// record the starting time (if flame not yet detected)
if (!flaming){// if not flaming
flaming = true;
flameStartedMillis = millis();// record time that flaming begins
}
else if (checkFlame()){ // has flame been flaming long enough?
lightCandle(); // ok finally light it up.
lit = true;
}
}
else{ // no flame detected
flaming = false;
}
}
}
// Check if flame has been detected long enough.
bool checkFlame(){
unsigned long currentMillis = millis(); // get current time
if (currentMillis - flameStartedMillis >= FLAME_DURATION) {
return true;
}
else
return false;
}
//------------------------------------------------------------
//Completion Routines - get called on completion of a pattern
//------------------------------------------------------------
// The below configuration routines are the same except for the strip
// being used.I kept them separate so the strips can be configured
// with different ranges if desired.
void Strip1Complete(){
Strip1.Reverse();
if (Strip1.Direction == REVERSE){ // go back down
Strip1.Interval = random(5,22); // choose random speed in range
}
else{// pattern ended.Stop, then trigger re-flicker
/*This needs an explanation:
rnd = random(random(45,55),random(80,255));
You'd think that we could just do random(45,255), right?
Selecting the low and high randoms first helps make sure that
the ending random number is *more likely* to fall within a limited range.
When observing the flickering of a real candle, the flame generally bounces
around in a certain range.But, every once in a while, it spikes high or low.
This random(random, random) solves that problem!#proudnerddadmoment
*/
rnd = random(random(45,55),random(80,255));
Strip1.Pixel = random(0,Strip1.numPixels()); // pick a random Pixel
Strip1.Interval = 1;
Strip1.Color2 = Strip1.Color(2,rnd,0,rnd-10); //GRBW random red and random white-10
}
}
void Strip2Complete(){
Strip2.Reverse();
if (Strip2.Direction == REVERSE){ // go back down
Strip2.Interval = random(5,22); // choose random speed in range
}
else{// pattern ended.Stop, then trigger re-flicker
rnd = random(random(45,55),random(80,255)); // see explanation in Strip1Complete().
Strip2.Pixel = random(0,Strip2.numPixels()); // pick a random Pixel
Strip2.Interval = 1;
Strip2.Color2 = Strip2.Color(2,rnd,0,rnd-10); //GRBW random red and random white-10
}
}
// (pseudo)ASYNC light the candle by starting the animations
void lightCandle(){
Strip1.Flicker(Strip1.Color1, Strip1.Color2, 20, 5);
Strip2.Flicker(Strip2.Color1, Strip2.Color2, 20, 5);
}
void blowOutCandle(bool shouldSmoke){
if(shouldSmoke)
smokeStart();
cWipe(offColor, 10); // synchronously turn the candle off.
// We don't want no stinking patterns.
Strip1.ActivePattern = NONE;
Strip2.ActivePattern = NONE;
}
// SMOKING METHODS
void smokeStart(){
digitalWrite(SMOKE_PIN, HIGH); // HEAT SMOKE WIRE
smoking = true;
smokeStartedMillis = millis(); // record time smoking started
}
// Stop smoking if the time has come.
void smokeCheck(){
if (!smoking)
return; // if not smoking, get out of here.
unsigned long currentMillis = millis();
if (currentMillis - smokeStartedMillis >= SMOKE_TIME_MILLIS) {
smokeStop(); // smoke break is over
}
}
// Ok seriously now stop it
void smokeStop(){
digitalWrite(SMOKE_PIN, LOW); // TURN OFF SMOKE WIRE
smoking = false;
}
// synchronous color wipe
// To avoid smoke becoming fire, be sure to only
// use synchronous methods like this SPARINGLY and when you
// are sure it won't interfere with the smoking.
//
// In other words, here's something that would be very bad:
//
//smokeStart();
//cWipe(offColor, 1000); // CPU would get caught up in
// here for a while and would
// not stop the smoking process
//
//At this point, I'm only using it directly after smokeStop();
void cWipe(uint32_t c, uint8_t wait) {
for (uint16_t i = 0; i < Strip1.numPixels(); i++) {
Strip1.setPixelColor(i, c);
Strip1.show();
delay(wait);
}
for (uint16_t i = 0; i < Strip2.numPixels(); i++) {
Strip2.setPixelColor(i, c);
Strip2.show();
delay(wait);
}
}
需要详细教程的朋友可以去看原文
挺不错的创意 挺不错的创意
页:
[1]