Go Down

Topic: By the registers how to prohibit to have 2 digital pins at the same time in ON ? (Read 4644 times) previous topic - next topic

Tfou57

I can not get DTUPD to work properly using either:
Uint32_t DTUPD = 100;
REG_PWM_DT2 = DTUPD << 16;

or

REG_PWM_ DTUPD2 = 100

By consulting the Datasheet in Chapter 38.7.44 on page 1052

• DTHUPD: updating the dead time value for the PWMHx output
Sets the dead time value for the PWMHx output.
This value must be set between 0 and CPRD-CDTY (PWM_CPRx and PWM_CDTYx).
This value is only applied at the beginning of the next channel period x PWM.

• DTLUPD: updating the dead time value for the PWMLx output
Sets the dead time value for the PWMLx output.
This value must be set between 0 and CDTY (PWM_CDTYx).
This value is applied only at the beginning of the next channel period x PWM
With DTHUPD and DTLUPD it works in part with
- a cyclic irregularity
- No Dead Time after program void P39_HIGH_and_P43_LOW () or at the beginning of void P39_LOW_and_P43_HIGH ()

I tested the code again by Arduino in stages:
Void Setup () only = OK -> Pin 39 LOW and Pin 43 LOW
Void Setup () Setup
+ Void P39_LOW_and_P43_LOW () = OK -> Pin 39 LOW and Pin 43 LOW

Void Setup ()
+ Void P39_LOW_and_P43_LOW ()
+ Void P39_HIGH_and_P43_LOW () without DeadTime
+ Void P39_LOW_and_P43_HIGH () without DeadTime
-------------------------------------------------------------------------
= Enchainent expected but with an irregular cyregular irregularity (like a hockey!) In Void P39_LOW_and_P43_LOW () and Void P39_HIGH_and_P43_LOW () without DeadTime

I think the Dead Time of Void P39_LOW_and_P43_LOW () works badly, it has like a hockey in general every 7, 6ms. Recall my PWM frequency is 10Khz

(See attachment, time is from left to right)



QUESTIONS

1) Have tracks to make the Dead Time of Void P39_LOW_and_P43_LOW () more regular?

2) Limit of regularity of Arduino Due?

3) Do you have a similar code to suggest for study?

4) How to operate the Dead Time of void P39_HIGH_and_P43_LOW () and void P39_LOW_and_P43_HIGH?
I tried different values, no value creates coherent Dead Time.

5) Does anyone have the ability to redo an observation with another oscilloscope?



*************************************


Je n'arrive pas à faire fonctionner DTUPD correctement en utilisant soit :
uint32_t DTUPD =100;
REG_PWM_DT2 = DTUPD << 16;

ou

REG_PWM_ DTUPD2 = 100

En consultant le Datasheet  au Chap 38.7.44 à la page 1052

• DTHUPD: mise à jour de la valeur de temps mort pour la sortie PWMHx
Définit la valeur de temps mort pour la sortie PWMHx.
Cette valeur doit être définie entre 0 et CPRD-CDTY (PWM_CPRx et PWM_CDTYx).
Cette valeur n'est appliquée qu'au début de la prochaine période de canal x PWM.

• DTLUPD: mise à jour de la valeur de temps mort pour la sortie PWMLx
Définit la valeur de temps mort pour la sortie PWMLx.
Cette valeur doit être définie entre 0 et CDTY (PWM_CDTYx).
Cette valeur n'est appliquée qu'au début de la prochaine période de canal x PWM

Avec DTHUPD et DTLUPD cela fonctionne en partie avec
- une irregularité cyclique
- Pas de Dead Time après le programme void P39_HIGH_and_P43_LOW()  ou au début de void P39_LOW_and_P43_HIGH()  

J'ai testé à nouveau le code par Arduino par étapes :
Void Setup () seul = OK    -> Pin 39 LOW et Pin 43 LOW
Void Setup () Setup
+ Void  P39_LOW_and_P43_LOW () = OK    -> Pin 39 LOW et Pin 43 LOW

Void Setup ()
+ Void  P39_LOW_and_P43_LOW ()  
+ Void  P39_HIGH_and_P43_LOW () sans DeadTime
+ Void  P39_LOW_and_P43_HIGH () sans DeadTime  
----------------------------------------------------------------------------
= Enchainent attendu mais avec une irrégularité cylique irrégulière ( comme un hocquet !) en Void  P39_LOW_and_P43_LOW () et Void  P39_HIGH_and_P43_LOW () sans DeadTime

Je pense que le Dead Time du Void  P39_LOW_and_P43_LOW ()  fonctionne mal, il a comme un hocquet  en général toutes les 7, 6ms. Rappel ma fréquence PWM est de 10Khz

(Voir pièce jointe, le temps se déroule de gauche à droite)



QUESTIONS

1) Avez des pistes pour rendre le Dead Time du Void  P39_LOW_and_P43_LOW () plus régulier ?

2) Limite de régularité de l'Arduino Due ?

3) Avez-vous un code similaire à proposer pour étude ?

4) Comment faire fonctionner le Dead Time de void  P39_HIGH_and_P43_LOW () et de void  P39_LOW_and_P43_HIGH ?
J'ai essayé différentes valeurs, aucune valeur ne crée des Dead Time cohérents.

5) Est-ce que quelqu'un à la possibilité de refaire un constat avec un autre oscilloscope ?

ard_newbie

Your code becomes very very difficult to decipher…  :smiley-confuse:  

1/ Once you have set CPRD and CDTY, it gives you a frequency and a duty cycle for either PWMHx AND PWMLx (x=2 in your code).

2/ You set nowhere in your code :  

PWM->PWM_CH_NUM[2].PWM_DTUPD = DTHUPD | DTLUPD << 16;

Whereas you need to set this register, once PWM channel 2 is enabled, to UPDate dead time.

See a new example below where dead time is updated every 1500 ms :

Code: [Select]

#define DISABLE_SW_PROT (0)
#define ENABLE_SW_PROT  (1)
#define ENABLE_HW_PROT  (2)
#define PASSWD  (0x50574D)

uint32_t DTH = 0;                      //DTH is between 0 and CPRD - CDTY BUT MAX value = 2 exp13  - 1 = 8191
uint32_t DTL = 0;                      //DTL is between 0 and CDTY BUT MAX value = 2exp13 - 1 = 8191

void setup () {

  // PWM Set-up on pins PC7 and PA20 (Arduino Pins 39(PWMH2) and 43(PWML2)): see Datasheet chap. 38.5.1 page 973


  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // PWM power on
  PWM->PWM_WPCR = PWM_WPCR_WPCMD(DISABLE_SW_PROT)
                  | PWM_WPCR_WPRG0
                  | PWM_WPCR_WPRG1
                  | PWM_WPCR_WPRG2
                  | PWM_WPCR_WPRG3
                  | PWM_WPCR_WPRG4
                  | PWM_WPCR_WPRG5
                  | PWM_WPCR_WPKEY(PASSWD);  // Disable PWM write protect
  PWM->PWM_DIS = PWM_DIS_CHID2;                        // Disable PWM channel 2

  // Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pin 39, see pinout diagram) ; Peripheral=B
  PIOC->PIO_PDR |= PIO_PDR_P7;                          // Set PWM pin to an output

  PIOC->PIO_ABSR |= PIO_PC7B_PWMH2;                     // Set PWM pin perhipheral type B

  // Select Instance=PWM; Signal=PWML2 (channel 2); I/O Line=PA20 (P20, Arduino pin 43, see pinout diagram) ; Peripheral=B
  PIOA->PIO_PDR |= PIO_PDR_P20;                          // Set PWM pin to an output

  PIOA->PIO_ABSR |= PIO_PA20B_PWML2;                    // Set PWM pin perhipheral type B


  // Enable the PWM channel 2 (see datasheet page 973)

  PWM->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

  PWM->PWM_CH_NUM[2].PWM_CMR = PWM_CMR_CPRE_CLKA;     // The period is left aligned, clock source as CLKA on channel 2

  PWM->PWM_CH_NUM[2].PWM_CPRD = 1000;                             // Channel 2 : Set the PWM frequency 2MHz/(2 * CPRD) = F ;

  PWM->PWM_CH_NUM[2].PWM_CDTY = 500;                             // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ;

  // Dead time between 2 complementary PWM H and L, e.g.:
  PWM->PWM_CH_NUM[2].PWM_CMR |= PWM_CMR_DTE;                       // Enable dead time

  /****  Try with (DTH=500, DTL=0) then (DTH=0,DTL=500) ****/
  DTH = 0;                                                //DTH is between 0 and CPRD - CDTY BUT MAX value = 2 exp13  - 1 = 8191
  DTL = 0;                                              //DTL is between 0 and CDTY BUT MAX value = 2exp13 - 1 = 8191
  /**********************************************************/

  PWM->PWM_CH_NUM[2].PWM_DT = DTH | DTL << 16;                     // Datasheet chap. 38.6.2.4 page 981 and chap. 38.7.43 page 1051

  PWM->PWM_ENA = PWM_ENA_CHID2;

  // Alternately, you can use this format :  REG_PWM_CPRD2 = 1000;


}


void loop() {
  boolean flag = false;
  if (flag == false) {

    DTH = 500;
    DTL = 0;
    PWM->PWM_CH_NUM[2].PWM_DTUPD = DTH | DTL << 16;
    delay(1500);
    flag = true;
  }

  if (flag == true) {

    DTH = 0;
    DTL = 500;
    PWM->PWM_CH_NUM[2].PWM_DTUPD = DTH | DTL << 16;
    delay(1500);
    flag = false;
  }                                  
 
}







Tfou57

Quote
Your code becomes very difficult to decipher ...
Sorry! :-*
- for lines canceled and posted
- for plenty of comments
- For the comments in French, it was my working file!


REG_PWM_DT2 = DTHUPD | DTLUPD <16;
# Of
PWM-> PWM_CH_NUM [2] .PWM_DTUPD = DTHUPD | DTLUPD << 16; ?

I thought REG_PWM_DT2 = DTHUPD | DTLUPD << 16 was an identical but abbreviated way of writing and the 2 of DT2 meant channel 2!

When to use one writing or the other?
One method is faster and more reliable than the other?

Tomorrow, with head rested, I will adapt your code :

1) To set the PWM frequency to 10Khz
10Khz in 12 bits are also the frequency and the resolution of the 6 pins PWM Timer that I will use for the     drive speed setpoint.
The 6 pins PWM Timer 2,3,4,5,10,11
Frequency PWM Timer of 10Khz 12 bits being obtained modifying variant.h
(I have already tried 40Khz, but at this frequency the CPU heats up and the Arduino Due is HS after several hours ... A card already lost in the field of honor, CPU boiling and refusing to upload a new code. ...)

2) To add the important step, pin 39 LOW and pin 43 LOW
(case of future operation as soon as the position  setpoint is reached)

3) To put a shorter delay between each change of state to visualize to the oscilloscope over a width of screen the set of the 3 stages as well as the Dead Time with each change of state


What do you think of the problem of cyclical irregularity that I observed ...?




Quote
Your code becomes very very difficult to decipher…  
Désolé !
- pour les lignes annulées et mises en commentaires
- pour abondance de commentaires
- Pour les commentaires en Français, c'était mon fichier de travail !


REG_PWM_DT2 = DTHUPD | DTLUPD << 16;  
# de
PWM->PWM_CH_NUM[2].PWM_DTUPD = DTHUPD | DTLUPD << 16; ?

Je pensais que REG_PWM_DT2 = DTHUPD | DTLUPD << 16 était une façon identique mais écrite de façon abrégée et le 2 de DT2 signifiait le canal 2 !

Quand utiliser une écriture ou l'autre ?
Une méthode est plus rapide et fiable que l'autre ?

Demain , à tête reposée , je vais adapter votre code:

1) Pour mettre la fréquence PWM de 10Khz
10Khz en 12 bits sont  également la fréquence et la résolution des 6 pins PWM Timer que j'utiliserai pour la consigne de vitesse des variateurs .
Les 6 pins PWM Timer 2,3,4,5,10,11
Fréquence PWM Timer de 10Khz 12 bits étant obtenue modifiant variant.h
(J'ai déjà essayé 40Khz, mais à cette fréquence le CPU chauffe et l'Arduino Due est HS après plusieurs d'heures ... Une carte déjà perdue au champs d'honneur, CPU bouillant et refus de téléverser un nouveau code....)

2)Pour rajout l'étape importante, pin 39 LOW et pin 43 LOW ( cas du fonctionnement futur dès que la consigne de position est atteinte)

3)Mettre un delay plus court entre chaque changement d'état pour visualiser à l'oscilloscope sur une largeur d'écran l'ensemble des 3 étapes ainsi que les Dead Time à chaque changement d'état

Je verrais ensuite sur la régularité cyclique du signal test est améliorée.

Que pensez-vous du problème d'irrégularité cyclique que j'avais observée ...?

Tfou57

Report of the day:
After changing the setup to have Pin 39 LOW and Pin 43 LOW at the end of the configuration
Changing these lines in Setup:
 PWM-> PWM_CH_NUM [2] .PWM_CDTY = 500;
 DTH = 500;
 DTL = 500;

Modification in your Loop loop for 1st test: Duty constant at 50% (Setup)
DTH = 50
DTL = 50
Delay reduction to 15ms

Finding:
Dead Time = OK with PWM at 50% (Setup configuration)

Bizarre! : With delay (15) ms or delay (0), the observed curves are identical

Your Loop Loop does not meet my needs, need 3 different states
Pin 39 LOW and pin 43 LOW which requires a duty at 50% and DTH = 500 and
DTL = 500

Pin 39 HIGH and pin 43 LOW which requires a duty at 0% and DTH = 50 and
DTL = 50
Pin 39 LOW and pin 43 HIGH which requires duty at 100% and DTH = 50 and
DTL = 50

I had to modify your loop Loop by adding another Boolean variable STOP and modify on the fly the duty

To change the duty on the fly, I used the following syntax:
PWM-> PWM_CH_NUM [2] .PWM_CDTYUPD = 500; For Pin 39 LOW and pin 43 LOW
PWM-> PWM_CH_NUM [2] .PWM_CDTYUPD = 0; For Pin 39 HIGH and pin 43 LOW
PWM-> PWM_CH_NUM [2] .PWM_CDTYUPD = 1000; For pine 39 HIGH and pine 43 LOW

Problem encountered after using PWM-> PWM_CH_NUM [2] .PWM_CDTYUPD = x

- The cyclical variation of the state of tilting of the pines is no longer regular at all!
- Duration during which Pin 39 is LOW and pin 43 is LOW constantly changes



Constat de la journée:

Après modifier le setup pour avoir Pin 39 LOW et Pin 43 LOW à la fin de la configuration
Modification de ces lignes dans Setup:
 PWM->PWM_CH_NUM[2].PWM_CDTY = 500;       
 DTH = 500;                                             
 DTL = 500;

Modification dans votre  boucle Loop pour 1er test : Duty constant à 50% (Setup)
DTH = 50   
DTL = 50
Réduction du delay à 15ms

Constat:

Dead Time = OK avec le PWM à 50% (configuration du Setup)

Bizarre ! : Avec delay(15)ms ou delay(0), les courbes observées sont identiques

Votre boucle Loop ne repondant pa à mes besoins, besoin de 3 états différents
Pin 39 LOW et pin 43 LOW    qui nécessite un duty à 50% et DTH = 500  et                                           
DTL = 500

Pin 39 HIGH et pin 43 LOW   qui nécessite un duty à 0% et DTH = 50  et                                           
DTL = 50
Pin 39 LOW et pin 43 HIGH   qui nécessite un duty à 100% et DTH = 50  et                                           
DTL = 50

J'ai dû modifier  votre boucle Loop en rajoutant une autre variable booléenne STOP et modifier à la volée le duty

Pour modifier le duty à la volée , j'ai utilisé la syntaxe suivante :
PWM->PWM_CH_NUM[2].PWM_CDTYUPD = 500;   pour Pin 39 LOW et pin 43 LOW   
PWM->PWM_CH_NUM[2].PWM_CDTYUPD = 0;   pour Pin 39 HIGH et pin 43 LOW   
PWM->PWM_CH_NUM[2].PWM_CDTYUPD = 1000;   pour pin 39 HIGH et pin 43 LOW   

Problème rencontré après l'utilisation de PWM->PWM_CH_NUM[2].PWM_CDTYUPD = x

-   La variation cyclique de m'état de basculement des pins n'est plus régulier du tout !
-   Durée durant laquelle la Pin 39 est LOW et pin 43 est LOW varie en permanence



ard_newbie


I am not entirely clear what you want but you will note that PWM controller has an output override feature : 38.6.2.5 page 982. You can override the output of PWMH and PWML.

By using buffer registers PWM_OSSUPD and PWM_OSCUPD, the output selection of PWM outputs is done synchronously to the channel counter, at the beginning of the next PWM period.

By using registers PWM_OSS and PWM_OSC, the output selection of PWM outputs is done asynchronously to the channel counter, as soon as the register is written.

While overriding PWM outputs, the channel counters continue to run, only the PWM outputs are forced to user defined values.



Tfou57

Quote
I am not entirely clear what you want
To control the direction of rotation of each of the 6 three-phase drives, I must send 2 High or LOW signals on the terminal blocks S1 and S2 of the drives

Between the Arduino Due 0v or 3.3v and the 0v or 24v drive, an ULN2803A interface will adapt to voltage and current

Terminals S1 and S2 may have 3 different status combinations
S1 = HIGH and S2 LOW when the motor must run in forward
S1 = LOW and S2 HIGH when the engine must run in reverse
S1 = LOW and S2 LOW when the position setpoint is reached

And prohibition to have at the same time S1 and S2 HIGH

Either in our example:
Pin39 = HIGH and pin 43 LOW when the motor must run in forward
Pin39 = LOW and pin 43 HIGH when the motor must run in reverse
Pin39 = LOW and pin 43 LOW when the position setpoint is reached


In addition to the 2 direction signals per drive, the Arduino Due managed a speed setpoint 0v to 3.3v using PWM TIOx as well as the motor position feedback.
The Arduino Due must manage the PID of each of the 6 motors in less than 1 ms (maximum value)

The switching of the direction of direction must therefore take place very quickly to avoid the Yoyo effect in the vicinity of the target position of the motors

Under no circumstances should S1 and S2 (pin39 and pin43) ever be HIGH at the same time.

This would cause the three-phase inverter to fail.
Hence the interest of a DeadTime during some μs



Quote
I am not entirely clear what you want
Pour commander le sens de rotation de chacun des 6 variateurs triphasé il me faut envoyer 2 signaux High ou LOW sur les borniers S1 et S2 des variateurs

Entre l'Arduino Due 0v ou 3.3v et le variateur 0v ou 24v , une interface  ULN2803A fera l'adaptation en tension et en intensité

Les borniers S1 et S2 pourront avoir 3 combinaisons d'état différentes
S1 = HIGH   et  S2  LOW   quand le moteur doit tourner en marche avant
S1 = LOW    et  S2  HIGH  quand le moteur doit tourner en marche arrière
S1 = LOW    et  S2  LOW   quand la consigne de position est atteinte

Et interdiction d'avoir en même temps S1 et S2 HIGH

Soit dans notre exemple :

Pin39 = HIGH  et pin 43 LOW quand le moteur doit tourner en marche avant
Pin39 = LOW  et pin 43 HIGH quand le moteur doit tourner en marche arrière
Pin39 = LOW  et pin 43 LOW quand la consigne de position est atteinte


Outre les 2 signaux de directions par variateur, l'Arduino Due géra une consigne de vitesse 0v à 3.3v à l'aide de PWM TIOx ainsi que le Feedback de position moteur.
L'Arduino Due devant gérer les PID de chacun des 6 moteurs en moins de 1 ms (valeur maximum)

La commutation des sens de direction doit donc s'effectuer de façon très rapide pour éviter l'effet de Yoyo aux alentours de la position cible des moteurs

En aucun cas S1 et S2 (pin39 et pin43) doivent être jamais HIGH en même temps.
Cela mettrait le variateur triphasé en défaut.
D'où l'intérêt d'un DeadTime durant quelque µs

Go Up