Trying to get an accurate timer with timer2

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello people, I'm interfacing with the ATMEGA164P and I configured to work with CTC mode with timer 2 an also with interrupts.

 

It seems to work great in simulations but its definitely not accurate. 

 

My target time is 25mS, and my current error is like 1ms more than the selected time.

something like 25mS + 1 = 26mS and goes on and on.

 

I will put the code, it's just togglin two leds.

PB0 every 25mS

PB1 every 1 Second.

 

Thanks for your time and I'm hoping that's something wrong with my configuration.

#define  F_CPU 8000000
#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned int elapsed = 0;

void timer2_init()
{
	// Set up the Timer2 CTC mode
	TCCR2A |= (1 << WGM21);

	// Enable CTC Interrupt
	TIMSK2 |= (1 << OCIE2A);

	TCNT2 = 0;

	// target time: 25mS approx
	OCR2A = 25;

	// Start timer at Fcpu/1024
	TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);

	// Enable global Interrupts
	sei();
}

int main(void)
{
	// Set up the PB0 as OUTPUT
	DDRB |= (1 << DDB0);

	DDRB |= (1 << DDB1);

	timer2_init();

	return 0;
}

ISR(TIMER2_COMPA_vect)
{
	PORTB ^= (1 << PB0);	// toggle the LED
	elapsed++;
	if (elapsed == 40)
	{
		elapsed = 0;

		PORTB ^= (1 << PB1);
	}
}

 

Last Edited: Thu. Sep 28, 2017 - 09:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

fabianpi wrote:

// target time: 25mS approx
OCR2A = 25;

 

The timer starts counting starts from 0, so that would indeed result in 26ms.

 

Scratch that, didn't read your OP properly! I would question your timing calculations though, you define your clock as 8 MHz (and I'll assume you've checked that Fcpu is indeed 8 MHz...) and apply a prescaler of 1024, results in a timer frequency of 7,812.5 kHz, meaning each tick or cycle is 128us. You're interrupt will be fired every 25 ticks meaning your interrupt should be fired every 3.2ms... Are you absolutely sure your CPU is running at 8 MHz? (note, simply #define'ing F_CPU as 8000000 isn't enough)

Last Edited: Thu. Sep 28, 2017 - 10:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In that case I will always have 1ms of time difference between the real time and the target one?

 

Setting 24mS fix the first one, but the problem stills on the next signals.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also caveat: what are you using as the F_CPU? Is it the internal RC oscillator or an external crystal? If you use internal RC, you could have an error up to several percent.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In main() you have a return 0;
What is it going to return to? This will cause the code to restart.
Put a while(1); instead. This is an embedded system - there is no operating system to return to, so either you sleep or execute code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I doubt you're running at 8MHz. Probably 1MHz.
As was said, /1024 would lead to 128us ticks. 25 ms would take 195.3125 ticks, not 26.
CTC mode is zero-based, so you'd set OCR2A to 194 to get a period of 195, which would be close to 25ms, but slightly less (24.96).
You've set it to 25, so the period is 26. If that gets you 26 ms, you are >>not<< running at 8MHz..
And as mentioned, returning from main will disable all interrupts.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Thu. Sep 28, 2017 - 11:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I agree that the system is not running at 8MHz; it is running at 1MHz (the default factory internal RC clock speed).  At sysclock/1024, a 1MHz clock will produce 26 mS intervals with a CTC Timer setting of 25.

 

Disable the fuse for CLK/8 in the low fuse section.  This will run your CPU at 8MHz.  Now set your timer 2 CTC value to 195, and you will get interrupts quite close to 25 mSec.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:
Now set your timer 2 CTC value to 195,
joeymorin wrote:
CTC mode is zero-based, so you'd set OCR2A to 194 to get a period of 195
Wonder which one of those is right? Umm, let me see....