Neopixel sunrise alarm clock

So many possibilities:

  • A fog machine turns on and blows a morning mist into your bedroom.
  • A can of compressed air is released, sending fresh morning air into your nostrils (using a camera and face recognition software to aim the nozzle).
  • A servo slowly rolls your bedsheets down to your feet.
2 Likes

@mf2105 Thanks for the link! I’ll take a look at it and maybe steal a few of there features!

@topfunky I like the way you think! Now if only my :spark: would just go to school and do my homework for me I’d be set. :wink:

2 Likes

@shocku992 you could get the time of the sunrise from openweathermap.org. They have various web services providing actual weather conditions and forecast. But I could see that they are also providing sunrise and sunset.
Check it out: http://api.openweathermap.org/data/2.5/weather?id=2643743

For London: [..]"sunrise":1390377095,"sunset":1390408369[..]

Hmm. But converting 1390377095 to DateTime in c# returns {01.01.0001 00:02:19}

Sorry, so not sure if it’s usable for you.

1390377095 is a "seconds since epoch" value, so it will work just fine. Here's a web page that does it for you:

GMT: Wed, 22 Jan 2014 07:51:35 GMT

Google around for "epoch to datetime" and find a code snipped you like.

Rise and shine!

Dave O

You beat me to it @dorth! :slight_smile:

For a clock like this, if you look up the sunrise/sunset time and it’s in unix time, and you compare to an RTC that is also in unix time… all you need to do is 1) leave them all alone (GMT+0) for your comparison… or 2) convert them pretty easily UP or DOWN for your timezone (e.g. GMT-6) by adding or subtracting the number of seconds in an hour times the number of hours you need.
uint32_t gmt_minus_6 = unix_time - (uint32_t)(6 * 3600);

Works good as far as I can tell for Chicago, IL http://api.openweathermap.org/data/2.5/weather?id=4887398

What I lack in brains I make up for with speed! :slight_smile: But you bring up a good point about "needless conversions". Epoch is ugly to look at but really easy to work with!

@kwyjib​0 - thanks for the link to that web site. I'll have to keep that in mind for some future projects.

Dave O

Thanks for the info Guys. As soon as all the parts come together I’ll start working on it. At this rate all i’ll have to do is copy and paste. :wink: Keep the info coming!

1 Like

My RGB LED’s arrived today along with my Temp/humidity sensor. Now if only my :spark: would stop saying “Electronic Shipping Info Received” and hurry up and get here! Come on post office, it’s been a week!

It’s been a while since i’ve updated this thread! I’m still waiting on my second :spark: but I’ve been doing some testing with my first one. I’ve got the Realtime clock working, and the Neopixel library so I’m almost there. My next hurtle is going to be figuring out how to get the spark to pull a variable from a webpage. I want to be able to set the alarm time from a webpage, and the :spark: get that time as a variable and of course start the alarm sequence at that time. Any thoughts or suggestions?

Apart from being an awesome project, the MessageTorch by @luz also makes use of parameters which can be called upon through the rest API. You might be able to edit that in a way so you can use it to pass your time through to the core, without having the core looking for changes in variables. Seems like a logical solution, but there are more experienced people on this forum who could be of more assistance than me.
I’m hoping this project works out, because I’m planning to stuff about 24m of RGB strips in my ceiling to act as a wake up light :wink:

Good luck!

Link to the projects github: https://github.com/plan44/messagetorch/blob/master/messagetorch.cpp

I agree with @Moors7. You can easily pass in parameters from a web page through a [Spark.function();][1] as arguments.

You can do this with modifying my Remote Spark web app pretty easily. Or perhaps take a look at Luz’s project. I don’t know which would be easier. For setting the time, I’d think you’d need some nice scrollers or drop down fields to select the time, and then hit a button that says “Save” or “Set Time”… I actually need to do this for a project I’m working on as well, so if you beat me to it, please post something here :smile:
[1]: http://docs.spark.io/#/firmware/data-and-control-spark-function

Thanks guys! I’ll take a look at your project @Moors7 and Thanks for that @BDub. I’ll take a look at the spark.function. I doubt I’ll get to it before you. This is midterms week, I’m slammed, but maybe over spring break I’ll post something up if you haven’t.

Something else to think about… Another way to do this is to turn your Neopixel clock into it’s own TCP Server, and have it dish up a simple web interface. This puts more load on your clock, but could provide a faster response and you would not have to upload a web app somewhere, you would just save a link to an IP address on your local network. This is assuming you don’t need to be able to set it from the road, but you COULD forward a port on your router and still access it out and about as well.

I think you did this with your Spike Mon project, but used the RasPi right? I’m not sure how you had that all routed, but you probably wouldn’t want to have a ton of graphics if serving it up from the Core directly.

I hadn’t thought about that! That could work. It would be all self contained. I’ve got a static IP and a domain name that route back to my place. It would be easy to forward a port over to the :spark:. Something to think about indeed.

Just wanted to make sure you saw this:

:wink:

If you’re looking for some RGB colours, you can take aa look at these kelvin gradients

Not to hijack an old thread, but I started putting together something nearly identical using SmartThings. Just changing out the microcontroller for a Spark would be a piece of cake.

Hey guys. Although I don’t have the fancy neopixels, I still wanted a sunrise clock. I’ve now just made an array of RGB values that the code will walk through as soon as the relevant code is activated, based on the TimeAlarms library. I got the color values by using a web gradient maker, converting the hex values to rgb, and stuffing them in an array. This is by no means great, and I’m not sure if it resembles an actual sunrise, but as a proof-of-concept, it looks okay. I’ve used 300 values, to go over a period of 30mins. 1 every 6 seconds. The time can be changed by using the slider in the complementary webpage. I’m not sure if it’s possible, but I intend on using the FRAM/SD shield by @kennethlimcp to increase the number of values, making for a smoother transition.

Also, has anybody considered that pairing your RGB strips to this thing might be really nifty: https://www.kickstarter.com/projects/hello/sense-know-more-sleep-better?ref=home_popular It has a sleeping analyser, and will start to gradually wake you up as soon as it senses that you’re getting awake naturally. They say they’ll release an API which can be used to do whatever with. If you could hook this up to a sunrise lighting, your mornings might become a whole lot smoother. Added bonus: that clock thingy contains a few neat sensors, so yeah: collect ALL the data! You can make that thing handle all the “regular” alarm stuff, and make it do things by pairing it with your Spark, which can then drive things like RGB strips, heaters, and what-evers…

Anyhow, this is the code I currently use for the sunrise stuff, if anybody’s interested:

Spark:

// This #include statement was automatically added by the Spark IDE.
#include "TimeAlarms/TimeAlarms.h"

#define ledPin D7
#define redPin A0
#define greenPin A1
#define bluePin A5

int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated
int r = 0;
int g = 0;
int b = 0;    
char pubstring[64];

int redList[] = {  0,8,17,26,35,43,52,61,70,79,87,96,105,114,123,131,140,149,158,167,175,184,193,202,211,219,228,237,246,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,253,253,252,252,251,250,250,249,249,248,247,247,246,246,245,245,244,243,243,242,242,241,240,240,239,239,238,237,237,236,236,235,235,234,233,233,232,232,231,230,230,229,229,228,228,227,226,226,225,225,224,223,223,222,222,221,220,220,219,219,218,218,217,216,216,215,215,214,213,213,212,212,211,211,210,209,209,208,208,207,206,206,205,205,204,203,203,202,202,201,201,200,199,199,198,198,197,196,196,195,195,194,193,193,192,192,191,191,190,189,189,188,188,187,186,186,185,185,184,184,183,182,182,181,181,180,179,179,178,178,177,176,176,175,175,174,174,173,172,172,171,171,170,169,169,168,168,167,167,166,165,165,164,164,163,162,162,161,161,160,159,159,158,158,157,157,156,155,155,154,154,153,152,152,151,151,150,150,149,148,147,146,145,144,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128
};
int greenList[] = {  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,6,8,10,13,15,17,19,21,23,26,28,30,32,34,36,39,41,43,45,47,49,52,54,56,58,60,62,65,67,69,71,73,75,78,80,82,84,86,88,91,93,95,97,99,101,104,106,108,110,112,114,117,119,121,123,125,128,128,130,132,135,137,140,142,145,147,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,149,148,147,146,145,144,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128
};
int blueList[] = {  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,5,6,7,9,10,11,12,14,15,16,18,19,20,22,23,24,25,27,28,29,31,32,33,34,36,37,38,40,41,42,44,45,46,47,49,50,51,53,54,55,57,58,59,60,62,63,64,66,67,68,69,71,72,73,75,76,77,79,80,81,82,84,85,86,88,89,90,92,93,94,95,97,98,99,101,102,103,104,106,107,108,110,111,112,114,115,116,117,119,120,121,123,124,125,127,128,129,130,132,133,134,136,137,138,139,141,142,143,145,146,147,149,150,151,152,154,155,156,158,159,160,162,163,164,165,167,168,169,171,172,173,174,176,177,178,180,181,182,184,185,186,187,189,190,191,193,194,195,197,198,199,200,202,203,204,206,207,208,209,211,212,213,215,216,217,219,220,221,222,224,225,226,228,229,230,232,233,234,235,236,237,238,240,241,242,243,244,245,246,247,248,249,250,251,252,253,255
};

int x = 0;
int duration = 6000;

//300 color values times "duration" milliseconds is the time the sunrise goes for.
//The sunset is set to 1/6 of that time. At 6000ms this will take 30mins for a sunrise,
//and 5mins for a sunset. This value can be changed by the slider on the webpage, 
//from 0 to 6000.

void setup() {
    
    Time.zone(+2); //Amsterdam, Paris, stuff like that...
    
    // create the alarms 
    Alarm.alarmRepeat(8,15,0, MorningAlarm);  // 8:15am every day
    Alarm.alarmRepeat(9,15,0, MorningOffAlarm);  // 9:15pm every day 
    
    Serial.begin(9600);                                                                         
   
    pinMode(ledPin, OUTPUT);
    pinMode(redPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(bluePin, OUTPUT);
  
    RGB.control(true);                                                                          
    RGB.color(255,0,0);                                                                        
    myDelay(200);                                                                                   
    RGB.color(0,0,0);                                                                           
    myDelay(200);                                                                               
    RGB.color(0,0,255);                                                                         
    myDelay(200);                                                                              
    
    pubcolor();
    
    Spark.function("params", handleParams);                                                     
}

void loop() {
  digitalClockDisplay();
  Alarm.delay(1000); // wait one second between clock display
}


int handleParams(String command)
{                                                                                              
    int p = 0;                                                                                 
    while (p<(int)command.length()) {                                                           
        int i = command.indexOf(',',p);                                                     
        if (i<0) i = command.length();                                                         
        int j = command.indexOf('=',p);
        if (j<0) break;
        String key = command.substring(p,j);
        String value = command.substring(j+1,i);
        int val = value.toInt();
    
        	if (key=="r"){                                                               
                r = val;                                                                      
                Serial.println('Set red value');   
            } 
        	  
            else if (key=="g"){                                                       
                g = val;                                                                   
        	    Serial.println('Set green value');
        	}  
            
        	else if (key=="b"){                                                        
                b = val;                                                                    
        	    Serial.println('Set blue value');
        	}  
        	
        	else if (key == "GetColor"){
        	    //Just doing this to get the colors published.
            }
            
            else if (key == "duration"){
                //change the duration of the sunrise/sunset.
                duration = val;
            }
            else if (key == "sunrise"){
                //execute sunrise.
                sunrise();
            }
            else if (key == "sunset"){
                //execute sunset.
                sunset();
            }
        p = i+1;
    }
    //change colors to said values.
    color(r, g, b);
    //publish colors.
    pubcolor();
}
 
// duration is delay time in milliseconds
void myDelay(unsigned long duration)
{
  unsigned long start = millis();
  while (millis() - start <= duration)
  {
    blink(100);  // blink the LED inside the while loop
  }
}
    
    
// interval is the time that the LED is on and off
void blink(long interval)
{
  if (millis() - previousMillis > interval)
  {
    // save the last time you blinked the LED
    previousMillis = millis();
    // if the LED is off turn it on and vice versa:
    if (ledState == LOW)
      ledState = HIGH;    
    else
      ledState = LOW;
    digitalWrite(ledPin, ledState);
  }
}

//set the colors all at once, usefull as shorthand.
void color (unsigned char r, unsigned char g, unsigned char b){     
    analogWrite(redPin, r);     
    analogWrite(greenPin, g);
    analogWrite(bluePin, b);
    RGB.color(r, g, b);
};

//Convert color values to JSON string and publish them.
void pubcolor(){
    sprintf(pubstring,"{\"r\": %u, \"g\": %u, \"b\": %u}",r,g,b);         
    Spark.publish("color_values",pubstring);                                                
    Serial.println(String(pubstring));                                                     
};

//Sunrise function. Walks through the arrays.
void sunrise(){
    for (x = 0; x < 300; x++){
    	r = redList[x];
    	g = greenList[x];
    	b = blueList[x];
    	myDelay(duration);
    	color(r, g, b);
    };
}

//Sunset function. Walks through the arrays.
void sunset(){
    for (x = 0; x < 301; x++){
    	r = redList[300-x];
    	g = greenList[300-x];
    	b = blueList[300-x];
    	myDelay(duration/6);
    	color(r, g, b);
    };
}

//======================== ALARMS ===========================
// functions to be called when an alarm triggers:
void MorningAlarm(){
  Serial.println("Alarm: - turn lights on");
  RGB.color(255,0,0);                                                                        
  myDelay(200);                                                                                   
  RGB.color(0,0,0);                                                                           
  myDelay(200);                                                                               
  RGB.color(0,0,255);                                                                         
  myDelay(200);   
  
  sunrise();
};

void MorningOffAlarm(){
  Serial.println("Alarm: - turn lights off");  
  r = 0;
  g = 0;
  b = 0;
  color(r, g, b);
  RGB.color(r,g,b);
  
};

void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(Time.hour());
  printDigits(Time.minute());
  printDigits(Time.second());
  Serial.println(); 
};

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
};

HTML code:

<!DOCTYPE HTML>
<html>

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />

<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.2/jquery.mobile-1.4.2.min.css">


<script type="text/javascript">
      var deviceID    = "  DEVICE ID HERE  ";	
      var accessToken = "  ACCESTOKEN HERE  ";	
      var baseURL = "https://api.spark.io/v1/devices/";	
	  var r = 0;	
	  var g = 0;	
	  var b = 0;
	  var duration;
	  var Colors;	
	  var eventSource = new EventSource(baseURL + deviceID + "/events/?access_token=" + accessToken);	
	  var requestURL = baseURL + deviceID + "/" + "GetColor" + "/?access_token=" + accessToken;	
	  
alert = function() {};  /////////////// comment this function by adding two '//' if you would like to debug. you will see alerts in your browser at almost every step. This makes it easier to see what your code is doing.

		$(document).ready(function(){	
			alert('DOM loaded, I\'m gonna do stuff...');	
			$("#Red ").on( "slidestop", function( event, ui ) {	
				r = document.getElementById('Red').value;	
				Colors = document.getElementById('Red').name + r.toString();
				doMethod("params", Colors);	
			} ); 
			
			$("#Green").on( "slidestop", function( event, ui ) {
				g = document.getElementById('Green').value;        		
				Colors = document.getElementById('Green').name + g.toString();
				doMethod("params", Colors);
			} ); 
			
			$("#Blue").on( "slidestop", function( event, ui ) {
				b = document.getElementById('Blue').value;        		
				Colors = document.getElementById('Blue').name + b.toString();
				doMethod("params", Colors);				
			} ); 			
			
			$("#duration").on( "slidestop", function( event, ui ) {			
				duration = document.getElementById('duration').value
				para = "duration=" + duration.toString();
				alert(para);
				doMethod("params", para);	
			} );
			
			
			$("#off").on( "click", function( event, ui ) {				
				alert('off');  
				r = 0;
				g = 0;
				b = 0;
				multiple = "r=" + r.toString() + ",g=" + g.toString() + ",b=" + b.toString();
				alert(multiple);
				doMethod("params", multiple);	
			} );
			
			$("#sunrise").on( "click", function( event, ui ) {	
				alert("sunrise");
				doMethod("params", "sunrise=0");	
			} );
			
			$("#sunset").on( "click", function( event, ui ) {	
				alert("sunset");
				doMethod("params", "sunset=0");	
			} );

			
			eventSource.addEventListener('color_values', function(e) {	
				alert('Looks like I just received a SSE...'); 
				var rawData = JSON.parse(e.data);
				var parsedData = JSON.parse(rawData.data);	
				color_display.innerHTML = "(" + parsedData.r + "," + parsedData.g + "," + parsedData.b + ")";
				if (document.getElementById('Red').value != parsedData.r || document.getElementById('Green').value != parsedData.g || document.getElementById('Blue').value != parsedData.b){
					alert('Updating stuff.');
					r = parsedData.r;	
					g = parsedData.g;
					b = parsedData.b;					
					updateSliders();
				}
				else {
					alert('It\'s the same...');
				}
				
			}, false);
			
		});
		
		$(window).load(function() {	
			alert('Window loaded, going to execute doMethod for initial request'); 
			doMethod("params","GetColor=0");
		});
	
		function updateSliders(){			
			alert('Going to update sliders RIGHT NOW.');	
				$('#Red').val(r);	
				$('#Green').val(g);						
				$('#Blue').val(b);							
				$('#Red, #Green, #Blue').slider('refresh');			
			alert('Sliders updated!');	
		}
	
 
        function doMethod(method, data) {
          var url = baseURL + deviceID + "/" + method;
          $.ajax({
            type: "POST",
            url: url,
            data: {
              access_token: accessToken,
              args: data
            },
            dataType: "json"
          })
        }		
	
</script>

<body>
	<div data-role="page" id="pageone">	
		<div data-role="content">	

			
			Red:				<input type="range" name="r=" id="Red" min="0" max="255" step="1" data-highlight="true" value="0" >
			Green:				<input type="range" name="g=" id="Green" min="0" max="255" step="1" data-highlight="true" value="0" >
			Blue:				<input type="range" name="b=" id="Blue" min="0" max="255" step="1" data-highlight="true" value="0" >
			Current RGB value:	<span id="color_display"></span>
			<br /><br />
			duration (in ms):				<input type="range" name="duration" id="duration" min="0" max="6000" step="10" data-highlight="true" value="6000" >
			
			<input type="button" value="Off" id="off">			
			<input type="button" value="Sunrise" id="sunrise">
			<input type="button" value="Sunset" id="sunset">
		
			
		</div>
	</div>		
</body>
</html>

I’d suggest running the HTML code with the debugging enabled if you’d like to get a better idea what path the code follows. It’s by no means great coding, far from it. But for me it works (for now).

Any and all suggestions are highly welcome, and sincerely appreciated!

@scsc_tech, Nice project!

3 Likes

@Moors7 That is awesome. I’ve finally finished moving and got to working on my projects again. I’m using a modified version of your code to control the light around my room and living room, but I haven’t figured out how to make one webpage control multiple Cores. Any suggestions? Java isn’t my strong suit…at all!

Great to hear my code is somewhat useful to someone. I haven’t got any experience with Java either, just what I picked up playing around with my Core. It’s one big learning experience, which has been great so far!
Having said that, I looked around Google a bit, and thought the best option here might be a Radio selector. Searching a bit further, I found a JSFiddle which I adapted to work with ‘our’ code. Try this http://jsfiddle.net/k50vtwja/ Copy the code to the corresponding parts in the original code, edit the “values” to the corresponding Cores, and you should be good to go. You can comment out the alerts, those were just for testing.

Let me know if it works, and good luck!