Week 2 Candle
Candle
After I lit up the Neopixel, I played with the RGB and HSI then I tried the example code from Tom’s GitHub. I add more random delay to create a blinking effect. Then I found the color turns out to be a bit too red when putting an actual candle side by side, so I extract the color code of a flame in Illustrator and play with it a little bit.
/*
Candle example
Runs only on SAMD boards (Nano 33 IoT, MKR series)
uses Adafruit's NeoPixel library and the ColorHSV function therein
Also uses Scheduler library, which runs only on SAMD boards.
created 6 Jun 2020
modified 6 Feb 2023
by Tom Igoe
*/
#include <Adafruit_NeoPixel.h>
#include <Scheduler.h>
const int neoPixelPin = 5; // control pin
const int pixelCount = 7; // number of pixels
// set up strip:
Adafruit_NeoPixel candle = Adafruit_NeoPixel(pixelCount, neoPixelPin, NEO_GRBW + NEO_KHZ800);
int hues[pixelCount];
int saturations[pixelCount];
int intensities[pixelCount];
int changeValues[] = {1, 1, 1, 1, 1, 1, 1}; //change here does not make too much difference
int highPixels[] = {6, 3}; //lighter towards yellow
int lowPixels[] = {1, 4}; // darker towards red
int bluePixel = 0;
int lightPixels[] = {2, 5}; //in the middle -orange color
void setup() {
Serial.begin(9600);
candle.begin(); // initialize pixel strip
candle.clear(); // turn all LEDs off
candle.show(); // update strip
// set all initial hues, sats, intensities, and colorConverters
for (int p = 0; p < 2; p++) {
int thisPixel = highPixels[p];
hues[thisPixel] = random(1200) + 10000; //random(1200) + 1200; need to go future yellow (10012)
saturations[thisPixel] = random(10) + 240;
intensities[thisPixel] = random(20) + 200;
}
for (int p = 0; p < 2; p++) {
int thisPixel = lowPixels[p];
hues[thisPixel] = random(800) + 9000; //random(800) + 300; red 1274
saturations[thisPixel] = 255;
intensities[thisPixel] = random(120) + 100;
}
for (int p = 0; p < 2; p++) {
int thisPixel = lightPixels[p];
hues[thisPixel] = random(2800) + 10000; // random(1500) + 800; orange 5825
saturations[thisPixel] = random(20) + 220;
intensities[thisPixel] = random(140) + 110;
}
hues[bluePixel] = random(200) + 30000; // blue 39679
saturations[bluePixel] = random(10) + 230;
intensities[bluePixel] = random(20) + 30;
// set up some loops for timing:
Scheduler.startLoop(fastLoop);
Scheduler.startLoop(medLoop);
Scheduler.startLoop(slowLoop);
}
void loop() {
for (int p = 0; p < 2; p++) {
int thisPixel = highPixels[p];
// change the hue:
hues[thisPixel] = hues[thisPixel] + changeValues[thisPixel];
// keep the change within the min/max range,
// but change directions at the extremes:
if (hues[thisPixel] < 8 || hues[thisPixel] > 18) {
changeValues[thisPixel] = -changeValues[thisPixel];
}
long thisColor = candle.ColorHSV(hues[thisPixel],
saturations[thisPixel],
intensities[thisPixel]);
candle.setPixelColor(thisPixel, thisColor);
}
candle.show();
delay(500);
yield();
//candle.clear(); // turn all LEDs off
}
void fastLoop() {
for (int p = 0; p < 2; p++) {
int thisPixel = lowPixels[p];
// change the hue:
hues[thisPixel] = hues[thisPixel] + changeValues[thisPixel];
// keep the change within the min/max range,
// but add a random -1 to 2:
hues[thisPixel] += (random(3) - 1);
hues[thisPixel] = constrain(hues[thisPixel], 4, 16);
long thisColor = candle.ColorHSV(hues[thisPixel],
saturations[thisPixel],
intensities[thisPixel]);
candle.setPixelColor(thisPixel, thisColor);
}
candle.show();
delay(30);
//candle.clear(); // turn all LEDs off
}
void medLoop() {
for (int p = 0; p < 2; p++) {
int thisPixel = lightPixels[p];
// change the hue:
hues[thisPixel] = hues[thisPixel] + changeValues[thisPixel];
// keep the change within the min/max range,
// but change directions at the extremes:
if (hues[thisPixel] < 4 || hues[thisPixel] > 20) {
changeValues[thisPixel] = -changeValues[thisPixel];
}
long thisColor = candle.ColorHSV(hues[thisPixel],
saturations[thisPixel],
intensities[thisPixel]);
candle.setPixelColor(thisPixel, thisColor);
}
candle.show();
delay(60);
//candle.clear(); // turn all LEDs off
}
void slowLoop() {
// change the hue:
hues[bluePixel] = hues[bluePixel] + changeValues[bluePixel];
// change the intensity and constrain it:
intensities[bluePixel] += (random(3) - 1);
intensities[bluePixel] = constrain(intensities[bluePixel], 0, 20);
// keep the change within the min/max range,
// but change directions at the extremes:
if (hues[bluePixel] < 200 || hues[bluePixel] > 280) {
changeValues[bluePixel] = -changeValues[bluePixel];
}
long thisColor = candle.ColorHSV(hues[bluePixel],
saturations[bluePixel],
intensities[bluePixel]);
candle.setPixelColor(bluePixel, thisColor);
candle.show();
delay(random(5000)+1000); //add random flikering
yield();
candle.clear(); // turn all LEDs off, for flikering effect
}
The second I am thinking is to use the same code to program an ATtiny 85 using the method from Homemade Hardware and use a coin cell battery to power it, so it can fit into a small case. I disassembled a LED candle and took out the battery case and switch. It took me a while to figure out the polarity of how the battery case work.
But when I program the ATtiny 85, I realized that the code I used above only works on Nano, so I changed the code and added a capacitive sensor. I want to create a lantern that flickers slowly but once you pick up the metal handle, the light will start shaking and flicker fast.
#include <Adafruit_NeoPixel.h>
#include <CapacitiveSensor.h>
const int neoPixelPin = 0; // control pin attiny85
//const int neoPixelPin = 5; // control pin Arduino
const int pixelCount = 7; // number of pixels
int change = 200; // increment to change hue by
// CapacitiveSensor cs_4_2 = CapacitiveSensor(4, 2); // 10M resistor between pins 4 & 2, pin 2 is sensor pin, add a wire and or foil if desired
CapacitiveSensor cs_4_2 = CapacitiveSensor(4, 1); // attiny-10M resistor between pins 4 & 2, pin 2 is sensor pin, add a wire and or foil if desired
const int threshold = 1500;
// set up strip:
Adafruit_NeoPixel strip = Adafruit_NeoPixel(pixelCount, neoPixelPin, NEO_GRBW + NEO_KHZ800);
//use this website to convert hsi
//https://www.had2know.org/technology/hsi-rgb-color-converter-equations.html
int h = 1000; // hue, 0-65535
int s = 255; // saturation 0-255
int i = 255; // intensity 0-255
// int highPixels[] = {6, 3}; //lighter towards yellow
// int lowPixels[] = {1, 4}; // darker towards red
// int bluePixel = 0;
// int lightPixels[] = {2, 5}; //in the middle -orange color
void setup() {
cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // turn off autocalibrate on channel 1 - just as an example
strip.begin(); // initialize pixel strip
strip.clear(); // turn all LEDs off
strip.show(); // update strip
Serial.begin(9600);
}
void loop() {
// create a single color from hue, sat, intensity:
long color = strip.ColorHSV(h, s, i);
long start = millis();
long total1 = cs_4_2.capacitiveSensor(30);
Serial.print(millis() - start); // check on performance in milliseconds
Serial.print("\t"); // tab character for debug windown spacing
Serial.println(total1); // print sensor output 1
if (total1 > threshold) {
Serial.println("yes");
for (int pixel = 0; pixel < 8; pixel += 1) {
strip.setPixelColor(pixel, strip.ColorHSV(h, s, i));
strip.setPixelColor(pixel + 1, strip.ColorHSV(0, 0, 0));
strip.show(); // update the strip
delay(10);
if (pixel > 0) {
strip.setPixelColor(pixel, strip.ColorHSV(0, 0, 0));
strip.show();
delay(random(300));
}
}
} else {
// loop over all the pixels:
for (int pixel = 0; pixel < 8; pixel++) {
strip.setPixelColor(pixel, color);
strip.show(); // update the strip
delay(random(100)+30);
//strip.clear(); // turn all LEDs off
}
}
h = h + change;
if (h <= 1000 || h >= 3500) {
change = -change;
}
h = constrain(h, 1000, 3500);
}
For the light diffusers, below are some tests I did, using diffent color acrylic, paper at diffent thickness and combined.
Observation Assignment: Early morning, Exterior
The time is around 7 am, and my apartment is toward the north side so I cannot see the direct sunrise. But I can always see the rays of sunrise cast toward the northern sky.
The sky was originally a gradient from blue to orange and pink, and as time goes on, the orange gradually fades out into the horizon and the sky turns back to blue.