PWM continuous phase shifting

Hi,

Does anyone know if the Arduino Mega can have 2 PWM channels with a fixed 50% duty cycle but have the phase angle between them shift each switching cycle based on a calculation?

The switching frequency would be 50kHz

Thanks
Ted

No you can't do that.

If they have the same frequency how can the phase shift? If you want one PWM a bit faster than the other it is possible.

You have to know more about timers, see the controller data sheet.

For a 50% duty cycle you can use CTC mode of a timer, and let the output pins toggle on a compare match. The timer prescaler and TOP value (fixed or in ICRn) define the frequency of the output signals of that timer. In CTC mode the selected timer (n=1, 3, 4 or 5) will continuously count up from BOTTOM (always zero) to TOP (as specified e.g. in ICRn). For visualization: the timer counts will follow a sawtooth function.

Then set the Output Compare Registers (OCRnA, OCRnB) to some values between BOTTOM and TOP, to make the output signal of channel A and B toggle when the timer count reaches that OCR value. You can e.g. set OCRnA to the TOP value, and OCRnB to some other value, so that the A and B output pins are toggled at different timer counts, i.e. with a phase shift determined by the OCRnA and OCRnB difference. You have to map the desired phase shift into a value between BOTTOM and TOP, and write it to the OCRnB register. On a Mega a third phase-shifted signal can be created from channel C of the same timer.

You'll have to set the timer related registers in your code, using the predefined register and bit names. Please read and try to understand these settings, and come back with further questions.

Guys thanks for the help so far.

I’ve attached a matlab screen shot of the switching that I’m trying to achieve with the Arduino Mega.

S1 is a 50% duty cycle and its phase angle is 0 and never changes.

S2 has a 50% duty cycle but its phase angle is lagging by almost 180degrees, its lag reduces less and less each cycle until its almost 0degrees it then begins to get larger and larger until it gets to 180degrees and the whole process is repeated.

Note I’ve slowed down the switching frequency to 2500Hz in order to better display what is happening.

DrDiettrich I’ll try and read up on the CTC mode, I’ve found the Amtel data sheets a hard read in the past.

Thanks
Ted

You can't do that with a single timer (and most likely not with two timers) because the two base frequencies are slightly different.

This is not "PWM".

Run them at different non-harmonic frequencies. The closer the frequencies are the slower the change will be.
Don't use PWM since there are 2 PWM speeds, 490Hz and 980Hz that won't work for this.

Hey guys, why are you confusing Ted?

Of course it is possible to create the wanted signals, as I've described above. The frequency of both channels is different only from the analytical viewpoint, not from the technical VP. The second frequency can be created in discrete pieces, instead of a single continuous mathematical function. You can find out yourself what happens if the second OCR is e.g. incremented in the compare match ISR.

Hey guys, why are you confusing Ted?

Because he is confusing us. The requirements in reply #4 are nothing like what was asked in the origional post.

Grumpy_Mike:
Because he is confusing us. The requirements in reply #4 are nothing like what was asked in the origional post.

So Grumpy_Mike are you agreeing with DrDiettrich that the signal in post 4 can be achieved?
I'm sorry I have confused things by calling it PWM.

Yes this is just two frequencies that are close, nothing like what you asked for at first.

Even if the signals look like two slightly different frequencies, the requested effect can be achieved in software, using a single timer.

Even if PWM mode was suggested initially, the wise reader will understand that the solution requires a slightly different use of the timer.

Use micros() and forget about interrupts. Interrupts have more overhead than a tight loop() takes to run.

An even wiser person might question if the waveform shown in reply#4 is exactly what the OP actually needs.

If the waveform shown in #4 is the thing you want I see 3 ways to do it.

  1. Use CPU to generate the waveform as GoForSmoke suggests. It will eat all CPU time possibly with glitches on the waveform but easy to implement.

  2. Use 1 Timer/Counter to generate both waveforms with interrupt on each compare match changing OCRB slightly. It will fire interrupts quickly eating some (much) CPU time with possible glitches when CPU is loaded with other tasks.

  3. Use 1st T/C mode to generate one waveform with fixed frequency, 2nd T/C to generate the other waveform slightly faster/slower and 3rd T/C to count time and firing interrupt when making the 2nd waveform slower/faster is needed. It will need little care from CPU but uses 3 counters.

It depends on how long and precise the waves should be and what other tasks your Arduino must do. If you manage to do this you will learn much about timers - I think it is worth it.

It won’t eat all the cpu cycles. At 50KHz a 16MHz Arduino has 320 cpu cycles per frequency cycle. The timing for that speed BWD can be done with bytes holding microseconds. I know that micros() is only good to multiples of 4 but the overhead on a single interrupt is a few times that… what do you do when interrupts arrive closer than that? You wait. Overall for most but not all apps I’d much rather poll than use interrupts.

If you have short loop that is EVER faster than 300 cycles you may wait for corresponding interrupt flag instead of polling micros(). If you cannot ensure it interrupts are probably the only way.
Also Arduino uses hidden interrupts (for SPI, Wire, millis, ...). If one of those hits your loop while waiting for the right micros count you will get a huge glitch.

Smajdalf:
If you have short loop that is EVER faster than 300 cycles you may wait for corresponding interrupt flag instead of polling micros(). If you cannot ensure it interrupts are probably the only way.
Also Arduino uses hidden interrupts (for SPI, Wire, millis, ...). If one of those hits your loop while waiting for the right micros count you will get a huge glitch.

I've written a few examples that count loop() and display that count every second running from 57KHz to 68KHz. They all do more than generate a couple of frequencies.

Arduino "hidden" interrupts occur whether you use polling or interrupts.

Anyone stupid enough to write an if() that looks for an exact value (using == instead of >=) will get a "huge" glitch... duuuh!

Otherwise it's a question of "how FAR off" when there is no way to ensure "exact", only "how close".

From: Gammon Forum : Electronics : Microprocessors : Interrupts

Nick Gammon: How long does it take to execute an ISR?
I count 82 cycles there (5.125 µS in total at 16 MHz) as overhead plus whatever is actually done in the supplied interrupt routine. That is, 2.9375 µS before entering your interrupt handler, and another 2.1875 µS after it returns.

How long before the processor starts entering an ISR?

This various somewhat. The figures quoted above are the ideal ones where the interrupt is immediately processed. A few factors may delay that:

One way to save time would be to generate the signals with external circuitry and if necessary, time them with external CTC's.

Why not just set a two PWM signals going and just add one to the total count register of one. Then it all runs off hardware and is not interrupted by anything.

The separate generation of 2 PWM signals of (slightly) different frequencies is possible, but it's hard to vary their phases in software with every cycle, as requested in the initial posting.