0
\$\begingroup\$

I want to create a real-time clock using ATmega328p microcontroller. The microcontroller's frequency is 1 MHz. So, I think I should use timer interrupts in CTC mode to generate interrupt every second. I have calculated the value for timer CTC mode:

`n = t * f - 1
  • n - number of cycles for CTC mode.
  • t - target time.
  • f - frequency.
  • - 1 because it takes one cycle to reset the counter.

I set the frequency divider by 64 for the timer.

n = 1 s * (10^6 Hz / 64) - 1
n = 1 s * 15625 Hz - 1
n = 15625 - 1
n = 15624

So, I have code:

#include <avr/interrupt.h>
#include <util/delay.h>
#include <time.h>
static unsigned long t = 0;
ISR(TIMER1_COMPA_vect) {
 t++;
}
static void InitializeTimer() {
 cli();
 OCR1A = 15624;
 TCCR1B = (1 << WGM12) | (1 << CS10) | (1 << CS11);
 TIMSK1 = (1 << OCIE1A);
 sei();
}
[[noreturn]] int main() {
 InitializeTimer();
 LCD_SetUp(PC_5, PC_4, PC_3, PD_0, PD_1, PD_2, PD_3, PD_4, PD_5, PD_6, PD_7);
 LCD_Init(2, 16);
 while(true) {
 tm* time = gmtime((time_t*)&t);
 LCD_Clear();
 LCD_Printf("Time: %02d:%02d:%02d", time->tm_hour, time->tm_min, time->tm_sec);
 _delay_ms(100);
 }
}

This code prints number of seconds since the start of the microcontroller to an LCD display. It really does, but since even 3 minutes time error is 2 seconds, since 10 minutes time error is 5 seconds, since 45 minutes time error is 30 seconds. I checked the time error using my phone's stopwatch. Why there is a time error? Error during calculation? What are the reasons for this? Thanks in advance!

asked Jan 2, 2021 at 21:36
\$\endgroup\$
6
  • 2
    \$\begingroup\$ What are you using as the clock source for the AVR? I suspect it's the internal oscillator and if so, that is unsuitable for your purpose. You should switch to an external crystal clock source at least. Better yet would be an RTC chip with a precision crystal oscillator if you need accurate timekeeping. \$\endgroup\$ Commented Jan 2, 2021 at 21:42
  • \$\begingroup\$ Incidentally, because it's an 8bit machine, you should be aware of accessing the 16bit value "t" from the main code, as I believe it may be modified by the interrupt in the middle of being read from memory. The safe way to do it is wait until interrupt has just gone off, temporarily disable the interrupt, make a copy of t, and turn the interrupt back on immediately after that. \$\endgroup\$ Commented Jan 2, 2021 at 21:45
  • \$\begingroup\$ @jwh20, I'm using an inner crystal clock source by default in AVR microcontrollers. It's not suitable for real time clock? \$\endgroup\$ Commented Jan 2, 2021 at 21:48
  • 1
    \$\begingroup\$ @manueld4722623 the 328P internal clock isn't a crystal. And its accuracy is specified as +/- 10%. You're getting within about 1%, which is about as good as you could expect. \$\endgroup\$ Commented Jan 2, 2021 at 21:59
  • 1
    \$\begingroup\$ There is no "internal crystal" in AVR microcontrollers. There is a calibrated oscillator but the datasheet says +/- 2% @ 25C. That's enough for many purposes but not for an RTC in general or for your purpose. See page 260 at: ww1.microchip.com/downloads/en/DeviceDoc/… \$\endgroup\$ Commented Jan 2, 2021 at 22:13

1 Answer 1

2
\$\begingroup\$

The AVR's internal oscillator is unsuitable for your purpose. This is from the datasheet:

AVR RC Accuracy

You should switch to an external crystal clock source at least. Better yet would be an RTC chip with a precision crystal oscillator if you need accurate timekeeping.

answered Jan 2, 2021 at 22:16
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.