Step 14: Dealing With Inaccuracy

Step 15: Future Improvments

My intention is to create a smart alarm for version 2.0 of the Cwik Clock. I hate waking up to my alarm screaming at me, and I don't trust setting it...

Step 9: Prototyping the Display, Time Setting, and Seconds

Now that we have the base program for running a binary clock, the know-how to read from potentiometers, and are experts in using ammeters, it's time to put it all together! It may look like a rat's nest of cables and components, but you shouldn't have any issues if you follow along step-by-step.

In the following video, I use the reset switch on the Uno to start our program from the beginning (time 00:00). You can see the seconds counting on the analog meter which unfortunately has a max value of 50, not 60 (but we can open it up and swap out the background if desired). Regardless of what the meter reads, it "ticks" 60 times per minute. After a full minute, we see the time change to 00:01, and the analog meter resets. I later switch into time setting mode (this is when the orange LED at the top center turns on), at which point you can see the seconds reset to 0. I set the time to 16:59, and the moment I turn time setting mode off (the orange LED at the top center turns off), the seconds on the analog meter start to count up again. I then wait another minute, at which point the time changes to 17:00.

This program is the controller for a binary clock, with LEDs
attached to digital pins 0 through 10, 12, and 13. 2 potentiometers
connected to A0 and A1 control the hours and minutes respectively,
and only when A2 is pulled high. When A2 is pulled high, an LED on
pin A5 will light up to tell the user that they are in time set mode.
Finally, pin 11 is used with PWM to show the seconds on an analog
ammeter.

This example code is in the public domain.
*/

// This can be modified for debug purposes to make a minute go by quicker.
int ONE_SECOND = 1000; // measured in milliseconds
int DELAY_BETWEEN_LOOP_CALLS = 200; // measured in milliseconds

/**
* This method keeps track of the logical flow of time. If enough time has
* passed since the last time it was called, m_second, m_minute, and m_hour
* will be updated appropriate. This takes into account that millis() rolls
* over roughly every 50 days.
*/
void tick()
{
unsigned long now = millis();
unsigned long msElapsed;

// first we need to find out how much time has passed since the last time we
// called tick()
if (now < m_lastTick)
{
// gasp, either we've succeeded in travelling back in time, or millis() wrapped around!
msElapsed = (MAX_UNSIGNED_LONG - m_lastTick) + now;
}
else
{
msElapsed = now - m_lastTick;
}

// for each second that has passed (hopefully just 1, unless our code is really laggy),
// add 1 second to the time, and increase the minutes & hours if necessary
for (int i = 0; i < msElapsed / ONE_SECOND; ++i)
{
m_lastTick = m_lastTick + ONE_SECOND;

// we set the last tick to now, because when we set m_inTimeSetMode to false,
// many seconds could have passed since the last one, and the time would jump ahead
m_lastTick = millis();
}

/**
* This method checks CLOCK_MODE_SWITCH_PIN to see if it's HIGH. If it is,
* it means we're now in clock set mode (m_inTimeSetMode is set to true), and
* turns the CLOCK_MODE_LED_PIN on.
*/
void checkMode()
{
m_inTimeSetMode = (analogRead(CLOCK_MODE_SWITCH_PIN) > 512);
digitalWrite(CLOCK_MODE_LED_PIN, m_inTimeSetMode);
}