"""Module 2 — Entrées/sorties numériques & LED RGB NeoPixel.""" import matplotlib.pyplot as plt import numpy as np import schemdraw import schemdraw.elements as elm from outils import chronogramme from style import BLEU, CM, ENCRE, GRIS, ORANGE, ROUGE, VERT, Figure schemdraw.use("matplotlib") def pull_up(): d = schemdraw.Drawing(show=False) d.config(fontsize=10.5, unit=2.4, color=ENCRE) d += (vdd := elm.Vdd().label("3V3")) d += (r := elm.Resistor().down().label("pull-up interne\n≈ 45 kΩ", loc="bottom").color(BLEU)) d += (n := elm.Dot()) d += (lecture := elm.Line().left().length(2.6).label("vers digitalRead()", loc="top", fontsize=9).color(BLEU)) d += elm.Line().right().at(n.center).length(2.8) d += (gpio := elm.Dot(open=True).label("GPIO5", loc="top")) d += elm.Line().right().length(1.2) d += elm.Button().down().label("bouton", loc="bottom").color(ORANGE) d += elm.Ground() d += elm.EncircleBox([vdd, r, n, lecture, gpio], padx=0.3, pady=0.5).linestyle("--").color(GRIS) d += elm.Label().at((n.center[0] + 1.6, vdd.end[1] + 0.2)).label("à l'intérieur\nde l'ESP32-S3", color=GRIS, fontsize=9) d += elm.Label().at((gpio.center[0] + 3.6, n.center[1] - 2.0)).label( "relâché → HIGH (3,3 V)\nappuyé → LOW (0 V)", fontsize=10, color=VERT) return d.draw(show=False) def rebonds(): t = [0] niv = [1] # Appui avec rebonds autour de 40 ms, relâchement avec rebonds autour de 140 ms for a, b in ((40, 0), (41.2, 1), (42, 0), (43.5, 1), (44.1, 0), (140, 1), (140.8, 0), (141.9, 1), (142.5, 0), (143.2, 1)): t.append(a) niv.append(b) voies = [("broche (brut)", list(zip(t, niv))), ("état retenu", [(0, 1), (54, 0), (153, 1)])] fig, ax, y = chronogramme(voies, 200, largeur_cm=16, hauteur_voie_cm=1.7, graduations=range(0, 201, 25), unite="temps (ms)", couleurs={"état retenu": VERT}) for x0, x1, txt in ((40, 44.1, "rebonds\n(quelques ms)"), (140, 143.2, "rebonds")): ax.axvspan(x0 - 1, x1 + 1, color=ORANGE, alpha=0.18) ax.text((x0 + x1) / 2, y(0) + 1.25, txt, ha="center", fontsize=7.5, color=ORANGE) ax.annotate("", xy=(54, y(1) + 0.5), xytext=(44.1, y(1) + 0.5), arrowprops=dict(arrowstyle="<->", color=ENCRE, lw=0.9)) ax.text(49, y(1) + 0.62, "attente", ha="center", fontsize=7, color=ENCRE) ax.text(97, y(1) + 0.3, "un seul appui détecté", ha="center", fontsize=8, color=VERT, fontweight="bold") ax.set_ylim(-0.5, 3.9) fig.tight_layout() return fig def chenillard(): d = schemdraw.Drawing(show=False) d.config(fontsize=10.5, unit=2.2, color=ENCRE) pins = [elm.IcPin(name=f"GPIO{g}", side="right", anchorname=f"P{g}") for g in (7, 6, 5, 4)] ic = elm.Ic(pins=pins, size=(3.2, 5.4), pinfontsize=10).label("ESP32-S3", loc="center", fontsize=12).color(BLEU) d += ic couleurs = {4: ROUGE, 5: VERT, 6: BLEU, 7: ORANGE} fins = [] for g in (4, 5, 6, 7): d += elm.Line().right().at(getattr(ic, f"P{g}")).length(0.6) d += elm.Resistor().right().label("220 Ω", fontsize=9) d += elm.LED().right().color(couleurs[g]) d += elm.Line().right().length(0.6) fins.append(d.here) d += elm.Line().at(fins[0]).to(fins[-1]) d += elm.Line().down().at(fins[-1]).length(0.6) d += elm.Ground() d += elm.Label().at((fins[0][0] + 0.4, (fins[0][1] + fins[-1][1]) / 2)).label("GND\ncommun", loc="right", fontsize=9, color=GRIS) return d.draw(show=False) def ws2812(): fig = plt.figure(figsize=(16 * CM, 8.6 * CM)) # (a) trame 24 bits ax1 = fig.add_axes([0.04, 0.62, 0.92, 0.3]) ax1.axis("off") ax1.set_xlim(0, 24) ax1.set_ylim(0, 1.6) for k, (nom, c) in enumerate((("G", VERT), ("R", ROUGE), ("B", BLEU))): for b in range(8): x = k * 8 + b ax1.add_patch(plt.Rectangle((x, 0.3), 1, 0.8, facecolor=c, alpha=0.18 + 0.06 * (7 - b) / 7, edgecolor=c, lw=1)) ax1.text(x + 0.5, 0.7, f"{nom}{7 - b}", ha="center", va="center", fontsize=6.5, color=ENCRE) ax1.text(k * 8 + 4, 1.25, {"G": "Vert (8 bits)", "R": "Rouge (8 bits)", "B": "Bleu (8 bits)"}[nom], ha="center", fontsize=8.5, color=c, fontweight="bold") ax1.text(0, 0.02, "(a) Une couleur = 24 bits, envoyés dans l'ordre G-R-B (d'où NEO_GRB), bit de poids fort en premier", fontsize=8, color=GRIS) # (b) codage d'un bit ax2 = fig.add_axes([0.08, 0.12, 0.88, 0.36]) for x0, th, tl, nom in ((0, 0.4, 0.85, "bit 0"), (1.8, 0.8, 0.45, "bit 1")): xs = [x0, x0, x0 + th, x0 + th, x0 + th + tl] ys = [0, 1, 1, 0, 0] ax2.plot(xs, ys, color=BLEU, lw=1.8) ax2.fill_between([x0, x0 + th], 0, 1, color=BLEU, alpha=0.12) ax2.text(x0 + (th + tl) / 2, 1.32, nom, ha="center", fontsize=9, fontweight="bold", color=ENCRE) ax2.annotate("", xy=(x0, 1.1), xytext=(x0 + th, 1.1), arrowprops=dict(arrowstyle="<->", lw=0.8)) ax2.text(x0 + th / 2, 1.14, f"{th} µs".replace(".", ","), ha="center", va="bottom", fontsize=7.5) ax2.annotate("", xy=(x0 + th, -0.12), xytext=(x0 + th + tl, -0.12), arrowprops=dict(arrowstyle="<->", lw=0.8)) ax2.text(x0 + th + tl / 2, -0.2, f"{tl} µs".replace(".", ","), ha="center", va="top", fontsize=7.5) ax2.text(3.4, 0.55, "période d'un bit : 1,25 µs (800 kHz)\nla différence se joue à ~400 ns près :\n" "impossible avec digitalWrite(),\nla bibliothèque utilise le matériel (RMT)", fontsize=8, color=ENCRE, va="center") ax2.set_xlim(-0.1, 6.2) ax2.set_ylim(-0.5, 1.6) ax2.axis("off") fig.text(0.04, 0.03, "(b) Codage d'un bit : seule la durée de l'état haut change", fontsize=8, color=GRIS) return fig FIGURES = [ Figure("m02-pull-up", pull_up), Figure("m02-rebonds", rebonds), Figure("m02-chenillard", chenillard), Figure("m02-ws2812", ws2812), ]