Arduino and SnoRRRhea: making an unusual alarm clock's hardware
Making the SnoRRRhea alarm clock hardware with an Arduino Diecimila, an LCD screen, a Piezo buzzer, a breadboard, a potentionmeter and lots of wires.
To write the LCD display, we had to look for the specs of the Xiamen Ocular GDM1602K. This model's connections do not come inthe same order as in the Arduino LCD tutorial, which was a slight complication. Some guesswork was required to find out which acronyms in the product spec related to the LCD tutorial's description.
The LCD display requires the use of a Potentiometer. Luckily, this little thingy, which we first mistook for a little joystick, came with our Arduino set. It controls the LCD's contrast.
We should also note that we were able to go almost through the whole Learn Electronics using Arduino tutorial with this set, which differs from the one from Adafruit that the tutorial suggests. Shipping from the US may take very long in customs. Getting the board from Italy to the Netherlands is very fast.
After a few iterations with the software that we use on the board, we added a Piezo buzzer. This one's attached to a digital pin, which we flip between HIGH and LOW very quickly when the alarm goes off.
The software part uses the LCD4Bit library instead of the default LCD library. We thought using four fewer pins might be a good idea, should we want to attach more components in the future. As of this writing, we still have five pins unused.
While trying the alarm clock for the first time, we found a bug. The alarm went off two hours too late. In fact, the alarm clock showed the right time. So the problem was with our timing. The naive approach that we took was to delay a thousand seconds after every loop. We were expecting our loop to be run once a second this way. But naturally, as we found out, it takes longer than that for a loop to complete. It takes 1000ms plus the time it takes to update the LCD!
We had to find another solution. After wondering about the availability of <time.h>, we found out that there's a function called millis() that'll help us do what we want to do: We want to measure how long it takes to update the LCD, and subtract that from the 1000ms to delay.
However, the millis() documentation warns us that this value (an unsigned long) will flip back to 0 after approximately 9 hours and 32 minutes. This is bad news for an alarm clock. :-)
So now we went back to the code to revise it a last time (as of this writing): If the number of milliseconds at the end of the loop was lower than the number that it was at the beginning of the loop, we'll simply delay for 1000ms. Yes, this means that the clock will shift a few milliseconds after nine and a half hours, but what the heck!
Here's the code:
#include <LCD4Bit.h>
#undef int() //hack for arduino 0011 to allow use of stdio:
#include <stdio.h> //gives us function sprintf
//create object to control an LCD.
LCD4Bit lcd = LCD4Bit(2); //2 lines
int sec=55;
int min=55;
int hour=22; //keep track of time
int amin=56;
int ahour=22; //keep track of alarmtime
char time[9]; //string thats pushed to LCD
void setup() {
pinMode(13, OUTPUT); //we'll use the debug LED to output a heartbeat
pinMode(3, OUTPUT); // connected with buzzer
lcd.init();
lcd.clear();
//optionally, now set up our application-specific display settings, overriding whatever the lcd did in lcd.init()
//lcd.commandWrite(0x0F);//cursor on, display on, blink on. (nasty!)
}
char* inctime() {
sec=sec+1;
if(sec==60) {
min=min+1;
sec=0;
}
if(min==60) {
hour=hour+1;
min=0;
}
if(hour==24) {
hour=0;
}
if(sec%2==0) { //true if sec is even number
sprintf(time, "%2d:%2d:%2d", hour, min, sec); //shows blinking : every even sec
} else {
sprintf(time, "%2d %2d %2d", hour, min, sec); // : are off every uneven sec
}
return time;
}
void loop() {
unsigned long msbegin=millis();
unsigned long msafter;
digitalWrite(13, HIGH); //light the debug LED
lcd.cursorTo(1, 0); //line=1, x=0.
lcd.printIn(inctime());
digitalWrite(13, LOW); //13 is heartbeat pin
lcd.cursorTo(2, 0);
lcd.printIn("snoRRRhea");
if(ahour==hour && amin==min){ // alarm goes off for 60 secs
//during alarm effect of "vanishing" characters from left to right
lcd.cursorTo(2, sec%9); // sec%9 is rest of integer division sec/9
lcd.printIn(" "); //moving space sign that covers the letters
digitalWrite(3, HIGH); //buzzer on
}
lcd.cursorTo(2, 11);
sprintf(time, "%2d:%2d", ahour, amin);
lcd.printIn(time);
digitalWrite(3, LOW); //buzzer off
msafter=millis();
if (msafter<msbegin) { //millis reset to zero after 9 hours
delay(1000)
} else {
delay(1000-(msafter-msbegin));
}
}
Tonight we're going to try it out again to see how accurate the clock still is when we wake up. We won't rely on it as our only alarm clock yet because the buzzer is a bit low volume. :-)
Remember that the idea is that the alarm clock triggers SuperCollider to play samples of yourself while you were asleep. More of this next time.

