Arduino Due Timer PWM Frequency change

Hi there @wachaudhary,

Have a look to pwm_lib available at:

I think that with it you can do what you want, have a look to example "basic_test.ino" with comes with pwm_lib.

I hope it helps.

Tfou57:
Hello @Magician,
I am interested in your way to easily increase the frequency of pine

  1. Your method would not work also on other PWM?
    such as pines:

5 (TIOA6)
10 (TIOB7)
12 (TIOB8)

  1. By applying your method, can we still easily configure the PWM signal distortion 12-bit?

  2. What is the maximum frequency that you get without distorting the PWM signal?

Thank you for your tip.

I can't see any reason why it shouldn't work for any pin driven by Timers, like digital 5, 10, 11 and 12.
Regarding PWM, same configuration file has another section, just 10 lines above:

 * PWM
 */
#define PWM_INTERFACE		PWM
#define PWM_INTERFACE_ID	ID_PWM
#define PWM_FREQUENCY		1000
#define PWM_MAX_DUTY_CYCLE	255
#define PWM_MIN_DUTY_CYCLE	0
#define PWM_RESOLUTION		8

Could you guess what is the parameter has to be changed?
Interesting, it says resolution 8 bits, probably for consistent with others arduino boards. I'm not quite sure, what you mean saying distortion, probably, resolution is right word.
Timers on arduino DUE have max input freq. 42MHZ, that makes 42000000/4096= 10.254 kHz max output freq. with 12-bits resolution, and 42000000/256= 164.062 kHz max output freq. with 8-bits .

Question 1

Magician:
Could you guess what is the parameter has to be changed?

From your post 3, I would change that "#define TC_FREQUENCY 1000" for 8bit PWM and I thought then that "#define PWM_FREQUENCY 1000" was used for other PWM pins 6,7,8 and 9

We must therefore change if for example I want a PWM with 41000Hz 10bits

D’après votre post 3, j’aurais modifier que « #define TC_FREQUENCY 1000 » pour un PWM en 8bits et je pensais alors que « #define PWM_FREQUENCY 1000 » servait aux autres pins PWM 6,7,8 et 9
Il faut donc changer si par exemple je souhaite un PWM 10bits à 41000Hz

/*
 * PWM
 */
#define PWM_INTERFACE		PWM
#define PWM_INTERFACE_ID	ID_PWM
#define PWM_FREQUENCY		41000
#define PWM_MAX_DUTY_CYCLE	1023
#define PWM_MIN_DUTY_CYCLE	0
#define PWM_RESOLUTION		10

/*
 * TC
 */
#define TC_INTERFACE        TC0
#define TC_INTERFACE_ID     ID_TC0
#define TC_FREQUENCY        41000
#define TC_MAX_DUTY_CYCLE   1023
#define TC_MIN_DUTY_CYCLE   0
#define TC_RESOLUTION	    10

Question 2

Magician:
I'm not quite sure, what you mean saying distortion, probably, resolution is right word.

I spoke well of distortion of the PWM signal and no bit resolution PWM signal
Why : ?
I have to filter the signal into Arduino 3.3v output with a second order filter and amplify the received signal until a signal ranging from 0V to 10V as linear as possible
I must have a minimum of delay and distortion between the Arduino output signal and the signal continues 0V to 10V controlling the speed of controlling a drive of three phase frequency.
So I have to use the smaller RC couples using a high PWM frequency.
I asked you about the maximum frequency in 12bits because in my application I use 12-bit ADC in by manipulating ports
In your opinion what would be the desirable PWM frequency in such use

Je parlais bien de distorsion du signal PWM et pas de la résolution en bits du signal PWM
Pourquoi : ?
Je dois filtrer le signal 3,3v en sortie Arduino avec un filtre de second ordre puis amplifier le signal obtenu jusqu’à obtenir un signal variant de 0v à 10v le plus linéaire possible
Je dois avoir un minimum de retard et de distorsion entre le signal sortie Arduino et le signal continue 0v à 10v commandant la commande de vitesse d’un variateur de fréquence triphasé.
Je dois donc utiliser des couples RC les moins importants en utilisant une fréquence PWM élevée.
Je vous interrogeais sur la fréquence maxi en 12bits car dans mon application j’utilise des ADC en 12 bits par la manipulation de ports
A votre avis quelle serait la fréquence PWM souhaitable dans une telle utilisation

Question 3

Bob Cousins in August 2014 has also worked on the same subject and had shared code
In your opinion what is the fastest solution running?
Can you objectively give me the advantages and disadvantages in terms of the responsiveness of PWM of each solution?

Bob Cousins en aout 2014 a également travaillé sur le même sujet et avait partagé un code
A votre avis quelle est la solution la plus rapide en exécution ?
Pouvez-vous en toute objectivité me donner les avantages et inconvénients au niveau de la réactivité du PWM de chacune des solutions?

// --------------------------------------------
//
// PWM with timers demo
//
// Bob Cousins, August 2014
// --------------------------------------------

typedef struct {
    Tc *pTC;        // TC0, TC1, or TC2
    byte channel;   // 0-2
    byte output;    // 0 = A, 1 = B
}  tTimerInfo;

tTimerInfo timerLookup [] =
{
  {NULL,0,0}, // 0
  {NULL,0,0},
  {TC0,0,0},  // pin 2 = TIOA0
  {TC2,1,0},  // pin 3 = TIOA7
  {TC2,0,1},  // pin 4 = TIOB6
  {TC2,0,0},  // pin 5 = TIOA6
  {NULL,0,0},
  {NULL,0,0},
  {NULL,0,0},
  {NULL,0,0},
  {TC2,1,1},  // pin 10 = TIOB7
  {TC2,2,0},  // pin 11 = TIOA8
  {TC2,2,1},  // pin 12 = TIOB8
  {TC0,0,1}   // pin 13 = TIOB0
};

/**
 * \brief set a pin for PWM using a timer channel
 * \param pin       pin to use (0-13 only!)
 * \param frequency the frequency
 * \param dutyCyle  duty cycle 0-255
 * \return          this function returns a count, which is the effective PWM resolution. Returns 0 if pin is not valid
 */

uint32_t setupTimerPwm (byte pin, uint32_t frequency, unsigned dutyCycle)
{
  uint32_t count = VARIANT_MCK/2/frequency;
  tTimerInfo *pTimer = &timerLookup[pin];
  
  if (pTimer != NULL)
  {
    TC_SetRC (pTimer->pTC, pTimer->channel, count);
    if (pTimer->output == 0)
       TC_SetRA (pTimer->pTC, pTimer->channel, count * dutyCycle / 256);
    else
       TC_SetRB (pTimer->pTC, pTimer->channel, count * dutyCycle / 256);
  
    return count;
  }
  else
    return 0;
}

void setup() {
  // put your setup code here, to run once:

  // use the Arduino lib to do initial setup
  analogWrite (2, 128);
  analogWrite (13, 128);
  
  analogWrite (5, 128);
  analogWrite (4, 128);

  analogWrite (3, 128);
  analogWrite (10, 128);

  analogWrite (11, 128);
  analogWrite (12, 128);
 
  // pins 2 and 3 share the same timer so must have same frequency
  setupTimerPwm (2, 2000, 128); 
  setupTimerPwm (13, 2000, 64); 
  
  // pins 5 and 4 share the same timer
  setupTimerPwm (5, 3000, 128); 
  setupTimerPwm (4, 3000, 64); 

  // pins 3 and 10 share the same timer
  setupTimerPwm (3, 4000, 128); 
  setupTimerPwm (10, 4000, 64); 

  // pins 11 and 12 share the same timer
  setupTimerPwm (11, 5000, 128); 
  setupTimerPwm (12, 5000, 64); 

}

void loop() {
  // put your main code here, to run repeatedly:

}

I am trying to change the PWM frequency for pin 3 and 4 for Arduino DUE board. Originally it is running at 1KHz frequency. However, I want to change it to 10KHz. Any support or help would be grateful.

The following code outputs a 50% duty cycle, 10kHz signal on digital pins 4 and 5 using TC6, (confusingly also known as TC2 channel 0):

// Output 50% duty cycle PWM at 10kHz on digital pins D4 and D5 using TC6
void setup()
{
  REG_PMC_PCER1 |= PMC_PCER1_PID33;                 // Enable peripheral TC6 (TC2 Channel 0)
  REG_PIOC_ABSR |= PIO_ABSR_P26 | PIO_ABSR_P25;     // Switch the multiplexer to peripheral B for TIOA6 and TIOB6
  REG_PIOC_PDR |= PIO_PDR_P26 | PIO_PDR_P25;        // Disable the GPIO on the corresponding pins

  REG_TC2_CMR0 = TC_CMR_BCPC_SET |                  // Set TIOB on counter match with RC0
                 TC_CMR_ACPC_SET |                  // Set TIOA on counter match with RC0
                 TC_CMR_BCPB_CLEAR |                // Clear TIOB on counter match with RB0
                 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 = 48MHz)

  REG_TC2_RA0 = 2100;                               // Load the RA0 register
  REG_TC2_RB0 = 2100;                               // Load the RB0 register
  REG_TC2_RC0 = 4200;                               // Load the RC0 register
  
  REG_TC2_CCR0 = TC_CCR_SWTRG | TC_CCR_CLKEN;       // Enable the timer TC6
}

void loop() {}

Digital pin 3 could be used, but would mean having to also call on timer TC7. Using digital pins 4 and 5 instead is more convenient, as we can use the two channels (RA and RB) of timer TC6.

This solution gives 12-bit resolution.

Question 2

Quote from: Magician on 13-09-2016, 17:21:36
I'm not quite sure, what you mean saying distortion, probably, resolution is right word.
I spoke well of distortion of the PWM signal and no bit resolution PWM signal
Why : ?
I have to filter the signal into Arduino 3.3v output with a second order filter and amplify the received signal until a signal ranging from 0V to 10V as linear as possible
I must have a minimum of delay and distortion between the Arduino output signal and the signal continues 0V to 10V controlling the speed of controlling a drive of three phase frequency.
So I have to use the smaller RC couples using a high PWM frequency.
I asked you about the maximum frequency in 12bits because in my application I use 12-bit ADC in by manipulating ports
In your opinion what would be the desirable PWM frequency in such use

Now I see. Better option to have fast analog outputs would be using DAC, arduino DUE has two, and you probably needs 3?
If it's me, I would search external 3 channel DAC, over SPI (42MHz clock) about 1MHz update reachable for 10-12 bits/per channel.
If price is concern, than PWM may be an option, to have higher frequency you can "split" 10-bits into 5+5 and use two PWM channels to reproduce 1 sine output. Doing this way, adding just two resistors 32:1 max obtainable clock 42MHz/32 = 1.3125 MHz.

Magician:
Now I see. Better option to have fast analog outputs would be using DAC, arduino DUE has two, and you probably needs 3?
If it's me, I would search external 3 channel DAC, over SPI (42MHz clock) about 1MHz update reachable for 10-12 bits/per channel.
If price is concern, than PWM may be an option, to have higher frequency you can "split" 10-bits into 5+5 and use two PWM channels to reproduce 1 sine output. Doing this way, adding just two resistors 32:1 max obtainable clock 42MHz/32 = 1.3125 MHz.

@ Magician, thank you for your interest in my problem
I had already thought of using 3 or 4 Arduino Due because I have at my disposal 6.
The problem is that I know how to do data communications between multiple cards and port management to increase the frequency of DAC0 DAC1 and each card retaining the 12-bit.

I have to give you a bit more information on my application: dynamic simulator game

  1. Arduino receives every 1ms (à10ms) into the USB postions instructions engines (output shafts of gearmotors tri 220v)
  2. Arduino reads the current position
  3. Arduino calculate the position fix to be applied to stick to the set
  4. Arduino control drives with speed reference signal (0V to 10V =) = 2 and the direction of rotation (= 0V or 24V =)
  5. Return to step 1 ....

For 6 DAC, it takes 3 Arduino Due, each card will manage

  • ADC 2 (A10 and A11 for position control)
  • 2 DAC (DAC1 DAC0 and speed reference)
  • 4 digital outputs (34 -PWML0, -PWMH0 35, 36 -PWML1, -PWMH1 37) to try to make an inter locking in forward and backward in order to prevent the drives stop in an amount default. Example simple PWMC example - Arduino Due - Arduino Forum

Question 1

  1. How to control the DAC through direct management of ports and increasing the frequency to 1MHz without distorting the output voltage before I amplified by an operational amplifier?

Question 2
2a) Do you have feedback on the use of pin 34 (PWML0) and pin35 (PWMH0) taken as an example simple PWMC example - Arduino Due - Arduino Forum
2b) Direct management of digital ports with delayMicroseconds (1) between Does the risk inversions generate for a moment during the 2 signals forward and backward together?

Question 3
3) Do 3 Arduino Due cards can simultaneously read -they common USB frame with 6 axes to manage?
Either the statement of 3 Arduino Due cards with the same COM number
Ideal solution for each card read only the positions of the instructions concerning

Question 4
4a) How to transfer the fastest way to map 2 and map 3 positions instructions read by the card 1?
4b) Can we avoid introducing a fourth position to only read instructions to the USB port and relay instructions to other 3 cards?

@ Magician , merci de votre intérêt sur mon problème
J’avais déjà pensé à utiliser 3 ou 4 Arduino Due car j’en ai 6 à ma disposition.
Le problème est que je sais pas comment faire la communication de données entre plusieurs cartes et la gestion des ports pour augmenter de la fréquence des DAC0 et DAC1 de chaque carte en les conservant en 12 bits.

Je dois vous donner un peu plus d’information sur mon application : Simulateur dynamique de jeu

  1. Arduino reçoit tous les 1ms (à10ms) dans l’USB des consignes de postions des moteurs (arbres de sortie de motoréducteurs 220v tri)
  2. Arduino lit la position actuelle
  3. Arduino calcul le correctif de position à appliquer pour coller à la consigne
  4. Arduino commande les variateurs avec des signaux de consigne de vitesse (0v= à 10V)= et des 2 sens de rotation (0v= ou 24V=)
  5. Retour à l’étape 1 ….
    Pour 6 DAC, il faut 3 Arduino Due, chaque carte gérera
  • 2 ADC (A10 et A11 pour le contrôle de position)
  • 2 DAC (DAC0 et DAC1 consigne de vitesse)
  • 4 Sorties digitales (34 –PWML0, 35 –PWMH0, 36 –PWML1 , 37 –PWMH1 afin de tenter de faire un inter verrouillage en la marche avant et arrière dans le but d’éviter que les variateurs s’arrêtent en montant un défaut . Exemple sur simple PWMC example - Arduino Due - Arduino Forum

Question 1

  1. Comment piloter les DAC par une gestion directe des ports et en augmentant la fréquence à 1Mhz sans distorsion de la tension de sortie avant que je l’amplifie par un amplificateur opérationnel ?

Question 2
2a) Avez-vous un retour d’expérience sur l’usage de pin 34(PWML0) et la pin35(PWMH0) prises en exemple simple PWMC example - Arduino Due - Arduino Forum
2b) Une gestion directe des ports digitaux avec un delayMicroseconds(1) entre les inversions de sens risque-t-elle de générer durant un cours instant les 2 signaux marche avant et arrière ensemble ?

Question 3
3) Est-ce que 3 cartes Arduino Due peuvent –elles lire simultanément la trame USB commune aux 6 axes à gérer ?
Soit la déclaration de 3 cartes Arduino Due avec le même numéro COM
Solution idéale car chaque carte lirait uniquement les consignes de positions la concernant

Question 4
4a) Comment transférer de la façon la plus rapide à la carte 2 et à la carte 3 les consignes de positions lues par la carte 1 ?
4b) Peut-on éviter d’introduire une 4ème pour uniquement lire les consignes de position sur le port USB et retransmettre les consignes aux 3 autres cartes ?

Hello @Magician,

Thanks for your kind support.

Yes, I have positive results now. Was doing some mistake. Now I can confirm I have successfully changed the frequency according to your given instructions.

Bundle of Thanks.

Tfou57:
@ Magician, thank you for your interest in my problem

Question 3
3) Do 3 Arduino Due cards can simultaneously read -they common USB frame with 6 axes to manage?
Either the statement of 3 Arduino Due cards with the same COM number
Ideal solution for each card read only the positions of the instructions concerning
[

Question 3 of the previous post:
Sim Tools software that sends me the position setpoints can handle 6 different serial interfaces each with frame instructions postion
So I could have 3 cards in each of the same code management and they can operate independently if necessary
Problems 3 and 4: Resolved

Rest Questions 1, 2

Question 3 du post précédent:
Le logiciel Sim Tools qui m'envoie les consignes de position peut gérer 6 interfaces série différentes avec chacune sa trame de consignes de postion
Je pourrais donc avoir dans chacune des 3 cartes le même code de gestion et elles pourront fonctionner indépendament le cas échéant
Problèmes 3 et 4: Résolus

Reste les questions 1 et 2

Tfou57:
@ Magician, thank you for your interest in my problem

For 6 DAC, it takes 3 Arduino Due, each card will manage

Question 1

  1. How to control the DAC through direct management of ports and increasing the frequency to 1MHz without distorting the output voltage before I amplified by an operational amplifier?

Question 2
2a) Do you have feedback on the use of pin 34 (PWML0) and pin35 (PWMH0) taken as an example simple PWMC example - Arduino Due - Arduino Forum
2b) Direct management of digital ports with delayMicroseconds (1) between Does the risk inversions generate for a moment during the 2 signals forward and backward together?

I wouldn't use more than one DUE, communication/synchronization overhead would makes simple project over complex.

Put analog multiplexer at the arduino DAC output, and you will get as many DAC as you wish, with slower sampling rate, of course.

You may find an example of code to drive DAC at 1.6MHz here:Sinewave 100k generator, DAC + PDC + Timer. - Arduino Due - Arduino Forum

I have no answer for second question, post another thread to get response from more knowledgeable people .

@Magician

Magician:
I wouldn't use more than one DUE, communication/synchronization overhead would makes simple project over complex.

Put analog multiplexer at the arduino DAC output, and you will get as many DAC as you wish, with slower sampling rate, of course.

Multiplexer a DAC is similar to the multiplexing of other outputs?
Multiplexer un DAC est similaire au multiplexage des autres sorties ?

Front of multiplex, my goal is to order already 2 DAC 12 bits with a sampling frequency that is important but reasonable to not create distortion of the signal output DAC0 and DAC1

Avant de multiplexer, mon but est de commander déjà 2 DAC 12 bits avec une fréquence d’échantillonnage importante mais raisonnable pour pas créer de distorsion du signal en sortie DAC0 et DAC1

You may find an example of code to drive DAC at 1.6MHz here:Sinewave 100k generator, DAC + PDC + Timer. - Arduino Due - Arduino Forum

I admit, I looked at your example and "Glupps"... "I did not understand are work despite research...

I think that this example is for the creation of a sinusoidal signal.

In my use I would have a continuous signal of:

  • 0.544V to a value of 0
  • 1.65V for a value of 2048
  • 2.75v to a value of 4095

J’avoue, j’ai regardé votre exemple et « Glupps … » je n’ai pas compris sont fonctionnent malgré des recherches…
Je pense que cet exemple concerne la création d’un signal sinusoïdal.
Dans mon utilisation j’aurais un signal continu de :
* 0,544V pour une valeur de 0
* 1,65v pour une valeur de 2048
* 2.75v pour une valeur de 4095

In my research I found this link that manages the DAC with direct access to the registers of the DAC

http://forum.arduino.cc/index.php?topic=198758.0

J’ai trouvé dans mes recherches ce lien qui gère les DAC avec un accès direct aux registres de la DAC

Question 1 :
Can you help me to increase this chunk of code in order to increase its sampling frequency while remaining in 12bits?
Question 2 :
Please also tell me how to get other frequencies if the signal a distortions as a result of verification to the oscilloscope.
Thanks for all the information you can give me!

Question 1 :
Pouvez-vous m’aider à augmenter ce bout de code afin d’augmenter sa fréquence d’échantillonnage tout en restant en 12bits ?
Question 2 :
Merci de m’indiquer également comment obtenir d’autres fréquences si le signal a des distorsions à la suite de vérification à l’oscilloscope.
Merci pour toutes les informations que vous prouvez m’apporter !

Q1. No.
Q2. Don't understand.

Magician:
Q1. No.

Q1. No.
Where is the difficulty?
Will help to learn?
Do you have a suitable code I could study ?
Thank you

My analytical mind says, it's a waste of time to try to help you. You are too far from the required level for completing such project. Start from the beginning, like everyone does, blinking led. No offence mean.

Magician:
My analytical mind says, it's a waste of time to try to help you. You are too far from the required level for completing such project. Start from the beginning, like everyone does, blinking led. No offence mean.

Too bad!

Thank you!

Where is the file variant.h in IDE version 1.6.12? Although the Board Manager says that I have the Due software installed (v 1.6.9) and I can program my Due, I cannot find the variant.h file so that I can change the PWM frequency as discussed above.

Are you using windows or mac platform?

Hi. how can I change pwm frequency in pin13 to 150khz in arduino due?

antodom:
Have a look to pwm_lib available at:

GitHub - 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.

hello, and thank you for the library, it is exactly what i need -- however there is a problem.... the examples error out, looking for include file "tc_lib.h". do you know what library provides this dependency? or is it a file missing from your library?

Hi there @tom,

You can find tc_lib at GitHub - antodom/tc_lib: This is a library to take advantage of different functionalities available on Timer Counter (TC) modules in Arduino Due's Atmel ATSAM3X8E microcontrollers.

Library pwm_lib, itself, does not depend on tc_lib, but the examples do depend on it, as they use tc_lib for measuring duty and period of the PWM signals generated by pwm_lib, and for verifing its correct behaviour.

I hope it helps.
Best regards.