using two timers for time control

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

Hello.

I use an atmega16 at 16 MHz.
The microcontroller "talks" with spi to a DAC in order to produce a specific waveform of potentials. For the timing I use timer2 in CTC mode with a tick of 1 millisecond.
Also I need to toggle two pins (enable/disable of two switches) with accuracy of 1 microsecond.
Instead of using a software delay
ex.

_delay_us(10); //wait for 10us

I decided to use timer0 of atmega16 with 1 microsecond tick.
I have the interrupts setup, each one increments a "volatile" variable and in the main program I check the timers volatile variables in order to see if it's time to change something according to timing.

The problem is that timing gets real bad, perhaps out of control and I cannot understand why?

Thank you for your help.

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

kakarot wrote:
Hello.

I use an atmega16 at 16 MHz.
The microcontroller "talks" with spi to a DAC in order to produce a specific waveform of potentials. For the timing I use timer2 in CTC mode with a tick of 1 millisecond.
Also I need to toggle two pins (enable/disable of two switches) with accuracy of 1 microsecond.
Instead of using a software delay
ex.

_delay_us(10); //wait for 10us

I decided to use timer0 of atmega16 with 1 microsecond tick.
I have the interrupts setup, each one increments a "volatile" variable and in the main program I check the timers volatile variables in order to see if it's time to change something according to timing.

The problem is that timing gets real bad, perhaps out of control and I cannot understand why?

Thank you for your help.

Running the Timer0 with a period of 1us and firing interrupts is a tall order. Your micro is running only at 16MHz, so there will only be 16 clock cycles between consecutive Timer0 interrupts. Therefore, you have to complete the Timer0 interrupt service routine within less than 16 clock cycles. This can be done, but if, for example, it uses 12 cycles, then only 4 out of every 16 processor cycles will be left for everything else you want to do.

Furthermore, unless you have taken special steps with your coding, the Timer2 interrupt service routine will block the Timer0 routine. That is, the Timer0 interrupt routine will not run at all while the Timer2 routine is running. This is because the AVR architecture does not naturally prioritise or nest interrupts.

I think you need to look again at your design, and see whether your can do your switch-toggling task using hardware features of Timer0, rather than by relying on software in an ISR to toggle pins.

[EDIT: Having read your post a little more thoroughly, I see that you're actually incrementing a variable in the Timer0 ISR, and then monitoring that in the foreground thread to determine when to toggle the pins. This will introduce a random delay between the timer tick and the pin toggling, which will be exacerbated by the blocking effect of Timer2. If, with some careful coding you can do the pin toggling in the ISR of Timer0 in less than about a dozen cycles, AND you can make the Timer0 ISR nest inside the Timer2 ISR, then you might be able to do what you want. But it still strikes me as a sub-optimal design.]

Christopher Hicks
==

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

I see what you mean. Is it a better idea a RTOS?

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

kakarot wrote:
I see what you mean. Is it a better idea a RTOS?
No, probably not. That will, most likely, introduce even more timing uncertainty.

CH
==

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

ok. Thanks

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

kakarot wrote:
The microcontroller "talks" with spi to a DAC in order to produce a specific waveform of potentials. For the timing I use timer2 in CTC mode with a tick of 1 millisecond.
That should work well enough on its own.

kakarot wrote:
Also I need to toggle two pins (enable/disable of two switches) with accuracy of 1 microsecond.
If the toggle pattern is just that, look at the output compare functions of the timer. You can generate signals directly from the timer hardware, no interrupts involved! Read [TUT] [C] Newbie's Guide to AVR Timers and pay particular attention to Part 6.

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

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

Dear friends,
I have an idea I would like you to comment.

I am thinking of using a timer on CTC mode
that overflows every ms, but has a 0.5 microsecond tick
(16MHz crystal - prescaler 8 ).
Then for accurate control of specific pins
I can use TCNT register's value.
for example If I need pinb0 to be high for ten
microseconds I have to check if TCNT has increased by 20 (10/0.5=20)

Is this the proper way to do something like this?
Most of my peripherals use interrupts (spi, usart, etc)
and I worry about the accurate control of everything!

Thanks in advance

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

Quote:

Is this the proper way to do something like this?

Generally, for accuracy and repeatability and no jitter, you let the timer do the work.

-- Connect the signals to OCxx pin(s).
-- Set up the timer to do what you need when the compare match is reached.
-- Fire an interrupt upon compare match, and then disable the mechanism.

Much depends on the range of the pulse durations, whether it is a repeated waveform, what the period is, and other considerations.

It took you two years to get back to this? ;)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Almost two years...
The problem is I work and I am a chemist not
an electronics technician!
I have to open and close two switches.
SW1 opens for 30 microseconds and closes for either
100 microseconds, 1 millisecond, 10 millisecond,
100 milliseconds or 1 second (it depends on what I want to do).
SW2 closes for 10 microseconds after SW1 is open for 10 microseconds.
What you tell me about output compare pins I guess
is not compatible with this application.
Thanks anyway!