Auteur Sujet: PWM - Faire varier la fréquence  (Lu 41800 fois)

PhB22

  • Invité
PWM - Faire varier la fréquence
« le: février 02, 2017, 10:09:56 am »
Bonjour à tous,
J'ouvre un nouveau titre pour essayer de ne parler que d'un seul sujet, celui de la modification de la fréquence du PWM.
On trouve une allusion à ce sujet dans "loco LGB sans fil" et dans "Simulation daylight ".
Hier soir j'ai essayé de comprendre mais ????
Tout cela me parait un peu compliqué car peu de réelles explications du comment fait-on.
J'ai bien trouvé ceci mais c'est du charabia :
void setup() {
  // Set PB1/2 as outputs.
  DDRB |= (1 << DDB1) | (1 << DDB2);

  TCCR1A =
      (1 << COM1A1) | (1 << COM1B1) |
      // Fast PWM mode.
      (1 << WGM11);
  TCCR1B =
      // Fast PWM mode.
      (1 << WGM12) | (1 << WGM13) |
      // No clock prescaling (fastest possible
      // freq).
      (1 << CS10);
  OCR1A = 0;
  // Set the counter value that corresponds to
  // full duty cycle. For 15-bit PWM use
  // 0x7fff, etc. A lower value for ICR1 will
  // allow a faster PWM frequency.
  ICR1 = 0xffff;
}

void loop() {
  // Use OCR1A and OCR1B to control the PWM
  // duty cycle. Duty cycle = OCR1A / ICR1.
  // OCR1A controls PWM on pin 9 (PORTB1).
  // OCR1B controls PWM on pin 10 (PORTB2).
  OCR1A = 0x0000;
  delay(500);
  OCR1A = 0x8000;
  delay(500);
  OCR1A = 0xffff;
  delay(500);
}
Ma question est simple, si je veux telle ou telle fréquence, je dois mettre quoi dans quoi.
Autre question, si je modifie la fréquence, Est-ce que c'est fait définitivement dans mon MEGA?
Merci d'avance pour le partage d'expérience
Cordialement
Philippe
« Modifié: février 02, 2017, 10:37:22 am par PhB22560 »

Pierre59

  • Sr. Member
  • ****
  • Messages: 346
    • Voir le profil
Re : PWM - Faire varier la fréquence
« Réponse #1 le: février 02, 2017, 11:12:58 am »
Bonjour

Le code ressemble bien à cela, mais il est différent pour chaque Timer utilisé (ici c'est le Timer1 sur 16 bits), il y a deux Timers 8 bits et un Timer double sur 16 bits sur ATmega328. Le mieux serait de trouver une bibliothèque qui fait ce qu'il faut.

Ma question est simple, si je veux telle ou telle fréquence, je dois mettre quoi dans quoi.
Autre question, si je modifie la fréquence, Est-ce que c'est fait définitivement dans mon MEGA?
Merci d'avance pour le partage d'expérience
Cordialement
Philippe

On n'est pas trop maitre de la fréquence PWM précise, mais on peut choisir parmi quelques fréquences de basse à haute. La fréquence et déterminée par la fréquence du processeur (quartz) 16 MHz pour l'Arduino Uno, puis par des "prescalers" qui permettent de diviser la fréquence du processeur par quelques valeurs prédéfinies (différentes pour chaque Timer), puis par le nombre de pas PWM désirés (256 valeurs possibles de rapport cyclique par exemple)

J'ai, il y a un certain temps, utilisé un ATmega8 cadencé à 8mHz pour produire 4 PWM (chacune étant réglable de 0 à 255 indépendamment) en utilisant les deux Timers 8 bit et le Timer double sur 16 bits. Les fréquences des PWM étant toutes à 31250 Hz, soit 8MHz/1/256=31250 Hz, tous les prescalers étant réglés pour diviser par 1.

Pierre

PS Toutes ces manipulations pour la PWM ne modifient en rien la fréquence de l'horloge du processeur.

« Modifié: février 02, 2017, 11:30:10 am par Pierre59 »

PhB22

  • Invité
Re : PWM - Faire varier la fréquence
« Réponse #2 le: février 02, 2017, 11:57:54 am »
Merci pour ta réponse rapide.

Bon, donc il y a trois Timers (UNO ou MEGA) :
Le Timer 0 correspond aux broches 5 et 6
Le Timer 1 correspond aux broches 9 et 10
Le Timer 2 correspond aux broches 3 et 11.

Première chose : pas touche au Timer 2.
Cà tombe bien puisque je commande le pont en H avec les broches 5 et 6 donc le Timer 1.

D'après ce que j'ai compris la fréquence PWM "de base" est de 400 Hz.
Si je veux la faire varier, il me suffit de charger la bibliothèque qui va bien.

Par le gestionnaire de bibliothèque, j'ai trouvé une biblio qui s'appelle TimerOne by Jesse Tane et d'autres auteurs.
Est-ce bien cela?
Merci d'avance
« Modifié: février 02, 2017, 12:46:03 pm par PhB22560 »

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : PWM - Faire varier la fréquence
« Réponse #3 le: février 03, 2017, 11:20:55 am »
Sans aller jusqu'à utiliser la bibliothèque Timer1 (les bibliothèques sont présentées sur le PlayGround: http://playground.arduino.cc/Code/Timer1), tu peux simplement changer la division d'horloge du Timer1

Par défaut, la division d'horloge est mise à 64 dans les fonctions d'initialisation du logiciel Arduino. L'horloge utilisée pour les timers est de mémoire à la fréquence moitié de celle du CPU, 8MHz à 16MHz sur un Uno/Nano. Avec une division d'horloge de 64, ça donne une fréquence de 125kHz 250KHz pour le tick d'incrémentation du timer.

analogWrite fixe le rapport cyclique de 0 à 255, il faut donc 255 256 ticks et de plus comme la PWM du Timer1 est programmée en phase correct mode, il faut 2 fois ça pour une période, ce qui donne une fréquence de PWM de 250KHz/256/2 = (à peu près) 488 Hz.

Pour monter la fréquence de la PWM, il suffit de changer la la division d'horloge. Cela se fait en écrivant ce qu'il faut dans les bits 0, 1 et 2 du registre TCCR1B. Ces bits ont également pour petits noms CS2, CS1 et CS0 (CS pour Clock Select). Les combinaisons possibles sont

CS2CS1CS0Effet
000Aucune horloge, le timer ne compte pas
001division par 1
010division par 8
011division par 64
100division par 256
101division par 1024
110Horloge venant de la broche T1, sensible au front descendant
111Horloge venant de la broche T1, sensible au front montant

Mettre la valeur 001 dans ces 3 bits donnerait une fréquence de PWM de 800000016000000/256/2 = 31,25 kHz

Pour le faire, je te propose de mettre ceci dans setup :

TCCR1B &= 0xF8; /* CS2 = CS1 = CS0 = 0, coupe l'horloge */
sbi(TCCR1B,CS10); /* CS0 = 1 */
« Modifié: février 04, 2017, 09:55:07 am par Jean-Luc »
Cordialement

Pierre59

  • Sr. Member
  • ****
  • Messages: 346
    • Voir le profil
Re : PWM - Faire varier la fréquence
« Réponse #4 le: février 03, 2017, 11:43:05 am »
Bonjour

Très bonne idée, mais la fréquence de L'Arduino Uno est de 16MHz et je pense que le nombre de "ticks" est de 256. Ce qui donne une fréquence de PWM, si je me trompe pas, de 16 000 000/1/256=62500Hz.

Pierre

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : PWM - Faire varier la fréquence
« Réponse #5 le: février 03, 2017, 11:47:26 am »
Effectivement 256, pas 255 et oui, c'est 16MHz pour le tick pas 8MHz.

Par contre sur les Timers 1 et 2, la PWM est programmée en phase correct PWM mode, ce qui fait que le timer fait un aller-retour pour une période. Par conséquent c'est bien 16 000 000 / 1 / 256 / 2 (phase correct mode) = 31250 Hz et je l'avais vérifié à l'oscillo sur le Timer2.
Cordialement

PhB22

  • Invité
Re : PWM - Faire varier la fréquence
« Réponse #6 le: février 04, 2017, 09:17:20 am »
Bonjour à tous et merci à Pierre et Jean-Luc.
Ce W-D, je vais donc expérimenter ce que Jean-Luc m'a indiqué :
TCCR1B &= 0xF8; /* CS2 = CS1 = CS0 = 0, coupe l'horloge */
sbi(TCCR1B,CS0); /* CS0 = 1 */

On est bien d'accord que le Timer1 est celui qui "pilote" les broches PWM 5 et 6 ?

Je vais mettre dans le setup :
TCCR1B &= 0xF8; /* CS2 = CS1 = CS0 = 0, coupe l'horloge */
sbi(TCCR1B,001); /* CS0 = 1 */

Et en changeant la valeur de CS0 de 001 à 101, je devrais entendre une variation dans le "sifflement"  :) :) :)

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : PWM - Faire varier la fréquence
« Réponse #7 le: février 04, 2017, 09:24:53 am »
Non non non,  :)

sbi met le bit indiqué à 1.

EDIT : je me suis trompé dans les noms des constantes CS2, CS1 et CS0. Il existe en fait un jeu de constante par timer. CS02, CS01 et CS00 sont pour le timer 0, CS12, CS11 et CS10 sont pour le timer 1 et CS22, CS21 et CS20 sont pour le timer 2.

sbi(TCCR1B,001);
Va mettre le bit 1 à 1, c'est à dire CS1 ! Le résultat sera d'avoir ces 3 bits à 010, soit une division 8 et une fréquence de 4KHz environ.

sbi(TCCR1B,CS10);
fait exactement ce que tu veux, fréquence de 32KHz (j'arrondie), inaudible

Si tu veux mettre 101 dans CS2,CS1,CS0, ajoute

sbi(TCCR1B,CS12);
Fréquence 32Hz. Attention ! Va lire http://modelleisenbahn.triskell.org/spip.php?article44 et l'article suivant.
Le moteur va chauffer

Autre solution, si tu veux mettre directement 101,

TCCR1B |= B00000101;
Dans tous les cas, la ligne met ces 3 bits à 0,

TCCR1B &= 0xF8;
Doit être conservée. Elle peut aussi s'écrire :

TCCR1B &= B11111000;
Pour ces histoires de manipulations de bits, voir http://www.locoduino.org/spip.php?article70
« Modifié: février 04, 2017, 09:54:43 am par Jean-Luc »
Cordialement

PhB22

  • Invité
Re : PWM - Faire varier la fréquence
« Réponse #8 le: février 04, 2017, 09:44:23 am »
Bon, avant de commencer je vais essayer de digérer tout cela.
En tout cas merci à toi.
De toute manière cela ne va pas "casser" le UNO et "qui ne tente rien, n'a rien"  ;) ;)

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : Re : PWM - Faire varier la fréquence
« Réponse #9 le: février 04, 2017, 09:49:31 am »
On est bien d'accord que le Timer1 est celui qui "pilote" les broches PWM 5 et 6 ?

Ah non. Si j'en crois ce qu'a écrit Christian : http://www.locoduino.org/spip.php?article119, ce sont les broches 9 et 10 pour le Timer 1

Et non, le Uno ne risque absolument rien ;-)
« Modifié: février 04, 2017, 09:55:48 am par Jean-Luc »
Cordialement

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : PWM - Faire varier la fréquence
« Réponse #10 le: février 04, 2017, 10:19:21 am »
Les broches 5 et 6 correspondent aux PWM générée via le Timer 0

Contrairement aux PWM générées via le Timer 1 et le Timer 2, celles du Timer 0 ne sont pas en phase correct PWM mais en fast PWM. Ceci fait que la fréquence est deux fois plus élevée (par défaut 976 Hz environ)

Le Timer 0 est celui qui permet également à l'Arduino de compter le temps (c'est pour cela qu'il est programmé en fast PWM). Il est à cet effet avec une division de 64. Avec l'horloge à 16MHz, il compte à 250 KHz et déborde au bout de 256 coups, soit tous les 1,024 ms, une interruption se produit, ce qui donne la base de temps.

Si tu changes la division de l'horloge sur le Timer 0, tu auras le choix entre les fréquences suivantes pour la PWM :
  • 62,5kHz : division par 1, interruption toutes les 16µs (oups), le temps coule 64 fois plus vite
  • 7,8125KHz : division par 8, interruption toutes les 128µs, le temps coule 8 fois plus vite
  • ...

Il vaut mieux changer de broches je pense pour être sur le Timer 1
Cordialement

PhB22

  • Invité
Re : PWM - Faire varier la fréquence
« Réponse #11 le: février 04, 2017, 10:45:28 am »
Il vaut mieux changer de broches je pense pour être sur le Timer 1
D'accord. C'est un peu pour cela que j'insistais sur le numéro du Timer.
Donc Timer1 et utilisation des broches 9 et 10

Fréquence 32Hz. Attention ! Va lire http://modelleisenbahn.triskell.org/spip.php?article44 et l'article suivant.
Le moteur va chauffer
Je viens de lire...  ;) ;) ;) Cela m'a ramené en Terminal F3. Ouh là, ça ne rajeunit pas.  ;)
Mais je connaissais. Merci tout de même pour le lien car ces deux dossiers sont très bien faits.


Je vais partir en écrivant dans le setup :
TCCR1B &= 0xF8;
TCCR1B |= B00000101;

Et je verrais en faisant varier les 3 derniers chiffres : 000, 001, 010 etc.

PhB22

  • Invité
Re : PWM - Faire varier la fréquence
« Réponse #12 le: février 04, 2017, 02:15:33 pm »
Et bien voila, ça fonctionne et plus de sifflement  :D :D :D
J'ai donc mis dans le setup :

TCCR1B &= 0xF8;
TCCR1B |= B00000001;

Puis j'ai fais varier les 3 derniers chiffres de 001 à 101 pour diviser par 1 ... 1054.

Avec un gros moteur ROCO du genre de celui qui est dans le locotracteur Y 8000 voici ce que ça donne :
- avec " TCCR1B |= B00000001; " et " TCCR1B |= B00000010; "  c'est tout en souplesse et plus de sifflement :D :D :D
- avec " TCCR1B |= B00000011; " on retrouve le sifflement
- avec " TCCR1B |= B00000100; " ça "grogne"
- avec " TCCR1B |= B00000101; " ç'est le pire, on dirait que le moteur a le hoquet

J'allais oublié : pas d'échauffement anormal avec au moins cinq minutes de montée/descente de vitesse.

Là, un grand grand merci à Pierre et Jean-Luc.

Je vais maintenant faire des tests sur d'autres moteurs (JOUEF, BUHLER, en HO ou en N)
« Modifié: février 04, 2017, 02:20:04 pm par PhB22560 »

PhB22

  • Invité
Re : PWM - Faire varier la fréquence
« Réponse #13 le: février 04, 2017, 03:12:43 pm »
J'ai donc continué avec tous les moteurs que j'avais (train ou autre), il y a même un Electrotren (ABJ). Voir photo.

Pour tous  " TCCR1B |= B00000001; " ou " TCCR1B |= B00000010; " fonctionnent avec peut-être une préférence (démarrage, bruit) pour " TCCR1B |= B00000010; " donc dans les 15kHz si je ne me trompe pas.

Ce que je retire de cet essai : deux lignes de commande simples suffisent!

Encore merci
Philippe


« Modifié: février 04, 2017, 03:18:51 pm par PhB22560 »

Jean-Luc

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 1714
    • Voir le profil
Re : PWM - Faire varier la fréquence
« Réponse #14 le: février 04, 2017, 03:19:17 pm »
Divisé par 8 donc 4kHz (un peu bas concernant la dissipation thermique). Niveau bruit le 32kHz devrait être mieux.
Cordialement