Arduino: Out of sync PWMs

Follow up to my last article, here is an application which helps run out of sync PWMs. This only works on Arduino Mega, as it requires more control over timers. The application would be anything that requires 2 sets of PWMs that work out of sync and in sync with each other. There are 3 groups of three PWMs on the Mega which can be configured, so you can have six running against three, or all nine running in sync.

The last article can be found here: http://smacula.blogspot.com/2011/04/creating-variable-frequency-pwm-output.html

The simple technique to do this is to set one timer in invert mode, using the same logic as applied in the last article, and one in non-invert mode.

E.g. the code I use is:

TCCR3A = _BV(COM3A1) | _BV(COM3B1) | _BV(COM3C1);
TCCR4A = _BV(COM4A1) | _BV(COM4B1) | _BV(COM4C1) | _BV(COM4A0) | _BV(COM4B0) | _BV(COM4C0);

Which sets Timer 3 (pins 2,4,5) in non-invert mode and Timer 4 (pins 6,7,8) in invert mode.
Later on in the code, when PWM is applied, make sure you subtract the required percentage by a 100.
So say, you want 33% on pins 2 and pins 6, 180 degrees out of sync with each other.
So
PWM on pin 2 = 33
PWM on pin 6 = 100 – 33 = 67.
Which would mean that both pins are giving 180 degrees out of sync PWM output of 33%.
Refer to the last article for rest of the maths involved. But as a quick summary:

After above statements, apply pre-scalar if required:

TCCR3B = _BV(WGM33) | _BV(CS31); // Divides by 8
TCCR4B = _BV(WGM43) | _BV(CS41);

Set frequency:

ICR3 = 1000; // Set to 1kHz
ICR4 = ICR3;

Insert required PWM:

PWM2 = 33
PWM6 = 67

Apply the values to the required variables:

OCR3B = PWM2 * ICR3 / 100;
OCR4A = PWM6 * ICR3 / 100;

Alternatively, the 100 – PWM6 might be applied at the later stage:

OCR4A = (100 – PWM6) * ICR3 / 100;

Which means the above lines can be changed to:

PWM2 = 33;
PWM6 = 33;

Which is easier to manage.
Give me a shout if you have any questions/suggestions

Related Posts

4 thoughts on “Arduino: Out of sync PWMs

  1. I put together this code based on this article and your other one referenced above. My goal is to have variable frequency complimentary square waves from Arduino Mega. Can you please provide any feedback as to whether this would work or not? I haven’t had a chance to test it because I’m working my through some syntax errors.

    Thanks in advance!

    // This program outputs 2 complimentary square wave signals with variable frequency
    // by using pins on Timer 3 (pins 2,4,5) and pins on Timer 4 (pins 6,7,8)

    void setup(){
    pinMode(2, OUTPUT);
    pinMode(6, OUTPUT);

    TCCR3A = _BV(COM3A1) | _BV(COM3B1) | _BV(COM3C1); // Timer 3 set to non-inverting mode by placing bits in the appropriate slots
    TCCR4A = _BV(COM4A1) | _BV(COM4B1) | _BV(COM4C1) | _BV(COM4A0) | _BV(COM4B0) | _BV(COM4C0); // Timer 4 set to inverting mode

    TCCR3B = _BV(WGM33) | _BV(CS31); // Prescaler set to 8 for Timer 3
    TCCR4B = _BV(WGM43) | _BV(CS41); // Prescaler set to 8 for timer 4
    }

    void loop() {
    // This loop lets different values read from the potentiometer place certain values in ICR3 and ICR4
    // to produce certain frequencies at pins 2 and 6 according to the formula f_output = f_clk / 2*N*ICRx
    // where f_clk = 16 MHz, N = prescaler value, ICRx =

    if(analogRead(A3) 800) ICR3 = 6 && ICR4 = 6; // ~160 kHz when voltage at A3 = 5V

    PWM2 = 40;
    PWM6 = 60;

    OCR3B = PWM2*ICR3/100;
    OCR4A = PWM6*ICR3/100;
    }

Leave a Reply

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