Last active
August 29, 2015 13:56
-
-
Save jkeefe/8949978 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Mood Cube Light | |
* | |
* This is a program to subtly change a bedside lamp, driven by | |
* NeoPixel LEDs, as the days progress through the month to | |
* provide a visual cue to a woman's point in her menstrual cycle. | |
* Built by John Keefe at the request of Kristin Keefe. | |
* | |
* Some of the codes stands on example code that accompanies the | |
* the NeoPixel and the Time.h Libraries | |
* | |
* Use as you see fit! Comes with no promises on elegance or functionality. | |
* Would love a credit back to http://johnkeefe.net if you see fit. | |
* | |
* Full details on building the lamp: http://johnkeefe.net/the-monthly-mood-cube | |
* john@johnkeefe.net | |
* February 2014 | |
*/ | |
// Load the libraries needed for this program. | |
// More on installing libraries here: http://arduino.cc/en/Guide/Libraries | |
// First the Adafruit NeoPixel library, found here: | |
// http://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library | |
#include <Adafruit_NeoPixel.h> | |
// Then the Time and Time alarms libraries you can get here: | |
// http://www.pjrc.com/teensy/td_libs_Time.html and | |
// http://www.pjrc.com/teensy/td_libs_TimeAlarms.html | |
#include <Time.h> | |
#include <TimeAlarms.h> | |
// constants won't change. They're used here to | |
// set pin numbers and variables. | |
#define PIN 6 // the number of the NeoPixel pin | |
const int buttonPin = 2; // the number of the pushbutton pin | |
byte cycle_length = 28; // days in the cycle | |
byte color_day = cycle_length - 10; // day to start color change | |
// variables that will change | |
int current_day = 0; | |
int button_state = 0; | |
int ambient_light = 0; // this is the sensor light reading | |
int dark_threshold = 150; //this is the reading at which the lamp darkens | |
int intensity = 50; // this is the lamp's default brightness (0-100) | |
int lamp_state = 1; // is the lamp on (1) or off (0)? | |
int hold_count = 0; // used to measure button push | |
int hold_time = 0; // tracks last time button was held | |
boolean reset_mode; | |
// SET UP THE NEOPIXEL RING: | |
// Parameter 1 = number of pixels in strip | |
// Parameter 2 = pin number (most are valid) | |
// Parameter 3 = pixel type flags, add together as needed: | |
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs) | |
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers) | |
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products) | |
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2) | |
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800); | |
// this is the setup code, which is run once | |
void setup() { | |
strip.begin(); | |
strip.show(); // Initialize all pixels to 'off' | |
// initialize the pushbutton pin as an input: | |
pinMode(buttonPin, INPUT); | |
// Initialize Serial Port for debugging | |
Serial.begin(9600); | |
// Use the Alarm time code to run the aNewDay function once a day, | |
// or every 86400 seconds | |
setTime(8,29,0,1,1,11); | |
Alarm.timerRepeat(86400, aNewDay); | |
} | |
// this code continuously loops | |
void loop() { | |
// for some reason this is required in the code or the | |
// alarm doesn't work. | |
Alarm.delay(100); // wait 1/10 second | |
// if we're just starting out, run the aNewDay function | |
if (current_day == 0) { | |
strip.setBrightness(intensity); | |
aNewDay(); | |
} | |
// this bit of code detects when someone is holding the button. | |
// A short press resets the cube to day 1. | |
// A longer hold causes the cube to start turn blue and then flash once for | |
// each day to advance, starting with day 1. Releasing the button stops the count. | |
// This is so you can advance into the month after powering up. | |
hold_count = 0; | |
button_state = digitalRead(buttonPin); | |
while (button_state == HIGH){ | |
hold_count++; | |
// note that Alarm.delay() is used instead of delay() | |
// whenever we have to wait. A regular delay() will throw | |
// off the Time calculations. | |
Alarm.delay(100); | |
Serial.print("Hold Count:"); | |
Serial.println(hold_count); | |
button_state = digitalRead(buttonPin); | |
if (hold_count == 30) { | |
current_day = -1; | |
} | |
if (hold_count > 30) { | |
colorNow(strip.Color(0,0,255),1500); | |
aNewDay(); | |
} | |
if (hold_count < 30) { | |
current_day = 0; | |
aNewDay(); | |
} | |
} | |
// make the lamp dark if it's dark in the room | |
ambient_light = analogRead(0); // read value from light sensor | |
Serial.print("Ambient Light:"); | |
Serial.print(ambient_light); | |
Serial.print(" lamp state:"); | |
Serial.println(lamp_state); | |
// is it light in the room and the lamp is off? | |
if (ambient_light > dark_threshold && lamp_state == 0) { | |
// fade it up into the proper color for the day | |
for(int i=0; i<intensity+1; i++) | |
{ | |
strip.setBrightness(i); | |
setDayColor(); | |
strip.show(); | |
Serial.println(i); | |
Alarm.delay (50); | |
} | |
lamp_state = 1; // and toggle the state | |
} | |
// is it dark in the room and the lamp is on? | |
if (ambient_light < dark_threshold && lamp_state == 1) { | |
// fade the lamp down to off | |
for(uint16_t i=0; i<intensity + 1; i++) | |
{ | |
strip.setBrightness(intensity - i); | |
setDayColor(); | |
strip.show(); | |
Alarm.delay (30); | |
} | |
// and change the lamp state | |
lamp_state = 0; | |
} | |
} | |
// Make a color instantly | |
void colorNow(uint32_t colr, uint16_t wait) { | |
for(uint16_t i=0; i<strip.numPixels(); i++) { | |
strip.setPixelColor(i, colr); | |
} | |
strip.show(); | |
Alarm.delay(wait); | |
} | |
void aNewDay() { | |
// increment the day | |
current_day += 1; | |
// print it to the serial monitor for debugging | |
Serial.print("Day Number:"); | |
Serial.print(current_day); | |
Serial.println(); | |
setDayColor(); | |
} | |
void setDayColor(){ | |
// time to change the lamp yet? | |
if (current_day >= color_day) { | |
// send the day number of the fade toward orange | |
lampColor(current_day - color_day); | |
} else { | |
// otherwise leave it white | |
colorNow(strip.Color(255,255,75),0); | |
} | |
} | |
// Fade from yellow-white 255,255,75 to orange 255,128,0 | |
// over the course of 10 days. Takes the current day. | |
void lampColor(uint16_t fadeday) { | |
byte red; | |
byte green; | |
byte blue; | |
// fade to orange for first 7 days | |
if (fadeday <= 6) { | |
red = 255; | |
green = 255 - (fadeday * ( (255-128) / 6 )); | |
blue = 75 - (fadeday * ( (75-0) / 6 )); | |
} else if (fadeday > 6 && fadeday < 8) { | |
// provide two additional days of orange | |
red = 250; | |
green = 110; | |
blue = 0; | |
} else { | |
// otherwise make it red | |
red = 240; | |
green = 90; | |
blue = 10; | |
} | |
// run through the pixels in the strip | |
for(uint16_t i=0; i<strip.numPixels(); i++) | |
{ | |
strip.setPixelColor(i, red, green, blue); | |
} | |
strip.show(); | |
// prints to the serial port for debugging | |
Serial.println("RBG "); | |
Serial.print(red); | |
Serial.print(" "); | |
Serial.print(green); | |
Serial.print(" "); | |
Serial.println(blue); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment