Out of Phase (interleaved) PWM on the Arduino

Out of Phase (interleaving) PWM on Arduino

Recently while designing a charge controller, I needed out-of-phase PWM outputs from an Arduino. Since the timers are linked to two PWM outputs, I thought it would be pretty straight forward. After doing some research, I couldn’t find a simple solution.

While thinking about it, I figured I could offset the timer counter register (TCNTx – where x is the timer number). I thought I might have to change some more register settings to get the PWM between the two timers to match, but that was not the case.

By setting the initial value of TCNT1 to one half of its full value, we easily get out of phase PWM by adding a single line of code in the setup function:

TCNT1=0x7FFF;         //Set Timer1 Counter Register to half of its maximum value (32767)

Here is a scope plot of the output:

0078

And here is the full code for your use:

//START CODE

int PWM1 = 0;      // PWM1 width

int PWM2 = 0;      // PWM2 width

 

void setup()  {

 

TCNT1=0x7FFF;         //Set Timer1 Counter Register to half of its maximum value (32767)

pinMode(9, OUTPUT);   //Set Pin 9 to output

pinMode(11, OUTPUT);  //Set Pin 11 to output

}

 

void loop()  {

delay(500);            //delay 500ms to see change in PWM

analogWrite(9, PWM1);  //write PWM1 value to output on Pin 9

analogWrite(11,PWM2);  //Write PWM2 value to output on Pin 11

PWM1++;                //increment PWM1

PWM2++;                //increment PWM2

}

//END CODE

This is useful in many different applications: charge pump gate drivers, h-bridge control, ripple reduction and power handling in power converters.  Since there is a lot of information on PWM for the Arduino, I didn’t go into too much here. Please feel free to ask questions and I’ll do the best I can to answer it!

I hope this helps some people out there!

23 thoughts on “Out of Phase (interleaved) PWM on the Arduino”

  1. Hi. I have been searching for something to this affect for a while and have nothing except when I came to your site. I wanted to know if you have anycode on hand that will allow me to adjust pwm on two 180 out of phase pwm outputs up to max of 100khz or more? Im trying to drive Hbridge from micro and vary freq and duty.

    Thanks in advance,

    Shawn

    1. Hi Shawn,

      I would probably recommend the Arduino Mega 2560 R3. It has 14 PWM outputs and will probably get you to 50kHz. I dont think you will be able to get excellent resolution on a 100kHz PWM without going to a dedicated core. The problem is that you need a timer that runs at least 20x faster than your PWM for you to have enough resolution to accommodate narrow dead-times and such. Another great way to go is with an FPGA but you will need to have a clock of at least 50Mhz to get to your switching frequencies.

      Best Regards!
      Dimos

  2. Hi Dimos,

    Is it possible to get 8 PWM outputs shifted by 2Pi/8 with this method? AFAIK there are 9 timers in Arduino Due. I am searching for options to implement 8 phase high current buck converter.

    Thanks in advance,

    Pavlo.

    1. Dear Pavlo, I think this method can be extended to the Due. In Jason’s code you can get two outputs from a single timer ported to the digital pins. This means that for X timers you can theoretically get 2X outputs. I would however write a timer interrupt instead for better stability. That way you can run outside the main loop.

      1. hi AthenaEnergy,

        i want to create 4 out of phase pwm from arduino board to control 2 cascaded half bridge. how can it be done?

        thanks

        1. IF i understand your question, you want to control to separate bridges. What Arduino are you using? The ATmega328P has three timers known as Timer 0, Timer 1, and Timer 2. Each timer has two output compare registers that control the PWM width for the timer’s two outputs: when the timer reaches the compare register value, the corresponding output is toggled. The two outputs for each timer will normally have the same frequency, but can have different duty cycles.
          The Arduino Mega uses the ATmega1280 (datasheet), which has four 16-bit timers with 3 outputs each and two 8-bit timers with 2 outputs each. Only 14 of the PWM outputs are supported by the Arduino Wiring library

          Phase-Correct PWM example
          The following code fragment sets up phase-correct PWM on pins 3 and 11 (Timer 2). The waveform generation mode bits WGM are set to to 001 for phase-correct PWM. The other bits are the same as for fast PWM.

          pinMode(3, OUTPUT);
          pinMode(11, OUTPUT);
          TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM20);
          TCCR2B = _BV(CS22);
          OCR2A = 180;
          OCR2B = 50;

          On the Arduino Duemilanove, these values yield:

          Output A frequency: 16 MHz / 64 / 255 / 2 = 490.196Hz
          Output A duty cycle: 180 / 255 = 70.6%
          Output B frequency: 16 MHz / 64 / 255 / 2 = 490.196Hz
          Output B duty cycle: 50 / 255 = 19.6%

          Phase-correct PWM divides the frequency by two compared to fast PWM, because the timer goes both up and down. Somewhat surprisingly, the frequency is divided by 255 instead of 256, and the duty cycle calculations do not add one as for fast PWM.

  3. Is there a way one can use pwm to match an incoming pulse? trying to match phases for a solar system, doing a senior project in college.

    1. Exactly what switching frequency are you trying to match? Are you trying to slave another pulse (with phase shifting off a master pulse?) The arduino timer may not be fast enough as most DC/DC converters operate at very high switching frequencies to limit the size of passive components.

  4. Hello athenaenery. Thanks for the tutorial. I am struggeling with the control of sine pwm. Could your method be applied to generate dead time between sine pwm waveforms?

    1. Hi Andre,

      Sorry about the delay in the reply. One way we like to generate those waveforms is to provide an external low-frequency sine wave reference to the arduino. Any arduino will actually not be able to create a high-frequency representation of a 50/60Hz sinewave because the switching frequency of many converters is above 20kHz. We instead like to use a comparator to trigger the timer1 interrupt so that higher frequency PWM can be generated by the arduino. The dead-time can be achieved by applying a timer offset or an offset to the external comparator.

      Cheers,
      Dimos Katsis

  5. I am studying the code for my half bridge dc-dc converter, and wonder if it can work.

    I am using analogWrite(pin, Dcycle) for both pins, with a delaymicrosecond(25). I still cannot obtain the desired waveform of having alternate waveform between the 2 pins.

    Any solution to it?

    Thanks!

    1. Hi Tan,

      Be careful with analog write, it is not synchronized so that you can reliably create phase-shifted waveforms. The best approach is to slave your signals to a dedicated timer. The better approach is to use an arduino to control a dedicated phase shifted IC such as a UC3825 or equivalent. This also gives you a wide range of duty cycles!

      Cheers,
      Dimos

  6. Hi, is it possible to generate out of phase PWM, using PWM lib. the code below uses PWM lib to generate desired frequency on pin 9. I want another PWM on Pin 10 which is 180 degrees out of phase form the PWM at pin 9.

    #include
    int32_t frequency = 25000;
    int motor = 9;
    int potenciometer = 5;

    void setup(){
    InitTimersSafe();
    bool success = SetPinFrequencySafe(motor, frequency);
    if(success) {
    pinMode(9,OUTPUT);
    digitalWrite(9, HIGH);

    }
    pinMode(5,INPUT);
    Serial.begin(9600);
    }

    void loop(){
    int value = analogRead(potenciometer);
    int motor_speed = value/10;
    analogWrite(motor,motor_speed);
    Serial.println(motor_speed);
    }
    Thanks

  7. Hi there, I using arduino uno to generate 4 output 180 shifted adjustable duty cycle, how can I make it with your code?
    It is possible to make 4 output with 1 timer or we need 2 atleast?

    Best regard.

    Anjar

    1. Hello Anjar…take a look at this example code. It is good for many different frequencies

      //Simple High Frq. PWM generation
      // code by Dimos Katsis
      // PWM is selected on channels 3 and 11
      // created 1-26-2015
      //START CODE

      int PWM1 = 250; // PWM1 width
      int PWM2 = 250; // PWM2 width

      void setup() {

      TCNT1=0x7FFF; //Set Timer1 Counter Register to half of its maximum value (32767)
      //TCCR2B = TCCR2B & B11111000 | B00000010; // set timer 2 divisor to 8 for PWM frequency of 3921.16 Hz

      pinMode(3, OUTPUT); //Set Pin 3 to output
      pinMode(11, OUTPUT); //Set Pin 11 to output
      }

      void loop() {
      delay(50); //delay 500ms to see change in PWM
      TCCR2A = _BV(COM2A1) | _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
      // TCCR2B = _BV(CS22);
      TCCR2B = TCCR2B & B11111000 | B0000001; //Sets PWM freq to 62.kHz -adjust B0000001 to B0000010 for 7.8kHz (else 64kHz)
      OCR2A = PWM1;
      OCR2B = PWM2;

      //PWM1++; //increment PWM1
      //PWM2++; //increment PWM2
      }
      //END CODE

  8. Sir i want to generate dead time delay through aurduino, is it possible. Actually i have to make 12 volt AC from 12 volt DC. I am using switching technique

    1. It is not really possible to generate deadtime with precision in the Arduino. The typical deadtime is about 10uS for MOSFETs used in inverters but the TIMER sections of the Arduino do not have such precision. You can use a simple RC circuit to control turn-on and turn-off to make a deadtime prior to triggering the gate driver.

  9. Hi,
    do you have any idea on how i can calculate the phase shift between current and voltage signals from zero crossing op amp using Arduino uno.I am trying to calculate power factor.

    1. Here are my thoughts: You are providing zero crossings, then all you need to do is to use the frequency measurement tools to determine the time between these transitions. The higher the frequency the closer the transitions and the higher the power factor.
      Using FreqCounter library. It can measure frequencies up to several MHz, and is very precise. However, measurement pin is fixed to digital pin 5. Also it may affect Arduino PWM outputs, increasing their duty cycles. In case you don’t use PWM and you need to measure frequency of just one signal, FreqCounter is an excellent choice
      Using pulseIn() function from standard Arduino libraries. The technique I’m suggesting below is free from FreqCounter limitations, so you can use it on any pin. However, it’s minimal wave period is 10 uS, with corresponding maximum measurable frequency of 50 kHz

  10. sir i have one pwm signal pin3 from arduino uno ,this pwm signal(pin3) is output from my PID controller ,my question is how to add one more pwm signal that invert from pwm signal at pin 3?

Leave a Reply

Your email address will not be published. Required fields are marked *