Go Down

Topic: Arduino Due Timer PWM Frequency change (Read 4747 times) previous topic - next topic

wachaudhary

Aug 26, 2016, 05:35 am Last Edit: Aug 26, 2016, 05:41 am by wachaudhary
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.

ard_newbie

Hello wachaudhary


Here is an example of PWM programming :

Code: [Select]

void setup () {
 
  // PWM Set-up on pin PC7 (Arduino Pin 39): see Datasheet chap. 38.5.1
  // Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pine 39, see pinout diagram) ; Peripheral=B

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // PWM on

  REG_PIOC_ABSR |= PIO_ABSR_P7;                        // Set PWM pin perhipheral type B

  REG_PIOC_PDR |= PIO_PDR_P7;                          // Set PWM pin to an output

  REG_PWM_ENA = PWM_ENA_CHID2;                         // Enable the PWM channel 2 (see datasheet page 973)
 
  REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42);    // Set the PWM clock rate to 2MHz (84MHz/42). Adjust DIVA for the resolution you are looking for
                                                     
  REG_PWM_CMR2 = PWM_CMR_CALG |PWM_CMR_CPRE_CLKA;      // The period is left aligned, clock source as CLKA on channel 2

  REG_PWM_CPRD2 = 1000000;                             // Channel 2 : Set the PWM frequency 2MHz/(2 * CPRD) = F ; 1< CPRD < 2exp24  -1 ; here CPRD = 10 exp 6

  REG_PWM_CDTY2 = 200000;                              // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % , CDTY = 2 * 10 exp 5

 // Alternatively, you can use this format :  PWM->PWM_CH_NUM[2].PWM_CPRD = 1000000 ;                   
 // In this example, Frequency is 1 HZ with a DT of 20% so you can see it with an LED attached to pin 39 with a resistor 
 
}


void loop() {
}

wachaudhary

Dear ard_newbie,

Is this code is for pin 3 and 4 as I think its for built it PWM channel adjustment. I think Arduino is using Timer 1 to control the above pins

Magician

I think, what you need is to locate a file in your installation and mod one line:
~/arduino15/packages/arduino/hardware/sam/1.6.9/variants/arduino_due_x/variant.h
Code: [Select]
#define TC_FREQUENCY        1000

wachaudhary

I think, what you need is to locate a file in your installation and mod one line:
~/arduino15/packages/arduino/hardware/sam/1.6.9/variants/arduino_due_x/variant.h
Code: [Select]
#define TC_FREQUENCY        1000
I have changed this. Sadly no change

Magician

https://drive.google.com/open?id=0Bw4tXXvyWtFVUFBoU0hsX2xkeUE

Have no idea why it doesn't do the trick for you, but it does for me.

Code: [Select]
void setup()
{
  //3&4 PC26&PC28 TIOB6 & TIOA7
  Serial.begin (115200) ;
  pinMode( 2, OUTPUT);
  digitalWrite( 2, LOW);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  analogWrite( 2, 128);
  analogWrite(13,  64);

  pinMode( 3, OUTPUT);
  digitalWrite( 3, LOW);
  pinMode( 4, OUTPUT);
  digitalWrite( 4, LOW);
  analogWrite( 3, 128);
  analogWrite( 4, 128);
}


Successfully tested on pins 2, 3, 4, 13 .

Tfou57

#6
Sep 13, 2016, 05:17 pm Last Edit: Sep 13, 2016, 10:21 pm by Tfou57
Hello @Magician,
I am interested in your way to easily increase the frequency of pine
> 2 (TIOA0)
> 3 (TIOA7)
> 4 (TIOB6)
> 13 (TIOB0)

1) Your method would not work also on other PWM?
     such as pines:
> 5 (TIOA6)
> 10 (TIOB7)
> 12 (TIOB8)

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

3) What is the maximum frequency that you get without distorting the PWM signal?

Thank you for your tip.


Bonjour @Magician ,
Je m'intéresse à votre moyen d'augmenter facilement les fréquences des pins
> 2 (TIOA0)
> 3 (TIOA7)
> 4 (TIOB6)
> 13 (TIOB0)

1) Votre méthode ne fonctionnerait pas également sur les autres PWM ?
    comme les pins:
> 5 (TIOA6)
> 10 (TIOB7)
> 12 (TIOB8)

2) En appliquant votre méthode, peut-on toujours configurer sans problème de distorsion de signal les    PWM en 12 bits ?

3) Quelle est la fréquence maximale que vous obtenez sans distorsion du signal PWM ?

Merci de votre astuce .


antodom

Hi there @wachaudhary,

Have a look to pwm_lib available at:

 https://github.com/antodom/pwm_lib

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

Magician

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)

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

3) 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:
Code: [Select]
* 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 .

Tfou57

#9
Sep 14, 2016, 12:38 pm Last Edit: Sep 14, 2016, 01:05 pm by Tfou57
Question 1

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

Code: [Select]

/*
 * 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

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?


Code: [Select]

// --------------------------------------------
//
// 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:

}

MartinL

#10
Sep 14, 2016, 01:47 pm Last Edit: Sep 14, 2016, 01:53 pm by MartinL
Quote
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):

Code: [Select]
// 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.

Magician

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

Tfou57

#12
Sep 14, 2016, 04:12 pm Last Edit: Sep 14, 2016, 07:39 pm by Tfou57
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 http://forum.arduino.cc/index.php?topic=325585.0

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 http://forum.arduino.cc/index.php?topic=325585.0
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 http://forum.arduino.cc/index.php?topic=325585.0

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 http://forum.arduino.cc/index.php?topic=325585.0
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 ?



wachaudhary

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

#14
Sep 14, 2016, 06:35 pm Last Edit: Sep 14, 2016, 06:51 pm by 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

Go Up