2 - Commander une LED avec un variateur PWM”

De Wiki L.A.B
Révision de 8 novembre 2017 à 18:39 par BERNIER François (discussion | contributions) (Page créée avec « =='''Commander une LED avec un variateur PWM'''== Si on connecte une LED à des broches digitales comme vu dans le programme "blinky", on a seulement deux possibilités :... »)

(diff) ← Version précédente | Voir la version courante (diff) | Version suivante → (diff)
Aller à : navigation, rechercher

Commander une LED avec un variateur PWM

Si on connecte une LED à des broches digitales comme vu dans le programme "blinky", on a seulement deux possibilités : "on" avec la pleine luminosité et "off" éteint.
En utilisant le PWM (en anglais "pulse wide modulation"), on peux faire varier la luminosité de la LED.

Explication du PWM

Si on allume la LED, il y a une tension de 3.3 volt sur la broche, pour éteindre, on applique 0 volt:

PWM OnOff.png

Si on change rapidement (par exemple 100 fois par seconde) entre "on" et "off", l’œil humain ne distingue plus ce changement et on a l’impression, que la LED brille avec une luminosité moindre:

PWM OnOff100.png

A partir d’une certaine fréquence (25 fois par seconde), celle ci n’est plus importante car elle n'est plus perceptible à l’œil.

PWM OnOff25.png

Une periode "T" est défini par le temps entre deux allumage "on" (front montant du signal).
Maintenant, on peut diminuer ou augmenter le temps "t1" de l’état "on" par rapport à l’état "off". Par exemple dans le dessin, "t1" est à un quart de "T".

PWM Tt.png

Ce rapport t1/T est appelé le rapport cyclique ("duty cycle").

  • S’il est à 0 ( t1 = 0 ), la LED est "off" en continue.
  • S’il est à 1 ( t1 = T ), la LED est "on" en continue.
  • Si on modifie le rapport de "t1 beaucoup plus petit que T" (la LED brille très peu) à "t1 presque égale à T" (la LED brille beaucoup), on peux varier la luminosité de la LED.

Support du PWM par les STM32

Sur STM32, le PWM est supporté par l’utilisation du timer et des drivers HAL (source code "Hardware Abstraction Layer" distribué par ST).
Il faut savoir que les STM32 contiennent plusieurs types de timer avec des fonctionnalités différentes. Une description des timers se trouve dans les fichiers (en anglais) de STMicroelectronics:



On va utiliser l’outil STM32CubeMx pour générer le code source de base.

  • Première étape: Créer un nouveau projet en sélectionnant la carte sur laquelle on va travailler.
  • Dans l’onglet "Pinout" de la fenêtre principale, on sélectionne un timer (par exemple "TIM2"), qui propose plusieurs "Channel" avec la fonction "PWM Generation".



PWM Pinout.png

On peut voir sur l’image de la puce que la broche PA5 est utiliser pour le canal 1 du timer 2: "TIM2_CH1".
Pour calculer des valeurs "t1" et "T", il faut configurer le timer dans l’onglet "Configuration" en cliquant sur le bouton "TIM2" dans la rubrique "Control".

PWM Config.png

Dans l’onglet « Parameter Settings » de la boite de dialogue, il faut configurer le timer.
Pour cela, il faut savoir que le timer est sequencé par l’horloge du CPU. Dans le cas de la carte sélectionné, cette fréquence est de 80 MHz.
Si on configure le "Prescaler" (voir image) du timer à 80, le timer va déclencher l’incrémentation du compteur avec une fréquence de 1 MHz (80 MHz / 80). Il faut configurer une deuxième valeur "Counter Periode" à 100.
Ainsi, chaque micro seconde, le timer va incrémenter (en commençant à 0 jusqu’à 100). Ce temps (100 micro secondes) corresponds au "T". Maintenant on peut générer le code source.

Pour le contrôle du timer, il faut trois fonctions:

  • Démarrer le timer: HAL_TIM_PWM_Start( &htim2, TIM_CHANNEL_1 );
  • Arrêter le timer: HAL_TIM_PWM_Stop( &htim2, TIM_CHANNEL_1 );
  • Modifier la valeur de "t1": __HAL_TIM_SET_COMPARE( &htim2, TIM_CHANNEL_1, Value );

Allumage d’une LED

La valeur de la variable "Value" peut être réglée entre 0 (LED éteint) et 100 (LED allumé avec 100 % puissance). Avec de simples boucles, on peut réaliser un "blinkly en continue":

 HAL_TIM_PWM_Start( &htim2, TIM_CHANNEL_1 );
 /* Infinite loop */
 while (1)
 {
  for ( int i = 0; i < 100; i ++ )
  {
    __HAL_TIM_SET_COMPARE( &htim2, TIM_CHANNEL_1, i );
    HAL_Delay( 10 );
  }
  for ( int i = 100; i > 0; i -- )
  {
    __HAL_TIM_SET_COMPARE( &htim2, TIM_CHANNEL_1, i );
    HAL_Delay( 10 );
  }
 }