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...
NOTE: You can set this up in RTM_TimerCalc using any 16-bit Timer and Mode_12 CTC.
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 in 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.
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.
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.
BIG EDIT: Another take-away from the Atmel data above is the CTC mode is depicted actually resetting the counter. That would cause a shift in frequency as compare values were changed.
But -- RTM_TimerCalc does not create code performing this reset action! Instead the Timer runs to its Top Value (supplied by the Input-Capture Register) and rolls over to zero. In this case, the Timer frequency remains fixed and waveforms are derived by the Toggle action (where the counter value collides with either OCR register value). So, sorry for any confusion about this. It seems the Atmel folks designed a flexible counter system with numerous capabilities. I missed this distinction...
Arduino Phase-Shifted Square Waves Code
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 same Output-compares as shown in the picture displayed directly above. The phase relation remains constant regardless of what output frequency you choose..
NOTE: Code updated here from next version of RTM_TimerCalc.
// generated by: RTM_TimerCalc 1.20 // Timer1 Mode_12_16Bit_CTC_TOP_is_ICR TCCR1B = 0x18; // Disable Timer Clock TCCR1A = 0x50; // 0101 0000 ICR1 = 320-1; OCR1A = (int) (ICR1 * 0.01); OCR1B = (int) (ICR1 * 0.51); TCNT1=0x0; // 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 TCCR1B |= 1; // Prescale=1, Enable Timer Clock
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.
BIG EDIT: Recent testing revealed a problem changing the Output-Compare registers while the Counter was generating the phase-shifted square waves. What I found was it sometimes flipped the OCR waveform to its opposite phase (180 degrees!).
This is a horrible thing to happen when you're counting on the phase-difference to be accurate. I even tried using the code shown above ( for setup() ) and the problems remained. So, it seems from setup(), you -can- have repeatable phase shift. But on the fly changes will lead to problems with 180-flips. The reason seems to stem from the OCR register updating immediately as opposed to doing so from TOP or BOTTOM (as is done with non-CTC modes). Why this update situation is like this, I don't know. My apologies for not realizing this sooner.
If you haven't seen it yet, check out YouTube Video for RTM_TimerCalc.