# Changing arduino Due PWM frequency for DC motor control

**URL:** <https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383>\
**Category:** Due\
**Created:** [June 16, 2022, 7:35am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383 "2022-06-16T07:35:58Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![hyakoubi](https://avatars.discourse-cdn.com/v4/letter/h/dec6dc/32.png) [@hyakoubi](https://forum.arduino.cc/u/hyakoubi)\
**Post date:** [June 16, 2022, 7:35am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/1 "2022-06-16T07:35:58Z")

</div>

Hi,

I am working on projet where i need to control 3 dc motors with PWM frequeny around ,(15 Khz) on PIN (5,6,9 or 10).  
I am using arduino Due and multimoto (motor driver).

I tried many forums and make many search to change frequency froùm 1Khz to 15 khz but still I cant resolve this problem.

The best I found is PWM\_LIb in this link:

> **[GitHub - antodom/pwm\_lib: This is a C++ library to abstract the use of the...](https://github.com/antodom/pwm_lib)**
>
> This is a C++ library to abstract the use of the eight hardware PWM channels available on Arduino DUE's Atmel ATSAM3X8E microcontroller. - GitHub - antodom/pwm\_lib: This is a C++ library to abs...

but with this lib I can control only two pin (6 : PWML7\_PC24 // PWM\_CH7 and 9 : PWML4\_PC21, // PWM\_CH4).

Could you please help to resolve this problem ?

Bests Regards,

---

<div class="post-metadata">

**Author:** ![MartinL](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/martinl/32/216911_2.png) [@MartinL](https://forum.arduino.cc/u/MartinL)\
**Post date:** [June 16, 2022, 8:22am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/2 "2022-06-16T08:22:21Z")

</div>

Hi @hyakoubi

> [@hyakoubi](#):
>
> but with this lib I can control only two pin (6 : PWML7\_PC24 // PWM\_CH7 and 9 : PWML4\_PC21, // PWM\_CH4).

Is this because your Multimoto motor driver shield only supports PWM input on digital pins 5, 6, 9 and 10?

Are any other digital pins available on this shield, for example 7 and 8? Since I imagine that @antodom 's library would support these.

---

<div class="post-metadata">

**Author:** ![hyakoubi](https://avatars.discourse-cdn.com/v4/letter/h/dec6dc/32.png) [@hyakoubi](https://forum.arduino.cc/u/hyakoubi)\
**Post date:** [June 16, 2022, 8:25am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/3 "2022-06-16T08:25:47Z")

</div>

Hi Martin,

Availaible pin on this shield are only 5,6,9 and 10.  
An example in this link :

> **[MultiMoto 4 Channel H-Bridge Speed Controller for Arduino](https://www.robotshop.com/products/multimoto-4-channel-h-bridge-speed-controller-arduino)**
>
> MultiMoto 4 Channel H-Bridge Speed Controller for Arduino 6 - 36 V battery voltage Four independently controlled channels 6.5 A continuous (8 A peak) current on each channel. Fully reversible H-bridge design Size: 2.7 x 2.1 x 1 inches standard shield...

thanks,

---

<div class="post-metadata">

**Author:** ![MartinL](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/martinl/32/216911_2.png) [@MartinL](https://forum.arduino.cc/u/MartinL)\
**Post date:** [June 16, 2022, 8:41am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/4 "2022-06-16T08:41:40Z")

</div>

Hi @hyakoubi

The reason for asking is to do with the internals of the SAM3X8E used on the Arduino Due. Digital pins 6 an 9 use the microcontroller's PWM Controller, while pins 5 and 10 the TC timers.

I'll see if I can tweak the Due's _analogWrite()_ function to operate at 15kHz. If not, I can provide you with register level code that'll do the same thing.

---

<div class="post-metadata">

**Author:** ![MartinL](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/martinl/32/216911_2.png) [@MartinL](https://forum.arduino.cc/u/MartinL)\
**Post date:** [June 16, 2022, 10:39am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/5 "2022-06-16T10:39:51Z")

</div>

Hi @hyakoubi

I tried to tweaking the _analogWrite()_ function to change the PWM frequency, since it's possible with AVR microcontrollers (Uno/Mega, etc...), but it turns out for the Due's implementation this isn't so easy.

Here's a code example that outputs 15kHz PWM on pins D5 and D10. The duty-cycle is set by setting the respective timers' TC\_RA and TC\_RB registers between 0 and 2800, (with this code you're getting a much higher resolution):

```cpp
// Set up the Arduino Due's digital pins D5 and D10 for 15kHz PWM
void setup() 
{
  PMC->PMC_PCER1 |= PMC_PCER1_PID34 | PMC_PCER1_PID33; // Enable peripheral TC6 (TC2 Channel 0) and TC7 (TC2 Channel 1)
  PIOC->PIO_ABSR |= PIO_ABSR_P29 | PIO_ABSR_P25; // Switch the multiplexer to peripheral B for TIOA6 (D5) and TIOB7 (D10)
  PIOC->PIO_PDR |= PIO_PDR_P29 | PIO_PDR_P25; // Disable the GPIO on the corresponding pins

  TC2->TC_CHANNEL[0].TC_CMR = TC_CMR_ACPC_SET | // Set TIOA on counter match with RC0                           
                              TC_CMR_ACPA_CLEAR | // Clear TIOA on counter match with RA0
                              TC_CMR_WAVE | // Enable wave mode
                              TC_CMR_WAVSEL_UP_RC | // Count up with automatic trigger on RC compare
                              TC_CMR_EEVT_XC0 | // Set event selection to XC0 to make TIOB an output
                              TC_CMR_TCCLKS_TIMER_CLOCK1; // Set the timer clock to TCLK1 (MCK/2 = 84MHz/2 = 42MHz)

  TC2->TC_CHANNEL[1].TC_CMR = TC_CMR_BCPC_SET | // Set TIOB on counter match with RC0                              
                              TC_CMR_BCPB_CLEAR | // Clear TIOB on counter match with RB0                             
                              TC_CMR_WAVE | // Enable wave mode
                              TC_CMR_WAVSEL_UP_RC | // Count up with automatic trigger on RC compare
                              TC_CMR_EEVT_XC0 | // Set event selection to XC0 to make TIOB an output
                              TC_CMR_TCCLKS_TIMER_CLOCK1; // Set the timer clock to TCLK1 (MCK/2 = 84MHz/2 = 42MHz)

  TC2->TC_CHANNEL[0].TC_RC = 2800; // Set the PWM frequency to 15kHz: 42MHz / 15kHz = 2800 
  TC2->TC_CHANNEL[1].TC_RC = 2800; // Set the PWM frequency to 15kHz: 42MHz / 15kHz = 2800

  TC2->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Enable the timer TC6 (TC2 Channel 0)
  TC2->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Enable the timer TC7 (TC2 Channel 1)
}

void loop() 
{
  TC2->TC_CHANNEL[0].TC_RA = 700; // Set the duty-cycle to 25% on D5
  TC2->TC_CHANNEL[1].TC_RB = 700; // Set the duty-cycle to 25% on D10
  delay(2000); // Wait for 2 seconds
  TC2->TC_CHANNEL[0].TC_RA = 2100; // Set the duty-cycle to 75% on D5
  TC2->TC_CHANNEL[1].TC_RB = 2100; // Set the duty-cycle to 75% on D10
  delay(2000); // Wait for 2 seconds
}

```

---

<div class="post-metadata">

**Author:** ![MartinL](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/martinl/32/216911_2.png) [@MartinL](https://forum.arduino.cc/u/MartinL)\
**Post date:** [June 16, 2022, 10:58am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/6 "2022-06-16T10:58:01Z")

</div>

Note that there's a slight anomoly with the TC timers, in that it's not possible set the output to 0V by setting the respective TC\_RA and TC\_RB registers to zero. There's always a tiny slither of a pulse at the start of the timer cycle, (similar to fast PWM mode on the Uno or Mega).

The workaround is to set the timer to clear at the start to of the cycle with the line for D5:

```cpp
TC2->TC_CHANNEL[0].TC_CMR &= ~TC_CMR_ACPC_Msk; // Clear the ACPC bitfield
TC2->TC_CHANNEL[0].TC_CMR |= TC_CMR_ACPC_CLEAR; // Clear D5 output

```

and for D10:

```cpp
TC2->TC_CHANNEL[1].TC_CMR &= ~TC_CMR_BCPC_Msk; // Clear the BCPC bitfield
TC2->TC_CHANNEL[1].TC_CMR |= TC_CMR_BCPC_CLEAR; // Clear D10 output

```

Reinstate the PWM output oncemore with the respective TC\_CMR\_ACPC\_SET or TC\_CMR\_BCPC\_SET bitfields.

---

<div class="post-metadata">

**Author:** ![hyakoubi](https://avatars.discourse-cdn.com/v4/letter/h/dec6dc/32.png) [@hyakoubi](https://forum.arduino.cc/u/hyakoubi)\
**Post date:** [June 17, 2022, 8:08am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/7 "2022-06-17T08:08:11Z")

</div>

Thank you for your help

---

<div class="post-metadata">

**Author:** ![hyakoubi](https://avatars.discourse-cdn.com/v4/letter/h/dec6dc/32.png) [@hyakoubi](https://forum.arduino.cc/u/hyakoubi)\
**Post date:** [July 4, 2022, 8:35am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/8 "2022-07-04T08:35:48Z")

</div>

Hi MartinL,

I will need your help again about using encoder with this 3 motors if you can ?

Controlling the 3 motors with 15 Hz PWM works well in open loop but when i tried to use PID I used encoder with PIN 22,23 for exeample motor 1.The motors make too much noise (hissing).

There is a confusion between the use of PWM at 15 Hz and interrupt for counts with encoder but I cant find the solution ?

Motor 1 : PIN ( pwm 9, dir 2) encoder (phase A 22, Phase B 23)  
Motor 2 : PIN ( pwm 10, dir 3) encoder (phase A 24, Phase B 25)  
Motor 3 : PIN ( pwm 5, dir 4) encoder (phase A 26, Phase B 27)

I use software called Matlab Simulink with Sample time Te= 0.01 and (Ts=0.1 for encoder)

Any idea ?  
Many thanks,

---

<div class="post-metadata">

**Author:** ![MartinL](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/martinl/32/216911_2.png) [@MartinL](https://forum.arduino.cc/u/MartinL)\
**Post date:** [July 4, 2022, 8:49am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/9 "2022-07-04T08:49:30Z")

</div>

Hi @hyakoubi

> [@hyakoubi](#):
>
> Controlling the 3 motors with 15 Hz PWM works well in open loop but when i tried to use PID I used encoder with PIN 22,23 for exeample motor 1.The motors make too much noise (hissing).

Do you mean 15kHz?

Is your DC motor driver able to accept higher PWM frequencies? Switching to above 20kHz or so, would energise the motor coils at a frequency outside of (human) audible hearing range.

---

<div class="post-metadata">

**Author:** ![hyak](https://avatars.discourse-cdn.com/v4/letter/h/9fc29f/32.png) [@hyak](https://forum.arduino.cc/u/hyak)\
**Post date:** [July 4, 2022, 9:08am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/10 "2022-07-04T09:08:17Z")

</div>

yes I mean 15Khz.

For 20Khz it's not wotking too with the same PIN for Motor 1 : PIN ( pwm 9, dir 2) encoder (phase A 22, Phase B 23), stil hissing.

But I changed the encoder PIn to (phase A 44, Phase B 45) it seems to wrok even if my PID parameters not working in this case.

---

<div class="post-metadata">

**Author:** ![hyakoubi](https://avatars.discourse-cdn.com/v4/letter/h/dec6dc/32.png) [@hyakoubi](https://forum.arduino.cc/u/hyakoubi)\
**Post date:** [July 4, 2022, 11:50am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/11 "2022-07-04T11:50:39Z")

</div>

for :  
Motor 1 : PIN ( pwm 9, dir 2) encoder (phase A 44, Phase B 45)  
Motor 4 : PIN ( pwm 6, dir 7) encoder (phase A 42, Phase B 43)

the problem is resolved because I think the pwm channel for PIN (42,43,44,45) is not same pwm channel for PWM pin 9 and 6.

But for PWM pin 10 and 5, I am still facing the same noise (hissing) with many frequncies tested : 15 Khz,20 Khz, 32125 Hz...  
and tested many other PIn for encoder .

Motor 2 : PIN ( pwm 10, dir 3) encoder (phase A 24, Phase B 25) HISSING  
Motor 3 : PIN ( pwm 5, dir 4) encoder (phase A 26, Phase B 27) Hissing

---

<div class="post-metadata">

**Author:** ![MartinL](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/martinl/32/216911_2.png) [@MartinL](https://forum.arduino.cc/u/MartinL)\
**Post date:** [July 4, 2022, 11:54am UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/12 "2022-07-04T11:54:25Z")

</div>

Hi @hyakoubi

Just to clarify, so you're saying that you're getting no hissing on pins 6 and 9 using PWM library, but you are getting hissing on pins 5 and 10 with the PWM from the TC timers?

---

<div class="post-metadata">

**Author:** ![hyakoubi](https://avatars.discourse-cdn.com/v4/letter/h/dec6dc/32.png) [@hyakoubi](https://forum.arduino.cc/u/hyakoubi)\
**Post date:** [July 4, 2022, 12:02pm UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/13 "2022-07-04T12:02:37Z")

</div>

I am using Matlab/Simulink software not arduino IDE, but I cant see source code in Matlab.

yes, pin 6 and 9 no noise bacause it's related to PWM clock and noise on Pin 5 and 10. because it's TC Timers.

Noise only when I use encoder (phase A 24, Phase B 25), (phase A 26, Phase B 27) without encoder no noise.

---

<div class="post-metadata">

**Author:** ![hyak](https://avatars.discourse-cdn.com/v4/letter/h/9fc29f/32.png) [@hyak](https://forum.arduino.cc/u/hyak)\
**Post date:** [July 4, 2022, 12:23pm UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/14 "2022-07-04T12:23:32Z")

</div>

![pwm_Due](https://europe1.discourse-cdn.com/arduino/original/4X/0/c/3/0c31aa09b2a8b3e150d39f8f980153007bd7c63c.png)

---

<div class="post-metadata">

**Author:** ![MartinL](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/martinl/32/216911_2.png) [@MartinL](https://forum.arduino.cc/u/MartinL)\
**Post date:** [July 4, 2022, 12:48pm UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/15 "2022-07-04T12:48:12Z")

</div>

Hi @hyakoubi

I think it's because your closed-loop control system is making very fast, fine adjustments to the TC timers' duty-cycles. However, unlike the PWM controller used by the PWM library, the TC timers have no buffered TC\_RA and TR\_RB duty-cycle registers. This means any changes in duty-cycle occur immediately at the output rather than at the beginning of each timer cycle, causing glitches on their respective outputs.

The solution is to only set the new duty-cycle for the TC timers in their respective overflow interrupt service routines:

```cpp
// Set up the Arduino Due's digital pins D5 and D10 for 15kHz PWM with RC compare interrupts
volatile uint32_t dutycycleTC6 = 0, dutycycleTC7 = 0;

void setup() 
{
  PMC->PMC_PCER1 |= PMC_PCER1_PID34 | PMC_PCER1_PID33; // Enable peripheral TC6 (TC2 Channel 0) and TC7 (TC2 Channel 1)
  PIOC->PIO_ABSR |= PIO_ABSR_P29 | PIO_ABSR_P25; // Switch the multiplexer to peripheral B for TIOA6 (D5) and TIOB7 (D10)
  PIOC->PIO_PDR |= PIO_PDR_P29 | PIO_PDR_P25; // Disable the GPIO on the corresponding pins

  TC2->TC_CHANNEL[0].TC_CMR = TC_CMR_ACPC_SET | // Set TIOA on counter match with RC0                           
                              TC_CMR_ACPA_CLEAR | // Clear TIOA on counter match with RA0
                              TC_CMR_WAVE | // Enable wave mode
                              TC_CMR_WAVSEL_UP_RC | // Count up with automatic trigger on RC compare
                              TC_CMR_EEVT_XC0 | // Set event selection to XC0 to make TIOB an output
                              TC_CMR_TCCLKS_TIMER_CLOCK1; // Set the timer clock to TCLK1 (MCK/2 = 84MHz/2 = 42MHz)

  TC2->TC_CHANNEL[1].TC_CMR = TC_CMR_BCPC_SET | // Set TIOB on counter match with RC0                              
                              TC_CMR_BCPB_CLEAR | // Clear TIOB on counter match with RB0                             
                              TC_CMR_WAVE | // Enable wave mode
                              TC_CMR_WAVSEL_UP_RC | // Count up with automatic trigger on RC compare
                              TC_CMR_EEVT_XC0 | // Set event selection to XC0 to make TIOB an output
                              TC_CMR_TCCLKS_TIMER_CLOCK1; // Set the timer clock to TCLK1 (MCK/2 = 84MHz/2 = 42MHz)

  TC2->TC_CHANNEL[0].TC_RC = 2800; // Set the PWM frequency to 15kHz: 42MHz / 15kHz = 2800 
  TC2->TC_CHANNEL[1].TC_RC = 2800; // Set the PWM frequency to 15kHz: 42MHz / 15kHz = 2800

  NVIC_SetPriority(TC6_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC6 to 0 (highest) 
  NVIC_EnableIRQ(TC6_IRQn); // Connect TC6 to Nested Vector Interrupt Controller (NVIC)

  TC2->TC_CHANNEL[0].TC_IER |= TC_IER_CPCS; // Enable RC compare interrupt for TC6 (TC2 Channel 0)

  NVIC_SetPriority(TC7_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC7 to 0 (highest) 
  NVIC_EnableIRQ(TC7_IRQn); // Connect TC7 to Nested Vector Interrupt Controller (NVIC)

  TC2->TC_CHANNEL[1].TC_IER |= TC_IER_CPCS; // Enable RC compare interrupt for TC7 (TC2 Channel 1)

  TC2->TC_CHANNEL[0].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Enable the timer TC6 (TC2 Channel 0)
  TC2->TC_CHANNEL[1].TC_CCR = TC_CCR_SWTRG | TC_CCR_CLKEN; // Enable the timer TC7 (TC2 Channel 1)
}

void loop() 
{
  dutycycleTC6 = 700; // Set the duty-cycle to 25% on D5 on next timer cycle
  dutycycleTC7 = 700; // Set the duty-cycle to 25% on D10 on next timer cycle
  delay(2000); // Wait for 2 seconds
  dutycycleTC6 = 2100; // Set the duty-cycle to 75% on D5 on next timer cycle
  dutycycleTC7 = 2100; // Set the duty-cycle to 75% on D10 on next timer cycle
  delay(2000); // Wait for 2 seconds
}

void TC6_Handler() // ISR TC6 (TC2 Channel 0)
{
  if (TC2->TC_CHANNEL[0].TC_SR & TC_SR_CPCS) // Check for RC compare condition
  {
    TC2->TC_CHANNEL[0].TC_RA = dutycycleTC6; // Set the duty-cycle to on D5
  }
}

void TC7_Handler() // ISR TC7 (TC2 Channel 1)
{ 
  if (TC2->TC_CHANNEL[1].TC_SR & TC_SR_CPCS) // Check for RC compare condition
  {
    TC2->TC_CHANNEL[1].TC_RB = dutycycleTC7; // Set the duty-cycle on 10
  }
}

```

If there's still an issue, or if the motors on the TC timers still sound a bit different, then it could be that TC timers need to be configured to work in dual slope rather than single slope mode. Luckily the TC timers are capable of both.

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [April 8, 2023, 9:05pm UTC](https://forum.arduino.cc/t/changing-arduino-due-pwm-frequency-for-dc-motor-control/1003383/18 "2023-04-08T21:05:03Z")

</div>

Closed on April 8, 2023, 9:05pm UTC

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
