Qu'est-ce que le PWM?
La modulation par largeur d'impulsion (ou pulse width modulation, d'où l'acronyme PWM) est une succession de signaux logiques 0 ou 1 (donc 0 V et 5 V dans le cas de l'Arduino). Lorsque le rapport cyclique (duty cycle) est de 0%, le signal est toujours à 0 V. Lorsque le rapport cyclique est de 100%, le signal est toujours à 5 V. Si le rapport cyclique est de 25%, le signal est haut pendant 25% du temps, et bas pendant les 75% restants...
Et à quoi ça sert, le PWM?
Au moyen d'un filtre passs-bas, un signal PWM peut être transformé en une tension analogique continue dont la valeur se situe entre 0 et 5 V. On peut aussi utiliser un signal PWM pour contrôler la vitesse d'un moteur. Dans cet article, nous utiliserons le signal PWM pour contrôler la luminosité d'une LED (plus le rapport cyclique sera élevé, plus la lumière émise par la LED sera intense).
Le circuit
Le circuit sera évidemment très simple: une LED et une résistance de protection (220 ohms, par exemple), reliée à une des pins PWM de l'Arduino (3, 5, 6, 9, 10, 11 sur l'Arduino Uno). Les scripts présentés ci-dessous supposent que la LED est branchée à la pin 11.
Bibliothèque PyFirmata, etc.
Nous supposons que le sketch "StandardFirmata" a été téléversé dans votre Arduino, et que la bibliothèque pyFirmata a déjà été installée sur l'ordinateur hôte (si ce n'est pas le cas, référez-vous à l'article précédent pour plus de détails sur la façon de procéder).
Rédaction d'un script en python
L'utilisation du PWM avec pyFirmata nécessite deux étapes:
1) Le réglage d'une pin de l'Arduino en mode PWM, au début du programme, au moyen de la méthode "get_pin":
LEDpin = board.get_pin('d:11:p')
À prime abord, la syntaxe peut sembler un peu nébuleuse: nous créons un objet de type PIN nommé "LEDpin". Les arguments de get_pin indiquent que la pin numérique numéro 11 est en mode PWM (le "d" est pour "digital" et le "p" est pour "PWM").
2) Le réglage du rapport cyclique du signal PWM, chaque fois qu'on désire le modifier:
board.digital[LEDpin.pin_number].write(rapport_cyclique)
Le rapport cyclique doit être un nombre se situant entre 0 (rapport cyclique de 0%) et 1 (rapport cyclique de 100%). Par exemple, pour émettre sur la pin numéro 5 un signal PWM dont le rapport cyclique sera de 30%, on pourrait écrire:
board.digital[5].write(0.3)
Premier exemple de script (interface en mode texte)
Dans ce premier exemple, l'utilisateur doit écrire un nombre (entre 0 et 100) pour régler le rapport cyclique (et, par conséquent, la luminosité de la LED).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: latin-1 -*- | |
''' | |
Contrôle de la luminosité d'une LED l'Arduino | |
à partir d'un PC au moyen du protocole Firmata | |
Version simple en mode texte | |
Pour plus de détails: | |
http://electroniqueamateur.blogspot.com/2015/06/firmata-et-arduino-3-pwm-en-python.html | |
''' | |
import pyfirmata | |
port = 'COM3' #windows | |
#port = '/dev/ttyACM0' #linux | |
board = pyfirmata.Arduino(port) | |
LEDpin = board.get_pin('d:11:p') ## d = digital, 11 = numéro de la pin, p = PWM | |
print "-------------- CONTROLE DE LEDS ----------------" | |
print "En tout temps, vous pouvez quitter le programme en répondant par 'q'." | |
while True: | |
print "Luminosité désirée pour la LED:" | |
luminosite = raw_input("De 0 à 100 (ou q): ") | |
if (luminosite == 'q'): | |
board.exit(); | |
print "Au revoir!" | |
break; | |
board.digital[LEDpin.pin_number].write(float(luminosite)/100.0) |
Deuxième exemple de script (interface graphique)
Ici, nous utilisons Tkinter pour faire apparaître un curseur qui contrôle le rapport cyclique.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
""" | |
Contrôle de la luminosité d'une LED l'Arduino | |
à partir d'un PC au moyen du protocole Firmata | |
Interface graphique (Tkinter) | |
Pour plus d'infos: | |
http://electroniqueamateur.blogspot.com/2015/06/firmata-et-arduino-3-pwm-en-python.html | |
""" | |
from Tkinter import * | |
import pyfirmata | |
pin1 = 2 | |
pin2 = 3 | |
pin3 = 4 | |
port = 'COM3' #windows | |
#port = '/dev/ttyACM0' #linux | |
board = pyfirmata.Arduino(port) | |
LEDpin = board.get_pin('d:11:p') #on règle la pin 11 en mode PWM | |
# S'exécute lors d'un changement du slider: | |
def reglageLED(valeur): | |
board.digital[LEDpin.pin_number].write(float(valeur)/100.0) | |
class Example(Frame): | |
def __init__(self, parent): | |
Frame.__init__(self, parent) | |
self.parent = parent | |
self.initUI() | |
def initUI(self): | |
self.parent.title("LED") #titre de la fenêtre | |
self.pack(fill=BOTH, expand=1) | |
# Label (le texte dans la fenêtre): | |
w = Label(self, wraplength = 200, pady = 10, text="Veuillez glisser le curseur pour contrôler la luminosité de la LED") | |
w.pack() | |
# Curseur: | |
self.var1 = IntVar() | |
w2 = Scale(self, from_=0, to=100, orient=HORIZONTAL, command = reglageLED) | |
w2.pack() | |
def main(): | |
root = Tk() | |
root.geometry("250x200+300+300") # dimension et position initiale de la fenêtre | |
app = Example(root) | |
root.mainloop() | |
if __name__ == '__main__': | |
main() |
Yves Pelletier (Twitter, Facebook)