Accueil Cours GPIO, PWM et NeoPixel
💡 Actionneurs Débutant

GPIO, PWM et NeoPixel

Les sorties numériques de l'ESP32 : allumer une LED, lire un bouton, contrôler la luminosité avec PWM et créer des effets de couleur avec les LED RGB WS2812.

GPIO numérique — sorties

Le GPIO (General Purpose Input/Output) est la façon la plus simple d'interagir avec le monde physique. Un pin peut être mis à 1 (3.3 V) ou 0 (0 V).

GPIO numérique — entrées (boutons)

Pour lire un bouton, on configure le pin en entrée. La résistance pull-up interne évite le pin "flottant" quand le bouton est relâché.

⚠️ Logique inversée

Avec PULL_UP, la logique est inversée : 0 = appuyé, 1 = relâché. Le bouton connecte le pin à GND quand il est pressé.

PWM — Pulse Width Modulation

Le PWM simule une sortie analogique en faisant varier la largeur des impulsions. Utilisé pour la luminosité des LEDs, les servomoteurs, les sons.

ParamètreValeurEffet
freq100 – 40 000 HzFréquence du signal
duty0 – 1023Rapport cyclique (0 = éteint, 1023 = plein)

Correction de luminosité (courbe gamma)

L'œil humain ne perçoit pas la luminosité de façon linéaire. Une correction quadratique donne un rendu plus naturel.

NeoPixel — LED RGB WS2812

Les NeoPixel (WS2812) sont des LED RGB adressables en série. Un seul fil de données contrôle autant de LED que tu veux.

Résumé des pins ESP32

PinUsage typiqueNotes
2LED intégrée / sortieLED bleue sur la plupart des boards
0Bouton BOOT / entréePULL_UP interne
26NeoPixelDonnées WS2812
5Buzzer / sonPWM à 50-4000 Hz
18, 19, 23LEDs supplémentairesCarte ENIM

Exemples commentés

Chaque exemple est précédé de son contexte. Le code est affiché directement — bouton copier + lien GitHub disponibles.

💡 GPIO numérique

LEDs, boutons, minuteries — les bases des entrées/sorties numériques.

1 La sortie numérique — allumer et faire clignoter une LED

Une broche GPIO (General Purpose Input/Output) peut être configurée en sortie ou en entrée. En MicroPython, la classe Pin du module machine gère tout cela :

  • led = Pin(2, Pin.OUT) — crée l'objet LED sur la broche 2 en sortie
  • led.value(1) — met la broche à 3,3V (LED allumée)
  • led.value(0) — met la broche à 0V (LED éteinte)
  • led.value(not led.value()) — bascule l'état (inverse)

Pour clignoter à 1 Hz (période de 1 s), on allume 0,5 s puis on éteint 0,5 s avec sleep(0.5). La boucle while True fait tourner ça en continu. La boucle for a in range(6) fait clignoter exactement 3 fois (6 basculements) puis s'arrête.

La mesure du temps de clignotement (led-temps.py) révèle que l'ESP32 peut basculer la LED environ 50 000 fois par seconde, soit ~20 µs par cycle.

led.py — LED qui clignote à 1 Hz .python
cours-exemples/gpio/led.py
22 lignes GitHub
from machine import Pin
import time

led = Pin(2, Pin.OUT)

while True:
    led.value(1)          # on allume la LED    
    time.sleep(0.5)       # delai de 0.5 s
    led.value(0)          # on eteint la LED    
    time.sleep(0.5)       # delai de 0.5 s

#while True:
#    if led.value() == 1 :         # si la LED est allumee...
#        led.value(0)              # on l'eteint
#    else :                        # sinon (elle est eteinte)...
#        led.value(1)              # on l'allume       
#    time.sleep(0.5)               # delai de 0.5 s entre 2 boucles (1 Hz)

#while True:
#    led.value(not led.value()) ;  # inversion de l'etat de la LED
#    time.sleep(0.5)               # delai de 0.5 s entre 2 boucles (1 Hz)
   
led-3-fois.py — Clignote 3 fois puis s'arrête .python
cours-exemples/gpio/led-3-fois.py
11 lignes GitHub
from machine import Pin
import time

led = Pin(2, Pin.OUT)       

for a in range (6) :
  led.value(not led.value())
  time.sleep(0.5)


led-temps.py — Mesure le temps de 10 000 clignotements .python
cours-exemples/gpio/led-temps.py
15 lignes GitHub
from machine import Pin
import time 

led = Pin(2, Pin.OUT)       

start = time.ticks_ms()         # memorise la valeur du ticks au lancement

for iteration in range (10000) :
    led.value(1) ; led.value(0)

delta = time.ticks_ms() - start # calcule l'ecart : apres - avant

print("Temps total pour 10 000 cycles :", delta, "ms")
print("Temps pour 1 cycle ON/OFF      :" , delta/10, "microsecondes")
print("Frequence de basculement       : {0:2.1f} kHz".format(10000/delta))

2 L'entrée numérique — lire un bouton poussoir

L'entrée numérique lit un état logique : 0 ou 1. Le bouton poussoir, quand il est appuyé, connecte la broche à 3,3V → la valeur lue passe à 1. Relâché, la broche est à 0V → valeur 0.

  • bp = Pin(25, Pin.IN) — broche 25 configurée en entrée
  • bp.value() — retourne 0 (relâché) ou 1 (appuyé)
  • led.value(bp.value()) — la LED suit directement l'état du bouton

Attention : dans led-stop.py, la lecture du bouton a lieu toutes les 0,5 s (pendant le sleep). Si l'appui et le relâchement se produisent tous les deux pendant ce délai, l'appui est raté. Il faut appuyer assez longtemps pour être sûr d'être lu.

led-bouton.py — LED contrôlée par un bouton .python
cours-exemples/gpio/led-bouton.py
17 lignes GitHub
from machine import Pin
from time import sleep

led = Pin(2, Pin.OUT)
bouton = Pin(25, Pin.IN)
    
while True :
    if bouton.value() :
        led.value(1)
    else :
        led.value(0)
    sleep(0.1)

#while True :
#    led.value(bouton.value())
#    sleep(0.1)
led-stop.py — Bouton stop/reprendre .python
cours-exemples/gpio/led-stop.py
9 lignes GitHub
from machine import Pin
import time

led = Pin(2, Pin.OUT)
bp = Pin(25, Pin.IN)

while not bp.value() :            # continue tant que bp.value() == 0
    led.value(not led.value())
    time.sleep(0.5)

3 Le temporisateur d'éclairage

Un temporisateur d'éclairage allume la LED lors de l'appui sur un bouton, puis l'éteint automatiquement après 2 secondes. C'est le cas typique d'une minuterie de couloir.

Le principe du compteur décrémenté :

  • À chaque appui : compt = 20
  • À chaque itération de 0,1 s : compt = compt - 1
  • La LED est allumée si compt > 0, soit pendant 20 × 0,1 s = 2 s

tempo-eclairage.py est la version de base avec sleep(0.1) bloquant. tempo-eclairage-optimise.py est la version non-bloquante : la boucle tourne sans sleep, elle utilise ticks_ms() pour mesurer les 100 ms écoulés. Résultat : le programme peut faire autre chose en même temps.

tempo-eclairage.py — LED s'éteint après 2 secondes .python
cours-exemples/gpio/tempo-eclairage.py
21 lignes GitHub
from machine import Pin
import time

led = Pin(2, Pin.OUT)
bp = Pin(25, Pin.IN)

compt = 0
while True:
    if bp.value():
        compt = 20
        print("Light ON")
    print(compt)
    if compt > 0:
        led.value(1)
    else:
        led.value(0)
    time.sleep(0.1)
    compt = compt - 1
    if compt == 0:
        print("Light OFF")
tempo-eclairage-optimise.py — Version non-bloquante avec ticks_ms() .python
cours-exemples/gpio/tempo-eclairage-optimise.py
12 lignes GitHub
from machine import Pin
from time import sleep

led = Pin(2, Pin.OUT)
bp = Pin(25, Pin.IN)

compt = 0 
while True :   
    if bp.value() : compt = 20     
    led.value(compt > 0)   # si compt > 0, cela fait led.value(True) 
    sleep(0.1)
    compt -= (compt > 0)   # raccourci pour : compt = compt - (compt > 0)

🔆 PWM

Variation de luminosité, servomoteurs et signaux analogiques simulés.

1 Le signal PWM et le rapport cyclique

Le PWM (Pulse Width Modulation — modulation de largeur d'impulsions) simule une tension variable en faisant osciller très rapidement une sortie numérique entre 0 V et 3,3 V. La fréquence est suffisamment élevée (500 Hz typiquement) pour que l'œil ne voie pas le clignotement, mais perçoive une luminosité intermédiaire.

Le rapport cyclique (duty) fixe la proportion de temps à l'état haut dans chaque période :

  • duty = 0 → toujours à 0V → LED éteinte
  • duty = 512 → 50% du temps à 3,3V → luminosité moyenne
  • duty = 1023 → toujours à 3,3V → LED à plein
from machine import Pin, PWM
led = PWM(Pin(2, Pin.OUT), 500)  # fréquence 500 Hz
for i in range(0, 1024, 10):    # de 0 à 1023
    led.duty(i)
    sleep(0.01)
pwm.py — Variation de luminosité linéaire .python
cours-exemples/pwm/pwm.py
12 lignes GitHub
from time import sleep_ms           
from machine import Pin, PWM

led = PWM(Pin(2, Pin.OUT), 500)    # Initialise la freq : 500 Hz

for boucle in range(3) :   
    for i in range(0, 1023, 10) :  # de 0 a 1023 par pas de 10
        led.duty(i)
        sleep_ms(10)      
led.deinit()                       # liberation des ressources du PWM

    

2 La correction gamma — perception non-linéaire

Si vous avez testé pwm.py, vous avez observé que la LED passe de sombre à brillant très vite au début, puis évolue peu à la fin. Ce n'est pas un bug : c'est la physiologie humaine.

Notre œil perçoit la luminosité de façon logarithmique, non linéaire. La différence entre 0 et 100 semble énorme, alors que la différence entre 900 et 1000 est quasiment imperceptible.

La correction gamma applique une courbe pour compenser :

def correction(i, coef):
    return int((i / 1023) ** coef * 1023)
# coef = 2 : parabole douce
# coef = 3.5 : rendu encore plus naturel

Avec cette correction, la variation perçue est régulière et agréable sur toute la plage.

pwm-correction.py — Correction gamma perceptuelle .python
cours-exemples/pwm/pwm-correction.py
10 lignes GitHub
from time import sleep_ms           
from machine import Pin, PWM

led = PWM(Pin(2, Pin.OUT), 500)    # Initialise la freq a 500 Hz  

for boucle in range(3) :   
    for i in range(0, 1023, 10) :
        led.duty(int((i/ 1023)** 2 * 1023))
        sleep_ms(10)      
led.deinit()    

3 Application — fade-in sur appui bouton

On combine PWM et bouton pour créer un allumage progressif :

  1. On attend l'appui puis le relâchement du bouton
  2. La LED monte progressivement de 0 à 1023 (fade-in)
  3. On attend un second appui + relâchement
  4. La LED descend de 1023 à 0 (fade-out)

C'est une solution bloquante : les boucles while not bp.value(): pass et while bp.value(): pass figent le reste du programme pendant l'attente. Ce sera résolu plus loin avec la détection de fronts.

pwm-allume-bp.py — Fade-in progressif sur appui bouton .python
cours-exemples/pwm/pwm-allume-bp.py
26 lignes GitHub
from time import sleep_ms
from machine import Pin, PWM

led = PWM(Pin(2, Pin.OUT), 500)  # initialise la frequence a 500 Hz
bp = Pin(25, Pin.IN)

def correction(i, coef):
    return int((i / 1023) ** coef * 1023)

while True:
    while not bp.value(): pass  # attente de l'appui
    while bp.value(): pass      # attente du relachement

    for i in range(0, 1023, 10):  # allumage de la LED
        led.duty(correction(i, 3.5))  # utilisation fonction correction
        sleep_ms(10)

    while not bp.value():
        pass  # attente de l'appui
    while bp.value():
        pass  # attente du relachement

    for i in range(0, 1023, 10):  # extinction de la LED
        led.duty(correction(1023 - i, 3.5))
        sleep_ms(10)

🌈 NeoPixel RGB

LED WS2812 adressables — couleurs, animations et effets.

1 Les LED WS2812 — principe et synthèse additive

Les LED WS2812 (aussi appelées NeoPixel) sont des LED RGB adressables : chaque LED contient trois LEDs (Rouge, Vert, Bleu) et une puce de contrôle. On peut les chaîner en série sur un seul fil de données (DIN → DOUT → …).

La couleur est obtenue par synthèse additive — en mélangeant les trois composantes de 0 à 255 :

  • (255, 0, 0) → rouge pur
  • (0, 255, 0) → vert pur
  • (0, 0, 255) → bleu pur
  • (255, 255, 0) → jaune (rouge + vert)
  • (255, 255, 255) → blanc
  • (0, 0, 0) → éteint
from neopixel import NeoPixel
np = NeoPixel(Pin(26), 8)  # 8 LEDs sur la broche 26
np[0] = (255, 0, 0)        # LED 0 en rouge
np[3] = (0, 100, 200)      # LED 3 en bleu-cyan
np.write()                 # IMPORTANT : envoie tout le buffer

Important : np.write() envoie toutes les couleurs d'un seul coup. Rien n'est visible avant cet appel.

neopixel.py — Couleur unique sur toutes les LEDs .python
cours-exemples/neopixel/neopixel.py
19 lignes GitHub
from machine import Pin, ADC
from neopixel import NeoPixel  # import de la classe NeoPixel du module

n = 8                          # nombre de pixels
p = 26                         # pin de commande du neopixel
np = NeoPixel(Pin(p), n)       # creation de l'instance np
          
np[0] = (10, 0, 0)            # rouge, 10/255 brightness, soit 4%
np[1] = (40, 0, 0)            # rouge, 40/255 brightness, soit 16%
np[2] = (0, 40, 0)            # vert, 40/255 brightness, soit 16%
np[3] = (0, 0, 40)            # bleu, 40/255 brightness, soit 16%
np[4] = (40, 40, 0)           # rouge + vert = jaune
np[5] = (0, 40, 40)           # vert + bleu = cyan
np[6] = (40, 0, 40)           # rouge + bleu = magenta (violet)
np[7] = (40, 40, 40)          # rouge + vert + bleu = blanc
np.write()   


2 Animations — défilement, comptage, aléatoire

Les animations NeoPixel reposent sur la mise à jour du buffer à chaque cycle de la boucle principale :

  • Défilement : à chaque cycle, on décale les couleurs d'un cran et on place une nouvelle couleur en tête
  • Comptage au bouton : chaque appui allume une LED de plus (de 0 à 8) — on utilise la détection de front montant
  • Aléatoire : random.randint(0, 7) choisit une LED au hasard à chaque cycle
neopixel-defilement.py — Défilement de gauche à droite .python
cours-exemples/neopixel/neopixel-defilement.py
18 lignes GitHub
from machine import Pin, ADC
from time import sleep
from neopixel import NeoPixel  # import de la classe NeoPixel du module

n = 8                          # nombre de pixels
p = 26                         # pin de commande du neopixel
delai = .125
np = NeoPixel(Pin(p), n)       # creation de l'instance np

for x in range(0, n):
    np[x] = (0, 0, 255)        # bleu, 100% brightness
    np.write()
    sleep(delai)

for x in range(0,n):
    np[x] = (0, 0, 0)          # eteint
    np.write()
    sleep(delai)
neopixel-x-allumes.py — Nombre de LEDs contrôlé par bouton .python
cours-exemples/neopixel/neopixel-x-allumes.py
16 lignes GitHub
from machine import Pin, ADC
from time import sleep
from neopixel import NeoPixel     

n = 8                              # nombre de pixels
p = 26                             # pin de commande du neopixel
np = NeoPixel(Pin(p), n)           # creation de l'instance np

x = int(input("Combien voulez vous de LED allumees ? : "))
        
for led in range(0, n):
    np[led] = (0, 0, 20*(led<x))  # = 255 si (led < x) ;  = 0 sinon
np.write()


neopixel-random.py — Activation aléatoire .python
cours-exemples/neopixel/neopixel-random.py
18 lignes GitHub
from machine import Pin, ADC
from time import sleep
from neopixel import NeoPixel
from random import randint

n = 8                              # nombre de pixels
p = 26                             # pin de commande du neopixel
np = NeoPixel(Pin(p), n)           # creation de l'instance np

x = randint(0,8)                   # tirage aleatoire entre 0 et 8
print(x)

for led in range(0, n):
    np[led] = (0, 0, 50*(led<x))   # = 50 si (led < x) ;  = 0 sinon
np.write()


3 Arc-en-ciel et distribution uniforme

L'arc-en-ciel répartit les teintes uniformément sur le cercle chromatique (0° à 360°). On convertit la teinte HSV en RGB puis on décale l'ensemble à chaque cycle pour créer le mouvement.

Le tirage aléatoire uniforme est plus subtil qu'il n'y paraît : si on tire simplement un nombre entre 0 et 7, certaines valeurs reviennent plus souvent que d'autres selon la distribution du générateur. L'exemple tirage-aleatoire.py illustre comment vérifier et garantir une distribution véritablement uniforme.

neopixel-rainbow.py — Arc-en-ciel défilant .python
cours-exemples/neopixel/neopixel-rainbow.py
32 lignes GitHub
from machine import Pin, ADC
from time import sleep_ms
from neopixel import NeoPixel

n = 8                              # nombre de pixels
p = 26                             # pin de commande du neopixel
np = NeoPixel(Pin(p), n)           # creation de l'instance np
bp = Pin(25, Pin.IN)

def wheel(pos):
    if pos < 0 or pos > 255:
        return (0, 0, 0)
    if pos < 85:
        return (255 - pos * 3, pos * 3, 0)
    if pos < 170:
        pos -= 85
        return (0, 255 - pos * 3, pos * 3)
    pos -= 170
    return (pos * 3, 0, 255 - pos * 3)

def rainbow_cycle(wait):
    for j in range(255):
        for i in range(n):
            rc_index = (i * 256 // n) + j
            np[i] = wheel(rc_index & 255)
        np.write()
        sleep_ms(wait)
    
while not bp.value():
    rainbow_cycle(1)
    
tirage-aleatoire.py — Distribution aléatoire uniforme .python
cours-exemples/neopixel/tirage-aleatoire.py
12 lignes GitHub
from random import randint
 
liste=[]
 
for i in range(20):        # pour 20 nombres...
    tirage = randint(0,8)  # tirage entre 0 et 8
    liste.append(tirage)   # ajout a la liste des tirages
 
print(liste)             
liste.sort()               # classement de la liste dans l'ordre croissant
print(liste)

🔘 Boutons et comptage

Lecture d'entrées numériques, anti-rebond, comptage et touch capacitif.

1 Lecture simple et le piège du comptage naïf

Lire l'état d'un bouton est simple. Compter les appuis l'est beaucoup moins. Le premier réflexe (qui ne fonctionne pas) est d'incrémenter le compteur à chaque itération pendant l'appui :

if bp.value():
    compt = compt + 1  # PROBLÈME : s'incrémente des centaines de fois !

Le problème : un appui d'une demi-seconde sur un bouton, avec une boucle qui tourne à 50 Hz, provoque 25 incrémentations au lieu d'une seule. C'est ce que le fichier comptage-NFP.py illustre (NFP = Ne Fonctionne Pas).

lecture-bp.py — Lecture simple d'un bouton .python
cours-exemples/boutons/lecture-bp.py
18 lignes GitHub
from machine import Pin
from time import sleep

led = Pin(2, Pin.OUT)
bp = Pin(25, Pin.IN)

for t in range(500):    # pour que le code s'arrete au bout de 10 s
    led.value(bp.value()) 
    sleep(.02)
    
#for t in range(500):   # autre ecriture pour la meme chose
#    if bp.value() :
#        led.value(1)
#    else :
#        led.value(0)
#    sleep(.02)    
    
comptage-NFP.py — Comptage naïf — illustre le problème .python
cours-exemples/boutons/comptage-NFP.py
15 lignes GitHub
from machine import Pin
from time import sleep

led = Pin(2, Pin.OUT)
bp = Pin(25, Pin.IN)
compt = 0

for t in range(500):               # le programme s'arrete au bout de 10 s
    if bp.value() :
        compt = compt + 1          # inversion de l'etat de la LED
        print ("compteur", compt)  # affiche le compt si le bp est presse
        led.value(not led.value()) # basculement de la LED
    sleep(.02)    
    

2 La solution bloquante

La version bloquante résout le problème en attendant d'abord l'appui, puis le relâchement, puis en incrémentant :

while not bp.value(): pass  # attendre l'appui
compt = compt + 1           # incrémenter une seule fois
while bp.value(): pass      # attendre le relâchement

Ça fonctionne — mais le programme est bloqué pendant toute la durée de l'attente. Impossible de faire clignoter une LED ou d'effectuer une autre tâche en même temps.

comptage-bloquant.py — Comptage — version bloquante .python
cours-exemples/boutons/comptage-bloquant.py
17 lignes GitHub
from machine import Pin
from time import sleep

led = Pin(2, Pin.OUT)
bp = Pin(25, Pin.IN)
compt = 0

for cycle in range(10):        # on fait juste 10 cycles appui/relachement
    while not bp.value() :     # on attend l'appui sur le bp   
        pass                   # on ne fait rien, mais il faut le dire
    compt = compt + 1
    print("Compteur :",compt)
    led.value(not led.value()) # basculement de la LED
    sleep(0.02)                # delai pour supprimer les rebonds du bp
    while bp.value() :         # on attend l'appui sur le bp   
        pass                   # on ne fait rien, mais il faut le dire
    sleep(.02)                 # delai pour supprimer les rebonds du bp

3 La détection de front montant — version non-bloquante

La solution non-bloquante repose sur la détection de front montant : on ne compte qu'au moment précis où le bouton passe de 0 à 1 (l'instant de l'appui), pas pendant tout l'appui.

Le principe est de mémoriser l'état précédent :

ancien_etat = bp.value()    # mémorisation initiale

for cycle in range(500):    # boucle de 10 s (500 × 20 ms)
    etat = bp.value()
    if not ancien_etat and etat:   # front montant : 0→1
        compt = compt + 1
    sleep(0.02)             # temps de cycle fixe : 20 ms
    ancien_etat = etat      # mémoriser pour le prochain cycle

Théorème de Shannon : pour ne rater aucun appui, la fréquence d'échantillonnage doit être au moins 2 fois supérieure à la fréquence maximale du signal. Avec 50 lectures/seconde (20 ms), on peut détecter jusqu'à 25 appuis/seconde — largement suffisant.

Le temps de cycle est fixe et déterminé : 20 ms, quoi qu'il se passe. Le programme ne se bloque jamais.

comptage-ok.py — Comptage — version non-bloquante (front montant) .python
cours-exemples/boutons/comptage-ok.py
16 lignes GitHub
from machine import Pin
from time import sleep

led = Pin(2, Pin.OUT)
bp = Pin(25, Pin.IN)
compt = 0
ancien_etat = bp.value()

for cycle in range(500):           # on fait 500 cycles, donc durant 10 s
    etat = bp.value()              # = 1 si on appuie
    if not ancien_etat and etat :  # si front montant
        compt = compt + 1          # on incremente
        print("Compteur :",compt)
        led.value(not led.value()) # basculement de la LED
    sleep(.02)                     # temps de cycle
    ancien_etat = etat             # memorise l'etat de la boucle avant           

4 Multi-tâches avec les threads

Les threads permettent d'exécuter plusieurs fonctions en parallèle. Même si une fonction est bloquante, les autres threads continuent de tourner.

import _thread

def comptage():      # fonction bloquante
    while True:
        while not bpA.value(): pass
        compt += 1

def clignotement():  # autre fonction bloquante
    while True:
        led.value(not led.value())
        sleep(0.5)

_thread.start_new_thread(clignotement, ())
_thread.start_new_thread(comptage, ())

Les deux fonctions tournent en parallèle. La LED clignote pendant que le comptage attend l'appui.

comptage-thread.py — Comptage avec thread — multitâche .python
cours-exemples/boutons/comptage-thread.py
30 lignes GitHub
from machine import Pin
from time import sleep
import _thread

led_bleue = Pin(2, Pin.OUT)
bpA = Pin(25, Pin.IN)

led_orange = Pin(19, Pin.OUT)

def comptage():                     # fonction de comptage (bloquant)             
    compt = 0
    while True :
        while not bpA.value():                  # attente de l'appui
            pass                                # ne fait rien
        compt = compt + 1                       # incrementation compteur
        print("Compteur du bpA :",compt)
        led_bleue.value(not led_bleue.value())  # inversion etat de la LED
        sleep(.02)
        while bpA.value():                      # attente du relachement
            pass
        sleep(.02)

def clignotement():                 # fonction de clignotement (bloquante)                 
  while True:
    led_orange.value(not led_orange.value())    # inversion etat de LED
    sleep(.5) 

_thread.start_new_thread(clignotement, ())      # lancement du thread
_thread.start_new_thread(comptage, ())          # lancement du thread 
 

5 Le capteur capacitif (TouchPad)

L'ESP32 dispose de 10 broches pouvant être configurées comme capteurs capacitifs. La valeur lue varie selon la capacité détectée sur la broche :

  • Sans contact : valeur > 150
  • Doigt posé : valeur < 60
from machine import TouchPad, Pin
tp1 = TouchPad(Pin(15))
valeur = tp1.read()        # ex : 200 sans contact, 40 au toucher

Pour compter les appuis, on applique le même principe de front montant qu'avec un bouton classique, en utilisant un seuil de comparaison : etat = tp1.read() < 100 renvoie True si touché, False sinon.

touchpad.py — Capteur capacitif (touch) .python
cours-exemples/boutons/touchpad.py
12 lignes GitHub
from machine import TouchPad, Pin
from time import sleep

tp1 = TouchPad(Pin(15))              # Touch Pin 1 sur pin 15
tp2 = TouchPad(Pin(4))               # Touch Pin 2 sur pin 4

for boucle in range (400) :          # duree de la boucle : 4 s
    etat1 = tp1.read()               # lecture du TouchPad 1
    etat2 = tp2.read()
    print("Touche 1 : {0:3d}  Touche 2 : {1:3d}".format(etat1, etat2))
    sleep(.01)
touchpad-comptage-bloquant.py — Comptage touch — version bloquante .python
cours-exemples/boutons/touchpad-comptage-bloquant.py
18 lignes GitHub
from machine import TouchPad, Pin
from time import sleep

tp1 = TouchPad(Pin(15))
led_bleue = Pin(2, Pin.OUT)
compt = 0
seuil = 200
ancien_etat = tp1.read()

for boucle in range (10) :         # on fait juste 10 cycles, et on arrete
    while not tp1.read() < seuil : # on attend l'appui sur le touch pad
        pass                       # on ne fait rien, mais il faut le dire
    compt = compt + 1
    print("Compteur :",compt)
    led_bleue.value(not led_bleue.value())     # basculement de led_bleue
    while tp1.read() < seuil :     # on attend l'appui sur le touch pin   
        pass                       # on ne fait rien, mais il faut le dire
touchpad-comptage-ok.py — Comptage touch — version non-bloquante .python
cours-exemples/boutons/touchpad-comptage-ok.py
18 lignes GitHub
from machine import TouchPad, Pin
from time import sleep

tp1 = TouchPad(Pin(15))
led_bleue = Pin(2, Pin.OUT)
compt = 0
seuil = 200
ancien_etat = tp1.read()

for boucle in range (500) :        # duree de la boucle : 10 s
    etat = tp1.read() < seuil      # le test renvoie 1 si on touche
    if etat and not ancien_etat :  # si front montant
        compt = compt + 1          # on incremente
        print("Compteur :",compt)
        led_bleue.value(not led_bleue.value()) # bascule de led_bleue
    ancien_etat = etat             # memorisation ancien etat
    sleep(.02)                     # temps de cycle

Capteurs et afficheurs

ADC, OLED SSD1306 et capteur de température DS18B20.

Cours suivant →