NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » Clock Program.

June 24, 2012
by whitehatyoyoer
whitehatyoyoer's Avatar

Hello, I wrote this clock program to display the time, but there's a problem, it loses time. It loses about 5 second every 10 minutes, which to me isn't good. I've looked over the code multiple times, but can't find anything that would cause the time loss. Here's the code:

// A simple alarm clock, maybe with a few added features.
//written by Tyler Wilber(whitehatyoyoer) for the ATmega168 Nerdkit
//whitehatyoyoer@gmail.com
//This work is licensed under the Creative Commons Attribution 3.0 Unported License.
//To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>

#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"

volatile uint16_t hour=0;
volatile uint16_t min=0;
volatile uint16_t sec=0;
volatile uint16_t mil_sec=0;
volatile uint8_t wait = 0;

void pin_setup()
{
    //Pushbutton -- PC0(pin#23) -- input
    //Hour switch -- PC1(pin#24) -- input
    //Minute switch -- PC2(pin#25) -- input 
    //Second reset switch -- PC3(pin#26) -- input
    //Alarm switch -- PC4(pin#27) -- input
    DDRC &= ~(1<<PC0);
    PORTC |= (1<<PC0);
    DDRC &= ~(1<<PC1);
    PORTC |= (1<<PC1);
    DDRC &= ~(1<<PC2);
    PORTC |= (1<<PC2);
    DDRC &= ~(1<<PC3);
    PORTC |= (1<<PC3);
}

void update_time()
{   
    //read the pushbutton/DIP bit 1/DIP bit 3/DIP bit5 states respectively
    uint8_t pushbutton = (PINC & (1<<PC0)) >> PC0;
    uint8_t hr_bit = (PINC & (1<<PC1)) >> PC1;
    uint8_t min_bit = (PINC & (1<<PC2)) >> PC2;
    uint8_t sec_bit = (PINC & (1<<PC3)) >> PC3;
    //This section changes the time when the button is pressed
    if(mil_sec % 50 == 1)
    {
        wait = 0;
    }
    if(wait == 0)
    {
        if(pushbutton == 0) 
        {       
            wait = 1;
            if(~hr_bit && min_bit && sec_bit)
            //if the hour switch is up
            {
                hour++;
            }
            if(~min_bit && hr_bit && sec_bit)
            //if the min switch is up
            {
                min++;
            }
            if(~sec_bit && hr_bit && min_bit)
            //if the sec switch is up
            {
                sec = 0;
            }           
        }
    }
    //This section update the time when one of the time sections overflow
    if(mil_sec / 100 == 1)
    {
        sec++;
        mil_sec = 0;
    }   
    if(sec / 60 == 1)
    {
        min++;
        sec = 0;
    }
    if(min / 60 == 1)
    {
        hour++;
        min = 0;
    }
    if(hour / 24 == 1)
    {
        hour = 0;
    }   
}

void clock_setup()
{
    //WGM0[2:0] = 010 for CTC, TOP = OCRA -- WGM02 in TCCR0B
    TCCR0A |= (1 << WGM01);
    //CS0[2:0] = 101 for 14.7456Mhz/1024 = 14400hz
    TCCR0B |= (1 << CS02) | (1 << CS00);
    //set TOP(OCRA) to 144 -- 14400hz/144 = 100hz
    OCR0A = 144;
//  8x overclock for testing
//  OCR0A = 16;
    //OCIE0A timer interrupt on output compare match A
    TIMSK0 |= (1 << OCIE0A);
}

ISR(SIG_OUTPUT_COMPARE0A) 
{
//  sec++;
    mil_sec++;
    update_time();
}

int main()
{
    lcd_init();
    pin_setup();
    clock_setup();
    lcd_home();
    FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);

    sei();
    while(1)
    {
        lcd_home();     
        fprintf_P(&lcd_stream,PSTR("%2.2d:%2.2d.%2.2d"),hour,min,sec,mil_sec);
    }
}
June 24, 2012
by esoderberg
esoderberg's Avatar

Whitehat,

Set TOP to 143; because it counts 0, 1, 2,..142,143, 0, 1, 2 ... so 0 through 143 equals 144 events. You're running 144/145 slow, which matches well with what you report 600-5/600 = 595/600.

Eric

June 24, 2012
by whitehatyoyoer
whitehatyoyoer's Avatar

Thanks alot esoderberg, it's been running for over 10 minutes right now and hasn't lost any time. I can't believe I over looked that, I knew that the timer started at 0. It's always simple things that throw you off.

--Whitehat

June 24, 2012
by whitehatyoyoer
whitehatyoyoer's Avatar

So, now after running for over 4 hours it has actually gained 4 seconds. Now I have to figure that out.

--Whitehat

Post a Reply

Please log in to post a reply.

Did you know that the printf format string "%.3f" will show three digits after the decimal point? Learn more...