4 channel PWM generation with same frequency and varying dutycycle

How can i generate 4 channel PWM with same frequency. i want to vary duty cycle with POT. is it possible?

What kind of Arduino do you use?
Uno?

You have to program 2 timers for the frequency, then you can use their related PWM outputs. On an Uno use T1 and T2, search the forum for the frequency adjustment (register settings).

Arduino nano

When you are using an Arduino Nano, using standard analogWrite() function
with digital pins 3 / 9 / 10 / 11 will produce PWMs of the same frequency each pins.
The frequency of this PWM is 490Hz.
Duty cycle can be set from 0 to 255 with analogWrite() function.
Do you need to change the frequency?

i need frequency from 1Khz to 2 Khz. not varying but fixed between this range

Is there a problem with 976.6Hz ≈ 1kHz?

The Arduino Nano has two 8-bit timers and one 16-bit timer.
You can get two PWM outputs per timer, but due to the prescaler, the frequencies that can be achieved while keeping the duty cycle resolution at 8-bit are about 490Hz, 976Hz, 3922Hz around your desired value.

If you are comfirm with the reduce duty cycle resolution to less than 8-bit, you can set any frequency you like.

976Hz is ok but sometimes need to set 1.5 or 1.8 khz. no problem with 8 bit duty cycle resolution

can you explain how its done?

Please add

TCCR2A |= 2;

at your bottom of setup().

After that, using  analogWrite()  function with digital pins 3 / 5 / 6 / 11.
It will produce PWMs of the 976.6Hz each pins.
You can set duty cycle between 0 and 255 with  analogWrite()  function.

Please note that the pin is different from the I posted above.

I forgot to say.
It is possible to use Arduino Nano to generate hardware PWM with 8-bit resolution on 4 channels at 1.5kHz.
But many useful features will be sacrificed when doing this.
Because that need to use all timers and do some tricks.
Of course since it is hardware PWM, there is no CPU task after setting.

For 8-bit PWM, your frequency choices are:
62,500 Hz. Fast PWM, Prescale = 1
31,250 Hz. Phase Correct PWM, Prescale = 1
7,812.5 Hz, Fast PWM, Prescale = 8
3,906.25 Hz, Phase Correct PWM, Prescale = 8
976.5625 Hz, Fast PWM, Prescale = 64

To get any frequency between 976.5625 Hz and 3,906.25 Hz you will need to use a different number of bits. You can get lower frequencies by using more bits but that only works on Timer1 since Timer2 is an 8-bit timer. You can get higher frequency by reducing the resolution. To get 1 kHz you would use the prescale of 64 and drop the top value to 249 instead of 255. To get 2 kHz you would drop the top value to 124.

@aasukevay I thought I'd just add that the Arduino Micro (Atmega32U4) has four 16-bit timer outputs, (3 channels on T1 and 1 channel on T3). Both these timers can operate in fast PWM mode with adjustable frequency.

As explained above, It's possible to use 4 hardware PWM outputs while maintaining 8-bit resolution at Arduino Nano.
However, the standard features delay() and millis() and more etc are disabled.
So changing the board can be a good way to go.

If you really want to do it with your already had Nano, you need accept the above risks.

You could do this at modest frequencies with software PWM.

Great ..! thanks all for support, i will check and if have any issue, i will post ...

@aasukevay The following code sets up Fast PWM mode on the Arduino Micro's digital pins: D9, D10, D11 and D5.

The formula for calculating the PWM frequency is:

PWM Frequency = F(clk) / (N * (TOP + 1))

where:
F(clk) = 16MHz (or 8MHz if operating at 3.3V)
N = timer prescalar = 1
TOP = the value of the ICR1 or ICR3 registers = 8888

therefore:

PWM frequency = 16MHz / (1 * (8888 + 1)) = 1.8kHz

To find the ICRx value for a given PWM frequency:

ICRx = F(clk) / (N * F(pwm)) - 1

Resolution at 1.8kHz is given by:

Resolution = log(TOP + 1) / log(2)

Resolution = log(8888 + 1) / log(2) = 13-bits

Here's the code:

// Set Arduino Micro PWM output to 1.8kHz on D9, D10, D11 and D5
void setup() 
{
  // Configure the PWM outputs on D9, D10, D11 and D5
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(5, OUTPUT);
  
  // Initialise timers 1 and 3 for Fast PWM Mode
  TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(COM1C1) | _BV(WGM11);    // Enable the PWM outputs OC1A, OC1B and OC1B on digital pins 9, 10 and 11
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);                     // Set fast PWM mode and prescaler of 1 on timer 1
  TCCR3A = _BV(COM3A1) | _BV(WGM11);                                // Enable the PWM output OC3A on digital pin 5
  TCCR3B = _BV(WGM33) | _BV(WGM32) | _BV(CS30);                     // Set fast PWM mode and prescaler of 1 on timer 3
  ICR1 = 8888;                                                      // Set TOP value for fast PWM mode on timer 1 at 1.8kHz
  ICR3 = 8888;                                                      // Set TOP value for fast PWM mode on timer 3 at 1.8kHz
  OCR1A = 2222;                                                     // Set OCR1A to output 25% duty-cycle on digital pin 9
  OCR1B = 2222;                                                     // Set OCR1B to output 25% duty-cycle on digital pin 10
  OCR1C = 2222;                                                     // Set OCR1C to output 25% duty-cycle on digital pin 11
  OCR3A = 2222;                                                     // Set OCR3A to output 25% duty-cycle on digital pin 5
}

void loop() {}

As a side note, It should be remembered that when Fast PWM mode, set 0 to the OCRxn register doesn't complete turn off the output and continues outputs the minimal width pulse.
If you want to turn off the output completely, you need to disconnect the timer from the port.

If you want to turn it on completely, you can achieve it by writing the maximum duty.

@chrisknightley Thanks Chris, I didn't know that. Is the same true for phase and frequency correct mode?

No.
In Phase correct mode, set 0 to the OCRnx register completely turns off the output from the timer.


・Fast PWM mode

The extreme values for the OCRnx Register represents special cases when generating a PWM waveform output in the fast PWM mode.
If the OCRnx is set equal to BOTTOM (0x0000) the output will be a narrow spike for each TOP+1 timer clock cycle.
Setting the OCRnx equal to TOP will result in a constant high or low output (depending on the polarity of the output set by the COMnx1:0 bits).

from
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf#page=125


・Phase correct mode

The extreme values for the OCRnx Register represent special cases when generating a PWM waveform output in the phase correct PWM mode.
If the OCRnx is set equal to BOTTOM the output will be continuously low and if set equal to TOP the output will be continuously high for non-inverted PWM mode.
For inverted PWM the output will have the opposite logic values.

from
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf#page=127


1 Like