2 PWM signals out of phase

Dear Forum, I am trying to mimic an optical rotary encoder with two digital outputs from an Arduino Uno. The mechanical encoder has two outputs (ChA and ChB) which produce 5V pulses (50% duty cycle) at a frequency related to the speed of the encoder. I haven't measured the output frequency accurately but the two channels can operate at over 1KHz, probably much higher. The direction of the encoder appears to be coded by which channel (A or B) goes high first. So, to mimic this behaviour, I need to stagger the two digital outputs by roughly 500 us or even less.

I can get this working to some degree by simply setting a pair of output pins on an arduino high for a period and then low with a delay to stagger the two outputs. This is fine for relatively slow speeds but to get the motor running at a fast speed, I need to send pulses faster than the arduino can manage with millisecond delays. If I reduce the stagger delay between the pulses too low, then the motor stops turning smoothly; presumably this is because of interrupts interrupting the output.

I have tried using PWM outputs instead since I believe these will remain at a given frequency regardless of interrupts. I have managed to change the frequency of the output to get it running at more than 1KHz. However, to get this to work, I need a delay between the PWM signals. So far I have just tried outputs from the same timer (timer 0; pins 5 and 6); A quick look with an oscilloscope (while at work a couple of days ago) made me think that the two PWM signals were precisely in phase even though there was a delay before starting them.

Is this expected? I guess it could be because the PWM signals are from the same timer. Do you think it is possible to get PWM signals out of phase from the same timer, or from outputs controlled by different timers? I don't have access to an oscilloscope to test it out so I hoped someone out there would be able to tell me if I am flogging a dead horse!

I also wonder if there is another approach to this problem.

thanks, Nick

Is this expected? I guess it could be because the PWM signals are from the same timer.

Yes it is expected, you guessed right.

Do you think it is possible to get PWM signals out of phase from the same timer,

No it is not.

However you could get the timer to generate an interrupt. Then the interrupt service routing will toggle the pins in a quadrature fashion. You will need four interrupts for one quadrature cycle.

Alternatively you could always use microseconds delay.

You can get out-of-phase signals from the same timer if you put it in one of its PWM modes and configure the TCCRxA register for toggling on compare match.

For example, let's take Timer 1 (Section 16.11 of the ATmega328P datasheet). Configure it for CTC mode 12 (WGM1[3:0]=0b1100) so that the ICR1 register defines the TOP timer value, hence the frequency (PWM frequency will be 16 MHz/(ICR1+1)). Then, configure the TCCR1A register so that OC1A and OC1B both toggle on a compare match.

Now set OCR1A=ICR1-1, OCR1B=OCR1A/2. This means that once every timer period (from TCNT1=0 to TCNT1=ICR1) there will be a compare match with OCR1A and it will toggle, and approximately half a period later there will be a compare match with OCR1B and it will toggle.

-- The Rugged Audio Shield: Line In, Mic In, Headphone Out, microSD socket, potentiometer, play/record WAV files

Thank you, I have a bit of reading to do to understand this but I will give it ago.


As I understand it you are looking for two signals in 'quadrature' (meaning 90 degrees out of phase, probably doesn't need to be exactly 90 degrees for most applications, but it is essential that the two signals not switch simultaneously as that would be 0 or 180 degrees out.)

The standard PWM modes on the timer allow the two pins controlled by that timer to switch with different duty cycles, with the fast mode this is accomplished by switching both pins together as the counter wraps round, then each switches back at its own point in the cycle. This means both switch simultaneously at the start of a pulse. (No good for quadrature)

With 'phase-correct' mode the counter counts up, then down, then up, and each pin switches at a fixed counter value, one way for counting up and switch the other way for counting down. This means the PWM signals overlap symmetrically, making them precisely in-phase.

In fact each output pin can have its sense inverted with configuration bits, so, for instance 180 degrees out of phase IS possible - however its still not quadrature.

So the method RuggedCircuits suggests is a neat trick to get quadrature out of the timer unit - new to me, sounds like the way to go. Study the relevant timer chapters in the datasheet for all the details. timer1 is the most general timer, so I'd start with that one.

Sorry but PWM won't work to emulate an encoder. PWM has a fixed frequency and the on/off time ratio (DUTY CYCLE) determines the output average DC value. An encoder is a device that, when the encoder is rotating at a constant speed will have 2, 90 degree out of phase, signals of 50% duty cycle.

What you want to do is use 2 digital outputs, and 4 delays of equal value -

output 1 High, delay output 2 High delay output 1 Low delay Output 2 low. delay repeat.

the delay is what determines the speed. Shorter the delays - the faster the speed, longer the delays - the slower the speed. the frequency changes with speed, not the duty cycle like PWM.

i want to generate 2 PWM signals with 180 degrees out of phase using arduino.how do i go about it?

Create one, and use a transistor to invert it.
Otherwise, use blink-without-delay and flip two outputs at every time change:

unsigned long currentTime;
unsigned long previousTime;
unsigned long elapsedTime;
unsigned long duration = 50; //  toggle output every 50uS, 10KHz output
byte pin2 = 2; // PORTD bit2
byte pins = 3; // PORTD bit3
void setup(){
pinMode (pin2, OUTPUT);
digitalWrite (pin2, HIGH);
pinMode (pin3, OUTPUT);
digitalWrite (pin3, LOW);
void loop(){
currentTime = micros();
elapsedTime = currentTime - previousTime;
if (elapsedTime >=duration){
  previousTime = previousTime + duration;
  PIND = PIND | 0b00001100; // toggle outputs by writing 1 to input port
// do other stuff while waiting for duration to pass. Must finish in < duration uS, or software PWM will be affected