LOCODUINO

Aide
Forum de discussion
Dépôt GIT Locoduino
Flux RSS

mardi 19 mars 2024

Visiteurs connectés : 31

La PWM : Qu’est-ce que c’est ? (3)

Changer la fréquence de la PWM

.
Par : Jean-Luc

DIFFICULTÉ :

Dans l’article précédent, « La PWM : Qu’est-ce que c’est ? (2) », nous avons vu comment piloter un moteur et nous avions noté que la PWM par défaut proposée par le logiciel Arduino était à une fréquence relativement basse, environ 490 Hz. Une telle fréquence présente deux inconvénients. Tout d’abord, le moteur émet un son correspondant à sa fréquence. Or, entre 20Hz et 20000Hz, nous somme dans les fréquences audibles. Ensuite, comme exposé dans une série d’article sur l’alimentation par PWM, une fréquence trop basse engendre des pertes par effet joule et fait chauffer le moteur. Nous allons donc voir comment modifier la fréquence de la PWM de l’Arduino.

<

Les PWM sur les Arduino à base d’AVR 328 (Uno, Nano, Pro Mini, ...) sont au nombre de 6 et sont disponibles sur les broches 3, 5, 6, 9, 10, et 11. À l’intérieur du micro-contrôleur, les PWM sont associées, par paire, à un des 3 timers dont dispose le micro-contrôleur. L’association est résumée dans la table suivante :

TimerSorties du module Uno
timer0 5 et 6
timer1 9 et 10
timer2 3 et 11

Toutes le informations relatives à ces timers peuvent être trouvées dans la série d’articles de Christian en commençant par le premier « Les Timers (I) ».

À quelles fréquences sont les PWM

Les timers comptent au rythme de l’horloge du module Arduino. Cette horloge de base est la plupart du temps à 16MHz [1]. À cela vient s’ajouter la possibilité de diviser l’horloge pour ralentir le timer, voire de la couper purement et simplement. Comme expliqué dans « Les Timers (I) », les bits de contrôle du diviseurs sont situés dans les 3 bits de poids faible du registre TCCRxB ou x est le numéro du timer. Ces bits sont également appelés CSx2 (bit 2), CSx1 (bit 1) et CSx0 (bit 0), CS signifie Clock Select, sélection d’horloge en français. Les combinaisons suivantes de ces bits permettent de régler le diviseur :

Configuration de l’horloge des timers 0 et 1
CSx2CSx1CSx0Diviseur / fonction spéciale
0 0 0 Pas d’horloge
0 0 1 division par 1 (pas de division donc)
0 1 0 division par 8
0 1 1 division par 64
1 0 0 division par 256
1 0 1 division par 1024
1 1 0 source d’horloge sur la broche Tx [2], front descendant
1 1 1 source d’horloge sur la broche Tx, front montant
Configuration de l’horloge du timer 2
CS22CS21CS20Diviseur / fonction spéciale
0 0 0 Pas d’horloge
0 0 1 division par 1 (pas de division donc)
0 1 0 division par 8
0 1 1 division par 32
1 0 0 division par 64
1 0 1 division par 128
1 1 0 division par 256
1 1 1 division par 1024

Le logiciel Arduino configure ces timers de la manière suivante :

  • Le timer 0 est configuré avec une division par 64 et la PWM est en Fast PWM Mode ;
  • Les timers 1 et 2 sont configurés avec une division par 64 et la PWM est en Phase Correct PWM Mode.

Ces deux modes sont décrits dans « Les Timers (IV) ».

Tous les timers comptent donc à un rythme de 16MHz/64 = 250kHz, 250000 ticks par seconde. En Fast PWM Mode, un cycle de la PWM correspond à 256 ticks. Les PWM du timer 0 sont donc par défaut à 250kHz/256 = 976,5625Hz. En Phase Correct PWM Mode le timer fait un aller-retour : de 0 à 255 puis de 255 à 0, soit 510 ticks. Le cycle de la PWM est donc égal à 250kHz/510 et les PWM des timers 1 et 2 sont donc à 490,2Hz.

Peut-on changer la fréquence sans risque

Bien évidemment les timers sont utilisés pour de nombreuses fonctions dans le logiciel Arduino. Changer la fréquence des PWM n’est donc pas sans risque pour le bon fonctionnement du logiciel.

Le timer 0

Le timer 0 est employé pour fournir le temps au logiciel Arduino. Quand vous employez les fonctions delay(...), delayMicroseconds(...) ou bien encore millis() et micros(), c’est en fait le comptage de temps engendré par l’interruption du timer 0 qui est employé. Cette interruption va survenir à une fréquence de 976,5625Hz ce qui correspond à une période de 1,024 ms. Elle incrémente un compteur en l’ajustant de manière à compter des milli-secondes.

On comprend donc que changer la fréquence de comptage du timer 0 va également changer le comptage du temps, ce qui risquent de faire dérailler de nombreuses fonctions et de nombreuses bibliothèques. Il vaut donc mieux utiliser les deux autres timers si on veut changer la fréquence de la PWM.

Le timer 1

Ce timer est utilisé par la bibliothèque Servo. Si vous n’utilisez pas cette bibliothèque dans votre application, le timer 1 est libre pour vos PWM « customisées ».

Le timer 2

Enfin, le timer 2 est utilisé par la bibliothèque Tone, destinée à produire des sons. Ici aussi si cette bibliothèque ne vous est pas utile, usez librement du timer 2.

Comment changer la fréquence en pratique

Pour modifier la fréquence des PWM liées à ces timers, il suffit d’écrire les valeurs adéquates dans les 3 bits de poids faible des registres TCCR1B pour le timer 1 et TCCR2B pour le timer 2.

Si on reprend la table ci-dessus en substituant la fréquence de la PWM à la division, on a ceci :

Fréquences arrondies de PWM possibles pour les PWM liées au timer 1
CS12CS11CS10Fréquence en Hz
0 0 1 31373
0 1 0 3922
0 1 1 490
1 0 0 123
1 0 1 31
Fréquences arrondies de PWM possibles pour les PWM liées au timer 2
CS22CS21CS20Fréquence en Hz
0 0 1 31373
0 1 0 3922
0 1 1 980
1 0 0 490
1 0 1 245
1 1 0 123
1 1 1 31

Pour les moteurs des engins en N et pour les moteurs à rotor sans fer, on préférera la fréquence de 31373Hz. Pour les autres la fréquence de 3922 est utilisable. Voir à ce propos la série d’article « Tension hachée et pertes par effet Joule »

Une fonction de configuration

Pour configurer la fréquence de la PWM, je vous propose une fonction de configuration : setPWMFrequency. Cette fonction prend 2 arguments. Le premier sert à désigner la paire de broches concernée, la seconde la fréquence. Comme tout n’est pas permis, nous allons d’abord déclarer quelques constantes. Tout d’abord 2 constantes permettant de désigner la paire de broche :

const byte PINS_9_10 = 0;
const byte PINS_3_11 = 1;

Ensuite, 5 constantes, une pour chaque fréquence permise. Nous allons arrondir les noms à des valeurs arrondies aux dizaines des fréquences des PWM : 32k, 4k, 1k, 500, 250, 125 et 30, afin de nous en souvenir plus facilement même si en réalité les valeurs seront un peu différentes, nous ne sommes pas à quelques % près :

const byte PWM_32k = 0;
const byte PWM_4k  = 1;
const byte PWM_1k  = 2;
const byte PWM_500 = 3;
const byte PWM_250 = 4;
const byte PWM_125 = 5;
const byte PWM_30  = 6;

Ces fréquences sont toutes possibles pour les broches 3 et 11 mais pas pour les broches 9 et 10 car le timer 1 ne permet pas la division par 32 (1k) et par 128 (250).

Comme le codage est différent entre le timer 1 et le timer 2, nous allons utiliser deux tables de constantes indexé par les constantes définies ci-dessus. La première table va donner les codes de CS pour le timer 1 et la seconde pour le timer 2. Les fréquences manquantes pour le timer 1 seront remplacées par le code 0, qui coupe l’horloge.

const byte codeForTimer1[] PROGMEM = {
  B00000001,
  B00000010,
  B00000000, /* no clock if config not allowed */
  B00000011, 
  B00000000, /* no clock if config not allowed */
  B00000100,
  B00000101,
};

const byte codeForTimer2[] PROGMEM = {
  B00000001,
  B00000010,
  B00000011,
  B00000100, 
  B00000101,
  B00000110,
  B00000111,
};

Enfin la fonction qui met en place ces codes dans le registre TCCR1B ou TCCR2B selon la paire de broche. Nous allons faire particulièrement attention aux arguments passées à la fonction et vérifier qu’il s’agit de valeurs autorisées. La fonction échouera silencieusement si les arguments sont hors de la gamme permise. Concernant le code de la fréquence, il suffira de tester que l’argument est inférieur à 7.

void setPWMFrequency(byte pins, byte frequency)
{
  if (frequency < 7) {
    if (pins == PINS_9_10) {
      byte csCode = pgm_read_byte_near(codeForTimer1 + frequency);
      TCCR1B &= B11111000; /* aucune horloge */
      TCCR1B |= csCode;
    }
    else if (pins == PINS_3_11) {
      byte csCode = pgm_read_byte_near(codeForTimer2 + frequency);
      TCCR2B &= B11111000; /* aucune horloge */
      TCCR2B |= csCode;
    }
  }
}

L’utilisation de la fonction est simple, dans setup(), appelez là avec les arguments adéquats. Par exemple, si vous souhaitez configurer la fréquence des broches de PWM 9 et 10 à 31373Hz, il suffit d’écrire :

setPWMFrequency(PINS_9_10, PWM_32k);

Voici le tout encapsulé dans une bibliothèque qu’il vous suffira d’installer sur votre machine.

Bibliothèque PWMFreq

Bon pilotage de moteurs.

[1Mais sur certains modèles et sur certains clones chinois, elle peut être plus basse, 8MHz ou 12MHz.

[2Sur l’Arduino, il s’agit de la broche 4 pour le timer 0, la 5 pour le timer 1

7 Messages

Réagissez à « La PWM : Qu’est-ce que c’est ? (3) »

Qui êtes-vous ?
Votre message

Pour créer des paragraphes, laissez simplement des lignes vides.

Lien hypertexte

(Si votre message se réfère à un article publié sur le Web, ou à une page fournissant plus d’informations, vous pouvez indiquer ci-après le titre de la page et son adresse.)

Rubrique « Projets »

LaBox, Une Centrale DCC polyvalente et abordable (1)

LaBox, Une Centrale DCC polyvalente et abordable (2)

LaBox, Une Centrale DCC polyvalente et abordable (3)

Comment piloter trains et accessoires en DCC avec un Arduino (1)

Comment piloter trains et accessoires en DCC avec un Arduino (2)

Comment piloter trains et accessoires en DCC avec un Arduino (3)

Comment piloter trains et accessoires en DCC avec un Arduino (4)

SGDD : Système de Gestion DD (1)

SGDD : Système de Gestion DD (2)

SGDD : Système de Gestion DD (3)

Mise en oeuvre du Bus CAN entre modules Arduino (1)

Mise en oeuvre du Bus CAN entre modules Arduino (2)

Un gestionnaire en C++ pour votre réseau (1)

Un gestionnaire en C++ pour votre réseau (2)

Un gestionnaire en C++ pour votre réseau (3)

Un gestionnaire en C++ pour votre réseau (4)

Réalisation de centrales DCC avec le logiciel libre DCC++ (1)

Réalisation de centrales DCC avec le logiciel libre DCC++ (2)

Réalisation de centrales DCC avec le logiciel libre DCC++ (3)

Contrôleur à télécommande infrarouge pour centrale DCC++

Gestion d’une gare cachée (1)

Gestion d’une gare cachée (2)

Gestion d’une gare cachée (3)

La carte Satellite V1 (1)

La carte Satellite V1 (2)

La carte Satellite V1 (3)

La carte Satellite V1 (4)

La carte Satellite V1 (5)

Chenillard de DEL

Enseigne de magasin

Feux tricolores

Multi-animations lumineuses

L’Arduino et le système de commande numérique DCC

Un décodeur d’accessoire DCC versatile basé sur Arduino

Un moniteur de signaux DCC

Une barrière infrarouge

Un capteur RFID

Un TCO xpressnet

Une animation sonore

L’Arduino au coeur des systèmes de pilotage analogiques ou numériques

Calcul de la vitesse d’un train miniature avec l’Arduino

La génèse d’un réseau 100% Arduino

Une horloge à échelle H0

Simulateur de soudure à arc

Un automatisme de Passage à Niveau

Automatisation du pont FLEISCHMANN 6152 (HO) avec un ESP32 (1)

Identifier et localiser vos trains avec le RFID/NFC et un bus CAN.

Etude d’un passage à niveau multivoies

La rétro-signalisation sur Arduino

Décodeur pour aiguillage à solénoïdes sur Arduino

Un décodeur DCC pour les signaux à deux ou trois feux sur Arduino NANO/UNO

Etude d’un passage à niveau universel

Réalisation pratique d’un système de mesure de vitesse à l’échelle N

Une Passerelle entre le bus S88 et le bus CAN pour la rétro signalisation

Un décodeur DCC pour 16 feux tricolores

Block Automatique Lumineux avec la carte shield "Arduino 4 relays"

Réalisation d’un affichage de gare ARRIVEE DEPART

Ménage à trois (Ordinateur, Arduino, réseau)

Réalisation d’un va-et-vient automatique et réaliste

Souris et centrale sans fil

Communications entre JMRI et Arduino

Annonces en gare avec la RFID

Une croix de pharmacie animée avec Arduino UNO

Réalisation d’un wagon de mesure (distance et vitesse)

Passage à niveau géré par Arduino (1)

Passage à niveau géré par Arduino (2)

Passage à niveau géré par Arduino (3)

Passage à niveau géré par Arduino (4)

Passage à niveau géré par Arduino (5)

Une manette simple et autonome pour LaBox

Éclairer le réseau (1)

Éclairer le réseau (2)

Block Automatique Lumineux à 8 cantons analogiques

Un décodeur DCC pour les plaques tournantes Fleischmann et Roco

Éclairer le réseau (3)

Éclairer le réseau (4)

Éclairer le réseau (5)

JMRI pour Ma première centrale DCC

Rocrail pour Ma première centrale DCC

CDM-Rail pour Ma première centrale DCC (1)

CDM-Rail pour Ma première centrale DCC (2)

Banc de test pour les décodeurs DCC

Ma première manette pour les aiguillages DCC

Mon premier décodeur pour les aiguillages DCC

Boitier 3D pour la station DCC minimale

Va-et-vient pour deux trains

Un programme pour régler facilement les servos moteurs avec un ESP32

Affichage publicitaire avec Arduino (1)

Affichage publicitaire avec Arduino (2)

TCO Web interactif avec des ESP32 et des ESP8266 (1)

TCO Web interactif avec des ESP32 et des ESP8266 (2)

TCO Web interactif avec des ESP32 et des ESP8266 (3)

TCO Web interactif avec des ESP32 et des ESP8266 (4)

TCO Web interactif avec des ESP32 et des ESP8266 (5)

Les derniers articles

LaBox, Une Centrale DCC polyvalente et abordable (3)


Thierry

LaBox, Une Centrale DCC polyvalente et abordable (1)


Thierry

LaBox, Une Centrale DCC polyvalente et abordable (2)


Dominique, msport, Thierry

Un programme pour régler facilement les servos moteurs avec un ESP32


bobyAndCo

TCO Web interactif avec des ESP32 et des ESP8266 (5)


utpeca

TCO Web interactif avec des ESP32 et des ESP8266 (4)


utpeca

TCO Web interactif avec des ESP32 et des ESP8266 (3)


utpeca

TCO Web interactif avec des ESP32 et des ESP8266 (2)


utpeca

TCO Web interactif avec des ESP32 et des ESP8266 (1)


utpeca

Affichage publicitaire avec Arduino (2)


catplus, Christian

Les articles les plus lus

Réalisation de centrales DCC avec le logiciel libre DCC++ (3)

La PWM : Qu’est-ce que c’est ? (1)

Mon premier décodeur pour les aiguillages DCC

La rétro-signalisation sur Arduino

Comment piloter trains et accessoires en DCC avec un Arduino (1)

Réalisation de centrales DCC avec le logiciel libre DCC++ (1)

Chenillard de DEL

Comment piloter trains et accessoires en DCC avec un Arduino (2)

LaBox, Une Centrale DCC polyvalente et abordable (2)

Décodeur pour aiguillage à solénoïdes sur Arduino