Moving SW mega64 with 4 timers to mega8 (3 timers!)

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

Hi,
I have a project on (test-)mega64 and it uses all 4 available timers.
After brushing&brushing, optimizing, etc, I managed to squeeze the code size to an incredible 5174 bytes so it can easily fit into a mega8 (I have one here).
Unfortunately, mega8 has only 3 timers available while the proggy requires 4 timers:
- timer0: motor1
- timer2: motor2
- timer3: remote-control sampler
- timer1: multi-timer (various actions triggered by this timer...)

I'm stuck right now... I really don't have any idea how to fix this problem! :?
So, any clue, any idea or trick that would help me to move the project from mega64 to mega8 (a cheaper AVR) ?!?

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

You could set timer 1 to a fast interrupt - a multiple of both your existing multi-timers and the remote control timer - and spawn fake interrupts in your main loop from there... difficult to make useful recommendations without a little more data regarding intervals and frequencies :)

Neil

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

Is it possible to combine both motor controls into a single timer with dual output-compare channels, such as the ATmega88?

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

Quote:
difficult to make useful recommendations without a little more data regarding intervals and frequencies

Oh, yes... I forgot to mention these data:
- timer0 and timer2: 1...10 ms (not constant; actual value is changing while driving the servo-motors);
- timer1: a lot of trigger-flags running at 100 ms granularity;
- timer3: sampling remote-control Rx signal @ about 123 us (I could change it to 370us if that would help somehow...).

Not very encouraging, isn't it? ... :-(

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

Last Edited: Tue. Feb 21, 2006 - 01:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

lfmorrison wrote:
Is it possible to combine both motor controls into a single timer with dual output-compare channels, such as the ATmega88?

Aaa... I'm not sure what is "dual output-compare channels". I'll have to check the mega88 datasheet.
All I can say is that I use timer0 to control (fast PWM) the first servo-motor: full speed, low speed, brake and idle (I simplified it a little bit). The same goes for timer2 controlling the second servo-motor. And, of course, the servos are operating simultaneously...

Damn, I didn't take into account mega8 has only 3 available timers... :(
This is so annoying! :x

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

In some of the newer devices, such as the ATmega88, you can use the Watchdog timer to generate general interrupts. However, it doesn't seem to be possible to calibrate the watchdog timer, and its frequency varies over temperature and supply voltage. You also don't get very many choices in granularity.

Could you replace the Timer1 heartbeat with the Watchdog?

If you went down this road, however, and you also wanted to use watchdog facilities for integrity protection, then you'd need to add an external wathdog chip.

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

Quote:
You could set timer 1 to a fast interrupt - a multiple of both your existing multi-timers and the remote control timer - and spawn fake interrupts in your main loop from there...

Yep... I was thinking about that too, but wouldn't it be overkill to interrupt the main thread every few hundreds of microseconds? Not that the main loop would have some important job to do, but it's just scary for me to chop it with so much "anger"...

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

Dual output compare-channels: Timer0 has 2 output-compare registers, OCR0A and OCR0B. Each OCR0x register is independantly compared against TCNT0, and in FastPWM mode, each can be used to trigger PWM waveforms with independent duty cycles. Note that you would be obliged to use the same fundamental PWM frequency on each channel.

The same is true of Timer2, with its OCR2A and OCR2B.
__________________

You could get the same effect on an ATmega8 if you re-distributed the jobs of the various timers... Timer0 on the ATmega8 doesn't have any PWM or output-compare functionality at all. But you should be able to get it to generate a reasnably good 100-millisecond heartbeat using a high prescaler and re-seeding TCNT at the beginning of the interrupt service routine.

Then you could use Timer2 to do the IR decoding.

And Timer1, with its dual OCR register set (OCR1A and OCR1B) can be used to control the two servos.

Last Edited: Tue. Feb 21, 2006 - 01:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
In some of the newer devices, such as the ATmega88, you can use the Watchdog timer to generate general interrupts. However, it doesn't seem to be possible to calibrate the watchdog timer, and its frequency varies over temperature and supply voltage. You also don't get very many choices in granularity.

Could you replace the Timer1 heartbeat with the Watchdog?


Aaa... yeah, I could probably replace my 100 ms granularity with - let's say - 125 ms (according to the datasheet it's not very precise, but acceptable at this point...). Also, the "interrupt mode" allows me to avoid resetting the micro by the doggy.
Is this the way you suggest to go ? [mega88 - no watchdog protection]

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

I'd suggest having a single system tick of the smallest granularity you need. My apps typically use somewhere between 2.5ms and 10ms, but I have some with 1ms ticks. Then run all you "events" and "tasks" by counting those ticks with soft timers.

Also, if your "motor" timers are always running and with a fixed frequency you can use compare match or overflow interrupts on those timer(s) as the "tick".

Lee

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

Quote:
You could get the same effect on an ATmega8 if you re-distributed the jobs of the various timers... Timer0 on the ATmega8 doesn't have any PWM or output-compare functionality at all. But you should be able to get it to generate a reasnably good 100-millisecond heartbeat using a high prescaler and re-seeding TCNT at the beginning of the interrupt service routine.

Then you could use Timer2 to do the IR decoding.

And Timer1, with its dual OCR register set (OCR1A and OCR1B) can be used to control the two servos.


Yes, this is probably the best way to go, because I only have a mega8 (no mega88 for the moment). Ok, thx very much! :-)
I'll have to analyze this idea and put some order into my thoughts... Then, I'll make some changes in the SW (and HW also - yuck!). We shall see...

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

Lee: It appears to me that's what Stanley's already doing. The IR decoder seems to need to operate at a very high frequency, and it would seem to be inappropriate to be using that frequency as the basic system tick.

The two motor timers appear to be used for generating FastPWM duty cycles for servo control. No point wasting CPU time controlling that, if you can make do with occasionally adjusting the OCR's instead for duty-cycle adjustment.

And everything else uses multiples of the 100ms tick.

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

theusch wrote:
I'd suggest having a single system tick of the smallest granularity you need. My apps typically use somewhere between 2.5ms and 10ms, but I have some with 1ms ticks. Then run all you "events" and "tasks" by counting those ticks with soft timers.

I'm already doing this with timer1 @ 100 ms. Somehow I don't feel very comfortable to lower the tick down to less than 10ms. Too paranoid I guess :lol: But, of course, I must admit this will probably save me 2 hardware timers! I'll think about it.

Quote:
Also, if your "motor" timers are always running and with a fixed frequency you can use compare match or overflow interrupts on those timer(s) as the "tick".

The servo timers are not running all the time. In fact, I'm using OC0/OC2 to drive some triacs, but only when a valid command has been received from the remote control. Similar to what you suggested?
Thx Lee!

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

lfmorrison wrote:
Lee: It appears to me that's what Stanley's already doing. The IR decoder seems to need to operate at a very high frequency, and it would seem to be inappropriate to be using that frequency as the basic system tick.

The two motor timers appear to be used for generating FastPWM duty cycles for servo control. No point wasting CPU time controlling that, if you can make do with occasionally adjusting the OCR's instead for duty-cycle adjustment.

And everything else uses multiples of the 100ms tick.


Yes, indeed! :-)
Except that I am "occasionally adjusting " TCNT0 / TCNT2 in order to drive the triacs (a tiny pulse to kick each of them - firmly).

BTW: The "client" requested the servos to operate quasi-independent, that's why things may seem so complicate.

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

Last Edited: Tue. Feb 21, 2006 - 02:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
timer3: sampling remote-control Rx signal @ about 123 us (I could change it to 370us if that would help somehow...).

Maybe you could elaborate on this - when you say about... and what's the relationship between "about 123uS" and 370uS ?

Four legs good, two legs bad, three legs stable.

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

Quote:
Maybe you could elaborate on this - when you say about...

Needed timer: 123 us
AVR Calc suggests: 124.49 us (don't ask why...)

Quote:
and what's the relationship between "about 123uS" and 370uS ?

about 123 x 3 = 370 :-) (... rounded up)
So:
3 samples / RC bit @ 123 us. Just to select "2 of 3" (majority law) in order to get rid of noise.
Otherwise, I suppose I can use only one sample @ 369 us tick. Something wrong here?... except the rounding up to 370 - dirty!

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

Well I think I'd stick with 123 uS and "run" my ticks once every 813. What's the clock speed?

Four legs good, two legs bad, three legs stable.

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

John_A_Brown wrote:
Well I think I'd stick with 123 uS and "run" my ticks once every 813. What's the clock speed?

Clock speed: 7.372800
123 x 813 = 99,999 = 100 msec ( :shock: good idea... I think)
Thx John!

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

As I mentioned in some other thread, I have a product which uses a periodic interrupt (written in C) every 45 uS with a 7.373800 crystal. I initially worried that it would use too much "bandwidth", but in reality there were no problems at all.

Four legs good, two legs bad, three legs stable.

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

With the 'mega8, you'll still run into problems in the fact that Timer0 doesn't have PWM or OCR capabilities. Whatever you do with that timer, you'll have to make do with overflow interrupts, and/or manual waveform generation.

I suppose you could use Timer1 in 8-bit mode for one servo, and use Timer2 for the other servo, to take care of the occasional "triac kick" problem and still have access to hardware PWM.

But you'd still have the challenge that Timer0 overflows would have to be carefully seeded, and you'd be left with non-deterministic jitter (and associated accumulating error) due to having re-seeded the counter at the beginning of each ISR. You'll have to evaluate how that might affect your IR decoding.

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

I this will at least take the the time passed before getting here into account
I used it for a 10ms "tick"

SIGNAL (SIG_OVERFLOW0)
{
	TCNT0 = (256 - LOOP_10MS) - TCNT0; // Re-init timer , adjust for values counted up before we reached here
	LED_PORT ^= (1 << TIMER_LED); //Just flip a bit , so we can put a freq meter on to check pulsetime
}

/Bingo

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

Merge Timer1 into Timer3.

DFR

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

I designed a hobby servo controller last summer based on at ATMEGA162 that controlled 32 servos. If you aren't familiar with them - these servos are controlled with a 1-2ms pulse at 50hz (with the pulse width controlling their angle). I made all 32 PWM signals with a single 16b timer. My strategy was to have an ordered array of when each pulse was needed, so as soon as one timer compare interrupt was fired it would load in the next interrupt value. Maybe something like that could help you eliminate your dependence on so many timers?

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

lfmorrison wrote:
With the 'mega8, you'll still run into problems in the fact that Timer0 doesn't have PWM or OCR capabilities.

Oh yes, I noticed! What a pity! (or maybe I should say... PITA).

Quote:
But you'd still have the challenge that Timer0 overflows would have to be carefully seeded, and you'd be left with non-deterministic jitter (and associated accumulating error) due to having re-seeded the counter at the beginning of each ISR. You'll have to evaluate how that might affect your IR decoding.

Another problem is to re-assign the ex-timer1 (that sets some flags @ 100ms granularity).
Seems ok in theory. I'll have to see if/how it works in real life...

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

nleahcim wrote:
My strategy was to have an ordered array of when each pulse was needed, so as soon as one timer compare interrupt was fired it would load in the next interrupt value.

Sounds interesting...
Aaa... I think I understand the idea; it shouldn't be too complicate to implement the logix for that array... to manage the pulse triggers.

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

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

groenhen wrote:
nleahcim wrote:
My strategy was to have an ordered array of when each pulse was needed, so as soon as one timer compare interrupt was fired it would load in the next interrupt value.

Sounds interesting...
Aaa... I think I understand the idea; it shouldn't be too complicate to implement the logix for that array... to manage the pulse triggers.

It works quite nicely. Someday when I have time (probabaly never) I'd like to move it to a linked list though - originally I thought an array would be faster, but looking back I think a linked list would be more efficient.

I can post some of the more pertinent code if you want.

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

Quote:
I can post some of the more pertinent code if you want.

Yes, it's always good to have an example. :-)
Thx, Michael!

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.