A post with the program.
Here it is, folks. The program for my Christmas Hat! I just want to give a big thank you to my Hunky Assistant, Pierre-Marc, for doing fancy code interpolations and humoring me during the lighting design process. I'm not yet good at enough at coding to have written all of this myself.
One of my favorite late-stage additions to the code is in line 134 below: "return get_tempF_serial();" which I un-comment and use to in order to tell the hat a specific temperature via the serial port. This was especially helpful when working out how it would look at what temp.
Let me know what you think!
//final version of the Xmas Hat code #include <math.h> #include <Adafruit_NeoPixel.h> // change these to adjust the range of temperatures you want to measure // (these are in Fahrenheit, multiplied by 10 to account for a decimal point) #define COLDTEMP 400 #define TRANSITION_TEMP 700 #define HOTTEMP 800 #define INSTALLED_PIXELS 73 //The long Neopixel Strip is called "strip1" Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(INSTALLED_PIXELS, 6, NEO_GRB + NEO_KHZ800); //The two 5mm Neopixels and three 8mm Neopixels are called "strip2" Adafruit_NeoPixel strip2 = Adafruit_NeoPixel(5, 9, NEO_RGB + NEO_KHZ800); //TMP36 Pin Variables int sensorPin = 10; //the analog pin the TMP36's data-out (middle) pin is connected to //defining colors for cold state uint8_t myColors[][3] = {{170, 170, 255}, // dim white {170, 85, 255}, // white {51, 102, 255}, // blue }; // don't edit the line below #define COLDCOLORS sizeof(myColors) / 3 #define COLD_MODE_COLD_BACKGROUND const uint8_t cold_mode_cold_background[] = { 0, 0, 11 }; const uint8_t cold_mode_hot_background[] = { 1, 2, 1 }; const uint8_t cold_mode_cold_interval = 2; const uint8_t cold_mode_hot_interval = 200; const uint8_t hot_mode_hot_frame_sleep = 2; const uint8_t hot_mode_cold_frame_sleep = 30; const uint8_t hot_mode_hot_interphase_sleep = 700; const uint8_t hot_mode_cold_interphase_sleep = 60000; #define HOT_FRONT_WIDTH 5 #define FRAMES_PER_PIXEL 10 uint8_t lut[256]; #define K 1.02189714865 // 256^(1/256) // The current temperature float temp; void initialize_lut(void) { short T; double TPh; for(lut[0] = 0, TPh = K, T = 1; T < 256; TPh *= K, T++) { lut[T] = (uint8_t) lrint(TPh); //Serial.print(TPh); Serial.print(" "); Serial.println(lut[T]); } } /* * the setup() function runs once when you turn on the Flora * Initialize the serial connection with the computer * Initialize strip1 and strip2 */ void setup() { Serial.begin(9600); //Start the serial connection with the computer //to view the result open the serial monitor pinMode(6, INPUT_PULLUP); //initializes strip1 pinMode(9, INPUT_PULLUP); //initializes strip2 strip1.begin(); strip2.begin(); strip1.show(); // Initializes strip1 to 'off' strip2.show(); // Initializes strip2 to 'off' initialize_lut(); temp = get_tempF(); } int get_tempF_serial() { static char buf[10]; static char *ptr = buf; static int serial_temp = get_tempF_sensor(); while(Serial.available()) { Serial.readBytes(ptr, 1); if (ptr - buf == 10) { ptr = buf; } if (*ptr == '\n') { *ptr = '\0'; serial_temp = atoi(buf); ptr = buf; } else { ptr++; } } Serial.print(serial_temp); Serial.println(" degrees F (serial)"); return serial_temp; } int get_tempF() { // to use serial temp, uncomment // return get_tempF_serial(); return get_tempF_sensor(); } /* *this next bit is the Flora getting the temp from the sensor * and also converting it into fahrenheit */ int get_tempF_sensor() // gets the temp { //getting the voltage reading from the temperature sensor int reading = analogRead(sensorPin); // converting that reading to voltage, for 3.3v arduino use 3.3 float voltage = reading * 3.3; voltage /= 1024.0; // print out the voltage //Serial.print(voltage); Serial.println(" volts"); // now print out the temperature float temperatureC = (voltage - 0.5) * 100 ; //converting from 10 mv per degree wit 500 mV offset //to degrees ((voltage - 500mV) times 100) //Serial.print(temperatureC); Serial.println(" degrees C"); // now convert to Fahrenheit float tempF = (temperatureC * 9.0 / 5.0) + 32.0; Serial.print(tempF); Serial.println(" degrees F"); return tempF * 10; } void interpolate_detailed(uint8_t components, int frame, int total_frames, const uint8_t *initial, const uint8_t *next, uint8_t *vals) { int i; //Serial.print("frame "); Serial.print(frame); Serial.print("/"); Serial.println(total_frames); for (i = 0; i < components; i++) { int16_t attrib_prev_val; int16_t attrib_next_val; attrib_prev_val = initial[i]; attrib_next_val = next[i]; int32_t tmp = (attrib_next_val - attrib_prev_val); tmp = tmp * frame / total_frames; vals[i] = attrib_prev_val + tmp; } } void set_background_color(uint8_t *col) { int i; for (i=0; i<INSTALLED_PIXELS; i++) { strip1.setPixelColor(i, Adafruit_NeoPixel::Color(col[0], col[1], col[2])); } } uint16_t current_frame = 0; uint16_t cold_frame = 0; uint16_t cold_phase = 0; uint8_t hot_phase = 0; /* Here's the meat of the program -- the loop */ void loop() { uint8_t white1, white2, blue1, blue2, green1, green2, red1, red2; if (temp < COLDTEMP) { temp = COLDTEMP; } if (temp > HOTTEMP) { temp = HOTTEMP; } if (temp < TRANSITION_TEMP) { uint8_t background[3]; interpolate_detailed(3, temp - COLDTEMP, TRANSITION_TEMP - COLDTEMP, cold_mode_cold_background, cold_mode_hot_background, background); //set_background_color(background); uint32_t base_color = Adafruit_NeoPixel::Color(background[0], background[1], background[2]); uint8_t interval; interpolate_detailed(1, temp - COLDTEMP, TRANSITION_TEMP - COLDTEMP, &cold_mode_cold_interval, &cold_mode_hot_interval, &interval); flashRandom(strip1, 0, INSTALLED_PIXELS, interval, 1, base_color); // first number is 'wait' delay, shorter num == shorter twinkle, third number is base color white1 = map(temp, TRANSITION_TEMP, COLDTEMP, 0, 255); blue1 = map(temp, TRANSITION_TEMP, COLDTEMP, 50, 255); strip2.setPixelColor(0, white1, white1, blue1); // strip.setPixelColor(pixel number in strip, R,G,B) strip2.setPixelColor(1, white1, white1, blue1); // "behind" LEDs get brighter the colder it gets strip2.setPixelColor(3, 0, 0, 4); strip2.show(); temp = get_tempF(); } else { uint16_t total_frames = (INSTALLED_PIXELS + 1) * FRAMES_PER_PIXEL; int i; for (i = 0; i < HOT_FRONT_WIDTH; i++) { if (current_frame / 10 < i) { break; } green1 = map(temp, TRANSITION_TEMP, HOTTEMP, 0, 250); green2 = map(temp, TRANSITION_TEMP, HOTTEMP, 0, 50); red1 = map(temp, TRANSITION_TEMP, HOTTEMP, 100, 250); red2 = map(temp, TRANSITION_TEMP, HOTTEMP, 0, 50); uint8_t green1_triplet[3] = {0, green1, 0}; uint8_t green2_triplet[3] = {0, green2, 0}; uint8_t red1_triplet[3] = {red1, 0, 0}; uint8_t red2_triplet[3] = {red2, 0, 0}; uint8_t this_pixel = current_frame / 10 - i; uint8_t val = 128*(i*FRAMES_PER_PIXEL+current_frame%FRAMES_PER_PIXEL)/(HOT_FRONT_WIDTH*FRAMES_PER_PIXEL); if (hot_phase < 1) { uint8_t color1_triplet[3] = {0, green1, 0}; uint8_t color2_triplet[3] = {0, green2, 0}; if (current_frame < 256) { interpolate_detailed(3, lut[current_frame], 255, red1_triplet, green1_triplet, color1_triplet); interpolate_detailed(3, lut[current_frame], 255, red2_triplet, green2_triplet, color2_triplet); } strip1.setPixelColor(this_pixel, strip1.Color(lut[val], 0, 0)); strip2.setPixelColor(0, color1_triplet[0], color1_triplet[1], color1_triplet[2]); // strip.setPixelColor(pixel number in strip, R,G,B) strip2.setPixelColor(1, color1_triplet[0], color1_triplet[1], color1_triplet[2]); // "behind" LEDs get brighter the warmer it gets strip2.setPixelColor(3, color2_triplet[0], color2_triplet[1], color2_triplet[2]); } else { uint8_t color1_triplet[3] = {red1, 0, 0}; uint8_t color2_triplet[3] = {red2, 0, 0}; if (current_frame < 256) { interpolate_detailed(3, lut[current_frame], 255, green1_triplet, red1_triplet, color1_triplet); interpolate_detailed(3, lut[current_frame], 255, green2_triplet, red2_triplet, color2_triplet); } strip1.setPixelColor(this_pixel, strip1.Color(0, lut[val], 0)); strip2.setPixelColor(0, color1_triplet[0], color1_triplet[1], color1_triplet[2]); // strip.setPixelColor(pixel number in strip, R,G,B) strip2.setPixelColor(1, color1_triplet[0], color1_triplet[1], color1_triplet[2]); // "behind" LEDs get brighter the warmer it gets strip2.setPixelColor(3, color2_triplet[0], color2_triplet[1], color2_triplet[2]); } } strip1.show(); strip2.show(); current_frame += 1; if (current_frame >= total_frames) { current_frame = 0; hot_phase++; uint8_t sleep_ms; interpolate_detailed(1, temp - TRANSITION_TEMP, HOTTEMP - TRANSITION_TEMP, &hot_mode_cold_interphase_sleep, &hot_mode_hot_interphase_sleep, &sleep_ms); delay(sleep_ms); delay(15000); hot_phase %= 2; temp = get_tempF(); } uint8_t sleep_ms; interpolate_detailed(1, temp - TRANSITION_TEMP, HOTTEMP - TRANSITION_TEMP, &hot_mode_cold_frame_sleep, &hot_mode_hot_frame_sleep, &sleep_ms); delay(sleep_ms); } } void flashRandom(Adafruit_NeoPixel &strip, uint8_t range_start, uint8_t range_end, int wait, uint8_t howmany, uint32_t base_color) { // pick a random favorite color! int c = random(COLDCOLORS); int red = myColors[c][0]; int green = myColors[c][1]; int blue = myColors[c][2]; // get a random pixel from the list int chosen_pixels[howmany]; for(uint16_t i=0; i<howmany; i++) { chosen_pixels[i] = random(range_end - range_start) + range_start; } int dim = 32; // now we will 'fade' it in 5 steps for(uint16_t i=0; i<howmany; i++) { strip.setPixelColor(chosen_pixels[i], strip.Color(red*dim/255, green*dim/255, blue*dim/255)); } strip.show(); delay(wait); for(uint16_t i=0; i<howmany; i++) { strip.setPixelColor(chosen_pixels[i], base_color); } strip.show(); delay(wait); } void colorWipe(uint32_t c, uint8_t wait) { for(uint16_t i=0; i<strip1.numPixels(); i++) { strip1.setPixelColor(i, c); strip1.show(); delay(wait); } }
Final post coming soon!