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.

Video Block
Double-click here to add a video by URL or embed code. Learn more

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.

Previous
Previous

Week 3-4 12V DC Lamp + Material Testings

Next
Next

Week 1