Google Analytics

Sunday, February 22, 2015

Building a clock to help kids tell time

My daughter is about 2 1/2.  She loves learning about colors, shapes, animals, dinosaurs, and all sorts of other things.  However, she's still too young to understand how to read a clock.  But now is a good time to start teaching her.

We wanted a clock that would change colors based on what it was time to do: play quietly, go to bed, get up and play, pick up toys, and so on.  Here is the result:



Alarm clock next to the baby monitors and entertainment center.



To start, I purchased a wife-approved, battery-driven clock from a local retailer for about $10.  This one was perfect for me: it has plenty of room inside, a nice, big face, some weight to it to hold it in place, and, to top it all off, it matched the wall.

OK, enough introduction, let's get down to it.  I've got a Pi running a baby monitor (another project, another write-up, but the LEDs in the lower left corner are a super bright infrared spotlight for night vision on the cameras), so I'll be driving it from that. And I've got some ShiftBrites leftover from version 1 of my DIY Ambilight (scroll down for more info on that project).  Perfect.  Let's build.

First, I needed a power supply.  Since we have an excess of USB ports, that's what we'll use.  I've already built a power supply based on the LM317T and it's been running for 7 or 8 years now.  Using this basic schematic, I built the power supply to take a 5V input:
(credit to http://kb.kaminskiengineering.com/ for the picture)




(I know, my workbench is cluttered.  I do a lot of work on it.)
This power supply is going to supply ~3V to the clock internals and 5V to the ShiftBrite.

Now we need software to test with.  After I could not get this tutorial to work, I found Hive13's project on GitHub.  After playing with it for a bit, I compiled the C program and was getting good tests.  However, I could not figure out a dead simple way to to just set certain colors and the program looped until interrupted - all of this is great for what Hive13 and likely most people want to do with a ShiftBrite on a Pi, but I needed something different.  I forked his GitHub repo and made a few changes, namely the ability to push red, green, blue, purple, yellow, and cyan from the command line and immediately exit.  I also added an "install script" as well as a "crazyclock" script to cycle through the colors.  It's all kind of hackish, but since the code was written for only my specific example, I don't care - but sharing that code back to the community is still the right thing to do.  

Essentially, I just added 6 command line arguments so instead of only having "-c [0-255]" emitting a white color with the given intensity, I've added the following code:

printf("  -R: Set to constant color Red\n");
printf("  -G: Set to constant color Green\n");
printf("  -B: Set to constant color Blue\n");
printf("  -P: Set to constant color Purple\n");
printf("  -Y: Set to constant color Yellow\n");
printf("  -C: Set to constant color Cyan\n");
.
.
.
} else if (opt->mode == RED && opt->constant_value_red >= 0) {
img[0] = opt->constant_value_red;
shiftbrite_refresh();
return 0;
} else if (opt->mode == GREEN && opt->constant_value_green >= 0) {
img[1] = opt->constant_value_green;
shiftbrite_refresh();
        return 0;
} else if (opt->mode == BLUE && opt->constant_value_blue >= 0) {
        img[2] = opt->constant_value_blue;
        shiftbrite_refresh();
        return 0;
} else if (opt->mode == YELLOW && opt->constant_value_yellow >= 0) {
        img[1] = opt->constant_value_yellow;
img[0] = opt->constant_value_yellow;
shiftbrite_refresh();
        return 0;
} else if (opt->mode == PURPLE && opt->constant_value_purple >= 0) {
        img[2] = opt->constant_value_purple;
        img[0] = opt->constant_value_purple;
        shiftbrite_refresh();
        return 0;
 } else if (opt->mode == CYAN && opt->constant_value_cyan >= 0) {
        img[2] = opt->constant_value_cyan;
        img[1] = opt->constant_value_cyan;
        shiftbrite_refresh();
        return 0;

All of this is on GitHub, but essentially calling the binary with "-R 255" will turn the LED red at full brightness and immediately exit.  Simple and straightforward.

It's also worth mentioning that since this box is secure and I didn't want to mess with the proper permissions to grant other users the ability to use SPI, I just changed the setuid attribute of the binary to always run as root.  Again, this would should never fly in a production environment but in this case it's nothing to worry about.  

SPI pins on the Pi.  
Next is the case mods.  There was not enough room to put the ShiftBrite, so my Dremel helped me make it fit. 

 
Essentially from here, I just hooked the Vout pin of the LM317T to the clock's battery terminal lines and attached the ShiftBrite directly to the 5V line coming off of the USB cable.  Then I crammed everything as neatly back in to the case as I could.  I had to cut some pins and use some hot glue to insulate some things, but it worked.


There is a USB cable running in to the back for the power supply and a piece of Cat5e running out the back for data from the Pi.
The clock installed next to the baby monitor cameras.


The last thing is setting the clock color automatically.  I found a nifty little project called Minicron. Essentially, it's a client/server setup that modifies your cron jobs and sends the output back to the server.  It's simple, straightforward to set up, and perfect for what I need (given my lack of web development skills).  I installed it on my web server and on this Pi.  Then I just configure what colors I want the clock to be and when.


Additionally, I've configured ConnectBot on my wife's phone to have different connections that will just log in using a public key and execute "/usr/local/bin/clock -G 255" for play time or "/usr/local/bin/clock -R 75" to turn the clock red at reduced brightness for nap.  The cron job will take care of almost everything, but she needed the ability to change it on demand.  

So, that's pretty much it.  I'll be happy to answer any questions below.  



UPDATE: I realize that I forgot to mention that it is important to keep the clock and Pi synchronized.  Since I use Raspbian on the Pi, here's how I ensure it has correct time by using a Stratum 1 time server in my home town.

apt-get install ntpdate
service ntp stop
update-rc.d ntp disable
echo -e '#!/bin/sh \n/usr/sbin/ntpdate 0.ntp.mst.edu' > /etc/cron.daily/ntpdate
chmod +x /etc/cron.daily/ntpdate
service cron restart

This will get the Pi to update its time every day.  If you notice a skew over the course of a day (since the Pis lack a realtime clock) then you can just move this script to the /etc/cron.hourly folder.  If you do so, please us a different time server than this one.