ATmega328 Timer 0/2 Pulsing, 0 and 180 degrees out of phase.

Hello,

I'm trying to make my Arduino Nano generate two PWM signals of varying pulse length and frequency.

Here is my initial code:

#include <avr/io.h>

void setup() {
  pinMode(3, OUTPUT);
  TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS20);
  //TIMSK2 = _BV(OCIE2B);
  OCR2A = 134;
  OCR2B = 67;

  pinMode(5, OUTPUT);
  TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
  TCCR0B = _BV(WGM02) | _BV(CS00);
  //TIMSK0 = _BV(OCIE0B);
  OCR0A = 134;
  OCR0B = 67;

  TCNT2 = 0;
  TCNT0 = 0; //191
}

void loop() {
  TCCR2A |= _BV(COM2B1);
  TCCR0A |= _BV(COM0B1);
  delay(2);
  
  TCCR2A &= ~(_BV(COM2B1));
  TCCR0A &= ~(_BV(COM0B1));
  delay(2);
}

The first thing I noticed from this code, is that the two timers, timers 0 and 2 are not perfectly in phase here. This is because of the commands:

TCNT2 = 0;
TCNT0 = 0

Upon executing both lines, there is a clock cycle difference between the two PWM signals, 62.5 ns. Exactyly 1/ 16 MHz

The first thing I'd like to know therefore, is how do I get the two timers in exact phase with one another? Looking at the data sheet, there's a block called "Control Logic" which increments the counter for each timer. Is there a way to turn this off and on, or clear it whenever I want? Or is there a better way?

The second thing is, once I've got both timers in sync, what would be the best way to get the second timer 180 degrees out of phase with the first?

Finally, I think my method for generating pulses is a poor implementation, but I've found the literature on using interrupts quite confusing. Are there any examples anyone can refer me to so I can generate pulses correctly.

Hopefully that all makes sense.

Thank you

I did not read your code properly but using timers is the right way to generate pulses.
To get timers in sync you must count cycles. It is problem in C (Arduino), it is better to do it in Assembler. You may try

TCNT2 = 0;
TCNT0 = 1; //TC2 already moved by 1

but maybe some other constant (2 I guess) must be used. Problem is the exact number may vary with used optimizations and may change with seemingly unrelated changes elsewhere in your code. Also interrupts should be disabled - interrupt firing between will cause problems.

Can you use Timer1?

Is so, you can use the fast PWM mode with ICR1 top and get synchronized output on pins 9 and 10.

Otherwise you will need to synchronize the timers with the GTCCR register.

http://www.avrfreaks.net/forum/tut-synchronizing-timers

Since he is not using prescaler he does not need to synchronize it.
But changing speed of Timer0 "breaks" millis and delay. And he uses delay.

Change

TCNT2 = 0;
TCNT0 = 0;  // now TCNT2 = 1

to

TCNT2 = 0;
TCNT0 = 1;

MarkT:
Change

TCNT2 = 0;

TCNT0 = 0;  // now TCNT2 = 1



to


TCNT2 = 0;
TCNT0 = 1;

Problem in C programming is you don't know how much TCNT2 is when writing to TCNT0. The procassor may need to load 1 to a register to put it into TCNT0 and in that case TCNT2 will be 2 at the time TCNT0 is written. But it is possible a register already contains 1 and this register will be used to place 1 to TCNT0. AFAIK you cannot know until you try.

Its worth trying - though rewriting it as asm would be the correct thing to do (then it doesn't matter
what version of the compiler).