Skip to content

Instantly share code, notes, and snippets.

@jkeefe
Last active August 29, 2015 13:56
Show Gist options
  • Save jkeefe/8949978 to your computer and use it in GitHub Desktop.
Save jkeefe/8949978 to your computer and use it in GitHub Desktop.
/*
* 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