Arduino Alarm Clock?

Greetings All

after 10 years hiatus, I decided it was time to play around with programming again. I picked up an Arduino Uno kit and am slowly going through the examples.

I thought I started with a modest goal to build an alarm clock. The time.h library should make this easy. I scripted this as a quick test:

#include <LiquidCrystal.h>
#include <Time.h>  
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int switchPin=6;
int prevSwitchState = 0;
int columnCount = 1;
int rowCount = 0;


void setup() {
lcd.begin(16,2);
lcd.clear();
pinMode(switchPin,INPUT);
lcd.noDisplay();
setTime(21, 41, 15, 18, 3, 2015);


}
void loop() {

lcd.display();
lcd.setCursor(0,0);
lcd.print(hour());
lcd.print(":");
lcd.print(minute());
lcd.print(":");
lcd.print(second());

lcd.setCursor(0,1);
lcd.print(month());
lcd.print("/");
lcd.print(day());
lcd.print("/");
lcd.print(year());
delay(500);

lcd.clear();

}

For testing purposes, I set the clock once and start the sketch. The plan is to get more sophisticated as I get better.

However, the clock is slow by nearly 1 minute / day and therefore can not be suitable for a stand-alone clock project.

So, my questions:

  • is this something I did wrong in the code?
  • could the power supply be having an influence? So far, I only powered the Arduino from the USB of the laptop.
  • is there a chance I just have “bad hardware” anywhere? (I can “borrow” another Arduino from work)

If this approach doesn’t work, I find an external crystal but since the library exists, I assumed it would be accurate (enough).

Any advice for a beginner who wants to learn?

Many thanks!

is this something I did wrong in the code?
Probably not. The Arduino UNO uses a ceramic resonator for timing and is only accurate to a couple of minutes per day. For a clock source most people use an external RTC (Real-Time Clock) chip with a backup battery. This modules are available for a few dollars. If you have a window nearby you can get precise and self-setting time from a GPS module. They cost $12 and up.

could the power supply be having an influence? So far, I only powered the Arduino from the USB of the laptop.
That shouldn't be a problem.

is there a chance I just have "bad hardware" anywhere? (I can "borrow" another Arduino from work)
Your hardware is doing what it is designed to do.

Thanks johnwasser, much appreciated. I didnt know the accuracy of the clock, guess, I should have checked the datasheet.

I'll use clock chip as you recommend in the future. But at least now I know I didn't goof up!

You may try this, it use micros() to keep time.

// a clock program no RTC



unsigned long currentMicros;
unsigned long previousMicros;
unsigned long elapsedTime;

byte hundredths;
byte tenths;
byte secondsOnes;
byte oldSecondsOnes;
byte secondsTens;
byte minutesOnes = 0;
byte minutesTens = 4;
byte hoursOnes = 1;
byte hoursTens = 1;

void setup(){

  Serial.begin(115200); // make serial monitor match
  currentMicros = micros();
  previousMicros = currentMicros;
  Serial.println ("Setup Done");
}

void loop(){

  currentMicros = micros();

  // how long's it been?
  elapsedTime = currentMicros - previousMicros;
  Serial.print ("Elapsed: ");  
  Serial.println (elapsedTime);
  if ( elapsedTime >=10000UL){  // 0.01 second passed? Update the timers
    elapsedTime = 0;
    previousMicros  = previousMicros + 10000UL;
    hundredths = hundredths+1;
    if (hundredths == 10){
      hundredths = 0;
      tenths = tenths +1;
      if (tenths == 10){
        tenths = 0;
        secondsOnes = secondsOnes + 1;
        if (secondsOnes == 10){
          secondsOnes = 0;
          secondsTens = secondsTens +1;
          if (secondsTens == 6){ 
            secondsTens = 0;
            minutesOnes =  minutesOnes + 1;
            if (minutesOnes == 10){
              minutesOnes = 0;
              minutesTens = minutesTens +1;
              if (minutesTens == 6){
                minutesTens = 0;
                hoursOnes = hoursOnes +1;
                if (hoursOnes == 10){
                  hoursOnes = 0;
                  hoursTens = hoursTens =1;
                  if (hoursOnes == 4 && hoursTens ==2){
                    hoursOnes = 0;
                    hoursTens = 0;
                  }
                }
              } // minutesTens rollover check
            } // minutesOnes rollover check
          } // secondsTens rollover check
        } // secondsOnes rollover check
      } // tenths rollover check
    } // hundredths rollover check
  } // hundredths passing check



  if (oldSecondsOnes != secondsOnes){  // show the elapsed time
    oldSecondsOnes = secondsOnes;
    Serial.print ("Time: ");
    Serial.print (hoursTens);
    Serial.print(hoursOnes);
    Serial.print(":");
    Serial.print(minutesTens);
    Serial.print(minutesOnes);
    Serial.print(":");
    Serial.print(secondsTens);
    Serial.println(secondsOnes);

/*
 if ( hoursTens == 0 && hoursOnes == 6 ** minutesTens == 0 && minutesOnes == 0 && secondsTens == 0 && secondsOnes == 0){
// alarm time!
}
*/

  } // end one second check
} // end loop

/*

#define MINUTE 60UL
#define HOUR 3600UL // MINUTE * 60
#define DAY 86400UL // HOUR * 24
#define WEEK 604800UL // DAY * 7

unsigned long actionTime = 0;

if ( now() > actionTime) // time to do stuff yet?
  {
  // do stuff
  actionTime = actionTime + DAY; // re-schedule for same time tomorrow
  }
 



digitalWrite (ssPin, LOW);
SPI.transfer(fontArray[HoursTens]);
SPI.transfer(fontArray[HoursOnes]);
SPI.transfer(fontArray[MinutesTens]);
SPI.transfer(fontArray[MinutesOnes]);
SPI.transfer(fontArray[SecondsTens]);
SPI.transfer(fontArray[SecondsOnes]);
digitalWrite(ssPin, HIGH);



digitalWrite (ssPin, LOW);
for (x=0; x<6; x=x+1){
SPI.transfer(fontArray[timeElements[0]]);
}
digitalWrite(ssPin, HIGH);




 
*/

BillHo:
You may try this, it use micros() to keep time.

Sadly, using micros() won't make the ceramic resonator any more accurate.