Sylvain Mahé Le site Web Retour à l'accueil Principes Partager mes idées et mes projets librement et gratuitement. Thématiques Mécatronique du système embarqué, artisanat pluridisciplinaire, bricolage commun, esthétique logicielle et matérielle, minimalisme fonctionnel, conceptualisation alternative, rédaction technique et littéraire, partage pédagogique documenté. Contact ✆ Téléphone : 06.45.49.96.98
✉ E-mail : contact@sylvainmahe.site
✎ Site Web : sylvainmahe.site
Écriture de la page : Sylvain Mahé
Les servo-moteurs avec la classe PwmWrite Comme pour les autres classes de MODULE, PwmWrite n'est pas dédiée à une application en particulier (bien que l'exemple qui suit concerne les servo-moteurs). J'utilise notamment la génération de signaux PWM pour faire varier la luminosité des diodes électroluminescentes (voir l'exemple plus bas : "Faire varier la luminosité d'une del"). Avec la classe PwmWrite, ce sont tous les ports GPIO de l'automate programmable qui peuvent servir à la génération de signaux PWM (voir plus loin : "Le choix du PWM matériel ou logiciel"). L'exemple suivant permet de faire fonctionner un servo-moteur sur le port GPIO numéro 1 de l'automate programmable à une fréquence PWM de 50Hz. Dans la boucle, le palonnier du servo-moteur se positionnera à 1000μs, puis 3 secondes plus tard, se positionnera à 2000μs, pour ensuite attendre de nouveau 3 secondes à cette position, après quoi le programme bouclera. Exemple d'utilisation de la classe PwmWrite : #include <PwmWrite.h> #include <Timer.h> int main() { PwmWrite myServo = PwmWrite (1); PwmWrite::start (50); while (true) { myServo.us (1000); Timer::pause (3000); //pause de 3 secondes myServo.us (2000); Timer::pause (3000); //pause de 3 secondes } return 0; } Un objet myServo de type PwmWrite est déclaré, en paramètre est indiqué d'utiliser le port GPIO numéro 1 de l'automate programmable en sortie. Puis la fonction statique start est appelée prenant en paramètre la fréquence du PWM, ce qui démarre la génération PWM à la fréquence de 50Hz dans cet exemple. La fréquence PWM indiquée en paramètre avec la fonction statique start sera toujours appliquée à l'ensemble des ports choisis. Ensuite dans la boucle, dans un premier temps l'objet myServo appelle la fonction us qui prend en paramètre 1000, la largeur d'impulsion en microsecondes, ce qui vient positionner le palonnier du servo-moteur à cet endroit. Puis 3000ms (3 secondes) plus tard, positionne le servo-moteur à 2000μs. Il vous est possible d'appeler la fonction us avant ou après avoir démarré et choisi la fréquence du PWM avec la fonction statique start. Ceci n'a en effet aucune incidence sur le fonctionnement puisque la fonction us retient les valeurs indiquées en paramètre lorsque le PWM n'est pas encore démarré. La fonction us attend en paramètre un nombre décimal (float), ou entier si vous le souhaitez. Libre à vous de déterminer dans vos montages électroniques si vous avez besoin de générer des signaux PWM avec une largeur d'impulsion précise à la fraction de microseconde (c'est le cas de certains servo-moteurs ou contrôleurs de moteurs sans charbons). À noter que la largeur d'impulsion des objets créés est à une valeur par défaut de 0 microseconde si aucun changement de rapport cyclique n'a encore été effectué avec la fonction us. Ce programme est simple, mais il permet en quelques lignes de comprendre facilement les fonctions de la classe PwmWrite. Si besoin est, une fonction statique stop existe et permet d'arrêter la génération de signaux PWM sur tous les ports GPIO utilisés par la classe PwmWrite, un nouvel appel à la fonction statique start permet de redémarrer la génération la ou elle s'était arrêtée (elle garde en mémoire les dernières valeurs de largeur d'impulsion indiquées en paramètre). Faire varier la luminosité d'une del : L'exemple suivant va vous montrer comment modifier la luminosité d'une del grâce au changement de la largeur d'impulsion d'un signal PWM. En effet, notre rétine étant sensible à la persistance rétinienne, une simple variation du temps d'exposition à la lumière à une fréquence supérieure au rafraîchissement de la rétine, sera perçue par le cerveau comme une variation de la luminosité. Exemple de variation de la luminosité d'une del avec un potentiomètre : #include <PwmWrite.h> #include <AnalogRead.h> #include <Math.h> int main() { PwmWrite myLed = PwmWrite (13); AnalogRead myPotentiometer = AnalogRead (25); PwmWrite::start (1000); while (true) { myPotentiometer.read(); myLed.us (Math::curve (0, myPotentiometer.value, 1023, 0, 1000, 0)); } return 0; } Dans l'exemple, la fréquence du PWM est de 1000Hz (bien plus rapide que le rafraîchissement de la rétine), ce qui donne un rapport cyclique (largeur d'impulsion) pouvant varier de 0μs (0%) à 1000μs (100%). La fonction statique curve de la classe Math permet d'interpoler la valeur 10 bits (0 à 1023) du potentiomètre en valeurs de 0μs à 1000μs. À une valeur de 500μs (rapport cyclique de 50%), la del éclairerait à une luminosité d'environ 50%. Le choix du PWM matériel ou logiciel : Tous les ports GPIO de l'automate programmable peuvent générer des signaux PWM sur une résolution théorique de 16 bits avec la classe PwmWrite (ce qui offre une grande souplesse d'utilisation), mais la façon dont ils sont générés (purement matérielle, ou partiellement logicielle) ainsi que les limites techniques (fréquence et résolution) seront différentes suivant les ports que vous utiliserez. Ports des automates programmables concernés par la génération purement matérielle du PWM : Automate programmable MODULABLE 20 :
- Port GPIO 10 (PB1) = OC1A (output compare 1A)
- Port GPIO 11 (PB2) = OC1B (output compare 1B)

Automate programmable MODULABLE 32 :
- Port GPIO 13 (PD4) = OC1B (output compare 1B)
- Port GPIO 14 (PD5) = OC1A (output compare 1A)

Spécificité pour le microcontrôleur ATmega1284P :
- Port GPIO 7 (PB6) = OC3A (output compare 3A)
- Port GPIO 8 (PB7) = OC3B (output compare 3B)
- Port GPIO 13 (PD4) = OC1B (output compare 1B)
- Port GPIO 14 (PD5) = OC1A (output compare 1A)
La sélection d'un autre port GPIO que ceux indiqués ci-dessus passera la génération PWM en mode logiciel. En mode logiciel, la génération de signaux PWM s'effectuant de manière séquentielle (ports après ports, dans l'ordre de déclaration des objets), la fréquence PWM choisie ainsi que le nombre de ports utilisés permettent de déterminer la largeur d'impulsion maximale possible avec une telle configuration. Exemple de calcul du rapport cyclique maximum suivant la fréquence et le nombre de signaux PWM à générer en mode logiciel : Fréquence du PWM = 1000Hz
Nombre de signaux PWM à générer (ports utilisés) = 4 ports

Limites maximales :
Rapport cyclique = 1000000μs / (1000Hz * 4 ports) = 250μs (max)
Dans cette configuration, la largeur d'impulsion maximale qui pourra être générée sera de 250 microsecondes (rapport cyclique de 25%). Si vous indiquez un rapport cyclique supérieur à 250μs, ceci n'aura aucun impact sur le bon fonctionnement du PWM (celui-ci sera bloqué à 250μs par port utilisé dans tous les cas). De façon matérielle, la classe PwmWrite permet de générer des signaux PWM à des fréquences très élevées (supérieures à 1MHz), mais vous devez prendre conscience que le nombre d'états possibles (soit la résolution) à de telles fréquences sera plus faible qu'à des fréquences inférieures. Ceci est dû aux contraintes même du matériel, en particulier du compteur 16 bits, de la fréquence d'horloge de 16MHz, et des diviseurs d'horloge du microcontrôleur. Exemple de calcul du rapport cyclique maximum suivant la fréquence PWM choisie en mode matériel : Fréquence du PWM = 1000Hz

Limites maximales :
Rapport cyclique = 1000000μs / 1000Hz = 1000μs (max)
En mode matériel, la largeur d'impulsion maximale n'est pas dépendante du nombre de ports utilisés. À noter que la classe PwmWrite calculera le diviseur d'horloge du microcontrôleur le plus adapté en rapport avec la fréquence PWM choisie avec la fonction statique start, ceci afin de garantir une résolution de la largeur d'impulsion la plus élevée possible (soit un nombre de pas ou d'états disponibles le plus important dans toutes les situations). Cette résolution de 16 bits théorique maximum est bien entendu égale et valable pour les deux méthodes de génération du PWM (matérielle et logicielle). Seul des limites de fréquences maximales ou de largeur d'impulsion maximale possible distinguent l'une ou l'autre méthode. Rappelez-vous que c'est la classe PwmWrite qui par vos choix en matière de ports utilisés, sélectionne automatiquement pour vous le mode de génération PWM matériel ou logiciel. Dans tous les cas, si un problème ou une limitation vient à se poser à vous (fréquence maximale, largeur d'impulsion maximale possible, ou résolution de la largeur d'impulsion), il convient alors avant toute chose de comprendre et de s'interroger sur la logique matérielle du composant (largeur des registres, cycles d'horloge, profondeur combinatoire, etc...), et de relire ce que j'ai indiqué plus haut afin d'en maîtriser les contraintes et les limites techniques (ceci ne doit en aucun cas être un frein à vos projets). Ports des automates programmables concernés par la génération du PWM : Automate programmable MODULABLE 20 :
- Port GPIO 1 (PD0)
- Port GPIO 2 (PD1)
- Port GPIO 3 (PD2)
- Port GPIO 4 (PD3)
- Port GPIO 5 (PD4)
- Port GPIO 6 (PD5)
- Port GPIO 7 (PD6)
- Port GPIO 8 (PD7)
- Port GPIO 9 (PB0)
- Port GPIO 10 (PB1)
- Port GPIO 11 (PB2)
- Port GPIO 12 (PB3)
- Port GPIO 13 (PB4)
- Port GPIO 14 (PB5)
- Port GPIO 15 (PC0)
- Port GPIO 16 (PC1)
- Port GPIO 17 (PC2)
- Port GPIO 18 (PC3)
- Port GPIO 19 (PC4)
- Port GPIO 20 (PC5)

Automate programmable MODULABLE 32 :
- Port GPIO 1 (PB0)
- Port GPIO 2 (PB1)
- Port GPIO 3 (PB2)
- Port GPIO 4 (PB3)
- Port GPIO 5 (PB4)
- Port GPIO 6 (PB5)
- Port GPIO 7 (PB6)
- Port GPIO 8 (PB7)
- Port GPIO 9 (PD0)
- Port GPIO 10 (PD1)
- Port GPIO 11 (PD2)
- Port GPIO 12 (PD3)
- Port GPIO 13 (PD4)
- Port GPIO 14 (PD5)
- Port GPIO 15 (PD6)
- Port GPIO 16 (PD7)
- Port GPIO 17 (PC0)
- Port GPIO 18 (PC1)
- Port GPIO 19 (PC2)
- Port GPIO 20 (PC3)
- Port GPIO 21 (PC4)
- Port GPIO 22 (PC5)
- Port GPIO 23 (PC6)
- Port GPIO 24 (PC7)
- Port GPIO 25 (PA7)
- Port GPIO 26 (PA6)
- Port GPIO 27 (PA5)
- Port GPIO 28 (PA4)
- Port GPIO 29 (PA3)
- Port GPIO 30 (PA2)
- Port GPIO 31 (PA1)
- Port GPIO 32 (PA0)
Références : Récapitulatif des fonctions de cette classe : PwmWrite (const unsigned char PIN); static void start (const float FREQUENCY); void us (const float US); static void stop();