Arduino Timer Phase-Shifted Square Waves

1 post / 0 new
Runtime Micro's picture
Runtime Micro
Joined: 07/24/2016 - 9:18am
Arduino Timer Phase-Shifted Square Waves

While developing RTM_TimerCalc, I stumbled onto a surprising ability of the 16-bit Arduino Timer. It could generate multiple square waves (up to three of them in a 2560). But more surprising was how you could shift the phase relation between the waveforms. The next image illustrates...

Animated Image shows phase shift capability of Arduino Timer

Now, I don't know if you'd find this mode useful. Perhaps it would make good show-and-tell for a classroom. Maybe it'd be helpful to test rotary-encoder circuits.

I liked this ability and decided to include it RTM_TimerCalc.

The Arduino Timer CTC Odditity

The Timer mode used to realize this capability is described as Non-PWM in the Atmel datasheet. Its designated as "mode-12 CTC". The CTC part means Clear Timer on Compare.

A surprise was the datasheet CTC-formula used a co-efficient of 2 (usually reserved for dual-slope Phase PWM counting -- which this is not). Plus Atmel's depiction of the Timer ramp was single-slope. Single-slope PWM's in the datasheet don't have a 2 co-efficient in their frequency formula. But, this isn't a true PWM mode. So what gives?

Arduino Timer Compare-Modes can Fool You

It begins to make sense when you realize the Waveform Compare-Mode was set for Toggle (which occurs when the Timer ramp value matches the Output-Compare register value). The Toggle action brings about two important characteristics;

  • The waveform frequency becomes half the Timer frequency.
  • The waveform duty-cycle is always 50%

Now, its hard to follow this stuff without the datasheet info handy. I combined two datasheet snapshots showing the CTC single-slope depiction next to the equation for frequency out. See next image -- click to enlarge.

CTC mode info for 16-bit Atmel Timer shows formula and count slope.

Some key take-aways from the above image are;

  • we see single-slope counting like Fast-PWM
  • we see the output waveform being toggled (divide by 2 action)
  • we see a 2 co-efficient in the formula accounting for the toggle effect
  • we see (1+OCra) which appears in Fast PWM formulas

There's one important thing to realize when you read this section (mode-12-CTC) of Atmel's datasheet. It -only- shows you the (toggle-type) formula and it -only- shows you a toggle derived output waveform. There is only one Output-compare mode that works as a toggle (I call it mode-1 out of 0, 1, 2, 3 bit-field selectors). You can see that mode selected in the following image.

Image shows selection of Toggle mode for waveform output-compare.

Yet, there are other modes and they can be useful to advanced techie-types who want to combine software and Timer hardware in clever ways. But that's beyond the needs of many hobby types.

So, I advise caution if you dial up those other Waveform modes. You'll see a "don't use -- advanced mode" message in the chart window. You actually can use the extra modes via RTM_TimerCalc. Its just alerting you of possibility diving into a deep rabbithole. Consider yourself warned.

Arduino Phase-Shifted Square Waves Example

I decided to add some code for this tip in case folks don't care to download the WYSIWYG PWM app. I chose an output frequency of 25 KHz. And I'm guessing the phase relation is close to 90 degrees. It has the exact same Output-compares as shown in the picture displayed directly above.

// generated by: RTM_TimerCalc --
// Timer1 Mode_12_16Bit_CTC_MAX_is_ICR

TCCR1A = 0x50; // 0101 0000
TCCR1B = 0x19 | 1; // Prescale=1

ICR1 = 320-1;

OCR1A = (int) (ICR1 * 0.55);
OCR1B = (int) (ICR1 * 0.05);

// UnComment following lines for UNO-NANO Timer-1 Pins 
// pinMode(9, OUTPUT); 	// OC1a
// pinMode(10, OUTPUT); // OC1b

// UnComment following lines for 2560 Timer-1 Pins 
// pinMode(11, OUTPUT); // OC1a
// pinMode(12, OUTPUT); // OC1b

Unfortunately, I just discovered a bug in the Code generator. Its calling out Mode-12 as 16Bit_CTC_MAX_is_ICR -- which is wrong. It should read 16Bit_CTC_TOP_is_ICR. Max is 65,535 (2^16-1) for this situation -- the highest the Timer can count. Its why I don't allow an Overflow Interrupt in this mode (gotta wait till 65,536 is counted). That doesn't happen due to the way I have things set up. A new version will correct this issue someday...

Final Thoughts

So there you have it. Using a 16-bit Timer, you can generate multiple 50% square-waves and easily change their phase relationship. Whether its useful depends on your project and what you want it to do.

If you haven't seen it yet, check out YouTube Video for RTM_TimerCalc.