This commit is contained in:
bach
2026-10-08 15:33:47 +02:00
parent da4fac3af7
commit 98fca33142
6 changed files with 605 additions and 83 deletions
+204 -66
View File
@@ -1,6 +1,8 @@
#!/usr/bin/env python3
"""Dessine les schémas du dossier « schemas » :
- branchement.svg : Raspberry Pi + 74AHCT125 + matrice + alimentation
- branchement_sans_puce.svg : solution A sans puce (matrice en 4,4 V)
- branchement_transistor.svg : solution B sans puce (transistor inverseur)
- brochage_74ahct125.svg : la puce adaptatrice de niveau, patte par patte
- chaine_krita_matrice.svg : le trajet d'une animation, de Krita à la matrice
Usage : python3 outils/schemas.py"""
@@ -66,10 +68,9 @@ def hop_h(x_croise, sens=1, r=7):
# 1. BRANCHEMENT
# =============================================================================
def branchement():
s = Svg(1200, 940, "Branchement matrice WS2812B 8×32, Raspberry Pi, 74AHCT125 "
"et alimentation d'établi")
def _matrice_et_alimentation(s, tension="5.00 V"):
"""Partie commune à tous les montages : matrice vue de dos, sortie DOUT,
alimentation d'établi + condensateur, connecteur DIN et sa fiche."""
# ---------- matrice (vue de dos) ----------
s.texte(60, 38, "Matrice WS2812B 8 × 32 — vue de dos (côté fils)", 20, "#222", gras=True)
s.add('<pattern id="pix" x="60" y="55" width="30.625" height="30.625" '
@@ -107,7 +108,7 @@ def branchement():
s.rect(300, 500, 330, 210, "#e9ecef", 10, "#adb5bd", 2)
s.texte(465, 526, "Alimentation d'établi", 16, "#333", "middle", True)
s.rect(318, 540, 160, 96, "#1d2b1d", 4)
s.texte(398, 578, "5.00 V", 28, "#7dff7d", "middle", True, True)
s.texte(398, 578, tension, 28, "#7dff7d", "middle", True, True)
s.texte(398, 618, "3.00 A", 20, "#ffb347", "middle", mono=True)
for x, t in [(345, "tension"), (420, "courant")]:
s.add(f'<circle cx="{x}" cy="672" r="16" fill="#666"/>')
@@ -127,6 +128,102 @@ def branchement():
s.texte(966, 358, "connecteur DIN de la matrice", 13, "#555")
s.texte(966, 381, "+ fiche fournie (rouge / blanc / vert)", 13, "#555")
def _resistance_v(s, x, y, couleurs, valeur, sous_titre=None):
"""Résistance verticale de 40 de haut, centrée en x, du haut y à y + 40."""
s.rect(x - 9, y, 18, 40, "#e8d3a8", 6, "#a88a52")
for i, c in enumerate(couleurs):
s.rect(x - 9, y + 8 + i * 8, 18, 4, c)
s.rect(x - 9, y + 32, 18, 3, "#c9a227")
s.texte(x + 18, y + 16, valeur, 13, "#7a5a1e", gras=True)
if sous_titre:
s.texte(x + 18, y + 33, sous_titre, 12, "#7a5a1e")
def _resistance_h(s, x, y, couleurs, valeur):
"""Résistance horizontale de 40 de large, centrée en y, de x à x + 40."""
s.rect(x, y - 9, 40, 18, "#e8d3a8", 6, "#a88a52")
for i, c in enumerate(couleurs):
s.rect(x + 8 + i * 8, y - 9, 4, 18, c)
s.rect(x + 32, y - 9, 3, 18, "#c9a227")
s.texte(x + 20, y - 15, valeur, 13, "#7a5a1e", "middle", True)
ANNEAUX_330 = ["#e67e22", "#e67e22", "#8b4513"] # orange-orange-marron
ANNEAUX_1K = ["#8b4513", "#1a1a1a", ROUGE] # marron-noir-rouge
def _raspberry_pi(s, x0, pas=16, y=645):
"""Carte Raspberry Pi avec son connecteur 40 pattes.
x0 = abscisse de la patte 2 ; renvoie un dictionnaire n° de patte → x."""
largeur = 19 * pas + 104
gauche = x0 - 52
s.rect(gauche, y, largeur, 230, "#1f7a3a", 12)
s.rect(x0 - 13, y + 10, 19 * pas + 26, 42, "#143d20", 3)
xs = {}
for i in range(20):
for n, yy in ((2 * i + 2, y + 21), (2 * i + 1, y + 39)): # bord : paires
xs[n] = x0 + i * pas
couleur = "#d4af37"
if n in (2, 4):
couleur = ROUGE
elif n in (6, 14):
couleur = NOIR
elif n == 12:
couleur = JAUNE_GPIO
s.rect(xs[n] - 5, yy - 5, 10, 10, couleur, 1)
s.texte(x0 - 9, y + 25, "2", 9, "#cde", "end")
s.texte(x0 - 9, y + 43, "1", 9, "#cde", "end")
s.texte(x0 + 19 * pas + 9, y + 25, "40", 9, "#cde")
s.texte(x0 + 19 * pas + 9, y + 43, "39", 9, "#cde")
centre = gauche + largeur / 2
s.texte(centre, y + 125, "Raspberry Pi", 24, "#fff", "middle", True)
s.texte(centre, y + 149, "3B+, 4 ou Zero 2 W (pas le Pi 5)", 14, "#d8f0dd", "middle")
s.texte(xs[12] + 3, y + 67, "patte 12 = GPIO 18", 12, "#ffe08a", "start", True)
s.texte(xs[6] - 2, y + 67, "patte 6 = GND", 12, "#fff", "end", True)
s.add(f'<path d="M{gauche + 30} {y + 188} l16 16 m0 -16 l-16 16" '
f'stroke="#ffb3b3" stroke-width="3"/>')
s.texte(gauche + 56, y + 201, "pattes 2 et 4 (5 V) : NE PAS relier à la matrice", 12, "#ffd6d6")
# alimentation USB du Pi
droite = gauche + largeur
s.rect(droite, y + 145, 18, 34, "#b8b8b8", 3)
s.fil(f"M{droite + 18} {y + 162} H{droite + 30} V{y + 255}", "#555")
s.texte(droite + 25, y + 273, "bloc secteur USB du Pi", 13, "#333", "end")
s.texte(droite + 25, y + 290, "(5 V, 2,5 A ou plus)", 12, "#777", "end")
return xs
def _legende(s, fils, lignes_gnd, alerte, notes=()):
s.rect(40, 470, 236, 140 + 28 * len(fils) + 18 * len(lignes_gnd) + 14 * len(notes),
"#f8f9fa", 8, "#dee2e6")
s.texte(56, 496, "Code couleur des fils", 15, "#222", gras=True)
for i, (c, t) in enumerate(fils):
y = 520 + i * 28
s.add(f'<line x1="56" y1="{y}" x2="90" y2="{y}" stroke="{c}" stroke-width="6" '
'stroke-linecap="round"/>')
s.texte(100, y + 5, t, 14)
y = 520 + len(fils) * 28 + 10
for ligne in lignes_gnd:
s.texte(56, y, ligne, 13, "#555")
y += 18
y += 6
s.texte(56, y, alerte, 13, "#b00020", gras=True)
y += 22
for ligne in notes:
s.texte(56, y, ligne, 12, "#777")
y += 14
FILS_5V = [(ROUGE, "rouge = + 5 V"), (NOIR, "noir = GND (masse)"),
(BLANC_FIL, "blanc = GND (masse)"), (VERT, "vert = données 5 V"),
(JAUNE_GPIO, "jaune = données 3,3 V")]
def branchement():
s = Svg(1200, 940, "Branchement matrice WS2812B 8×32, Raspberry Pi, 74AHCT125 "
"et alimentation d'établi")
_matrice_et_alimentation(s)
# ---------- plaque d'essai + 74AHCT125 ----------
s.rect(700, 425, 440, 190, "#f6f1e3", 8, "#d9cfb2", 2)
s.texte(1132, 608, "plaque d'essai", 12, "#a8997a", "end")
@@ -164,75 +261,114 @@ def branchement():
s.texte(broche_bas(3) + 6, 545, "1Y", 11, VERT, "start", True)
s.texte(broche_bas(7) + 8, 545, "GND", 11, "#333", "start", True)
# résistance 330 Ω
s.rect(1071, 470, 18, 40, "#e8d3a8", 6, "#a88a52")
for y, c in [(478, "#e67e22"), (486, "#e67e22"), (494, "#8b4513")]:
s.rect(1071, y, 18, 4, c)
s.rect(1071, 502, 18, 3, "#c9a227")
s.texte(1098, 486, "330 Ω", 13, "#7a5a1e", gras=True)
_resistance_v(s, 1080, 470, ANNEAUX_330, "330 Ω")
s.texte(966, 404, "fil rouge de la fiche : il alimente", 12, ROUGE, gras=True)
s.texte(966, 418, "la puce (patte 14 = VCC, 5 V)", 12, ROUGE, gras=True)
# ---------- Raspberry Pi ----------
s.rect(700, 645, 440, 230, "#1f7a3a", 12)
s.rect(750, 655, 336, 42, "#143d20", 3)
x0 = broche_bas(2) - 80 # x de la patte 2 → la patte 12 tombe sous « 1A »
for i in range(20):
for rang, y in ((0, 666), (1, 684)): # rangée du bord : pattes paires
n = 2 * i + 2 if rang == 0 else 2 * i + 1
couleur = "#d4af37"
if n in (2, 4):
couleur = ROUGE
elif n in (6, 14):
couleur = NOIR
elif n == 12:
couleur = JAUNE_GPIO
s.rect(x0 + i * 16 - 5, y - 5, 10, 10, couleur, 1)
s.texte(x0 - 9, 670, "2", 9, "#cde", "end")
s.texte(x0 - 9, 688, "1", 9, "#cde", "end")
s.texte(x0 + 19 * 16 + 9, 670, "40", 9, "#cde")
s.texte(x0 + 19 * 16 + 9, 688, "39", 9, "#cde")
# GPIO 18 (patte 12) → 1A (patte 2)
s.fil(f"M{broche_bas(2)} 528 V661", JAUNE_GPIO)
# GND (patte 6) ← rail
s.fil(f"M780 585 V630 H{x0 + 32} V661", NOIR, 4)
s.texte(920, 770, "Raspberry Pi", 24, "#fff", "middle", True)
s.texte(920, 794, "3B+, 4 ou Zero 2 W (pas le Pi 5)", 14, "#d8f0dd", "middle")
s.texte(x0 + 80, 712, "patte 12 = GPIO 18", 12, "#ffe08a", "start", True)
s.texte(x0 + 30, 712, "patte 6 = GND", 12, "#fff", "end", True)
s.add(f'<path d="M{x0 + 8} 833 L{x0 + 24} 849 M{x0 + 24} 833 L{x0 + 8} 849" '
f'stroke="#ffb3b3" stroke-width="3"/>')
s.texte(x0 + 34, 846, "pattes 2 et 4 (5 V) : NE PAS relier à la matrice", 12, "#ffd6d6")
# alimentation USB du Pi
s.rect(1140, 790, 18, 34, "#b8b8b8", 3)
s.fil("M1158 807 H1180 V900", "#555")
s.texte(1170, 918, "bloc secteur USB du Pi", 13, "#333", "end")
s.texte(1170, 935, "(5 V, 2,5 A ou plus)", 12, "#777", "end")
# ---------- légende ----------
s.rect(40, 470, 236, 300, "#f8f9fa", 8, "#dee2e6")
s.texte(56, 496, "Code couleur des fils", 15, "#222", gras=True)
for i, (c, t) in enumerate([(ROUGE, "rouge = + 5 V"), (NOIR, "noir = GND (masse)"),
(BLANC_FIL, "blanc = GND (masse)"), (VERT, "vert = données 5 V"),
(JAUNE_GPIO, "jaune = données 3,3 V")]):
y = 520 + i * 28
s.add(f'<line x1="56" y1="{y}" x2="90" y2="{y}" stroke="{c}" stroke-width="6" '
'stroke-linecap="round"/>')
s.texte(100, y + 5, t, 14)
s.texte(56, 670, "Tous les GND sont reliés :", 13, "#555")
s.texte(56, 688, "Pi ↔ puce ↔ fil blanc ↔ matrice", 13, "#555")
s.texte(56, 706, "↔ fil noir ↔ borne − de l'alim.", 13, "#555")
s.texte(56, 730, "Alim. réglée sur 5,0 V maxi !", 13, "#b00020", gras=True)
s.texte(56, 752, "Un pont = les fils se croisent", 12, "#777")
s.texte(56, 766, "sans se toucher.", 12, "#777")
pattes = _raspberry_pi(s, broche_bas(2) - 80) # la patte 12 tombe sous « 1A »
s.fil(f"M{broche_bas(2)} 528 V661", JAUNE_GPIO) # GPIO 18 → 1A
s.fil(f"M780 585 V630 H{pattes[6]} V661", NOIR, 4) # GND (patte 6) ← rail
_legende(s, FILS_5V,
["Tous les GND sont reliés :", "Pi ↔ puce ↔ fil blanc ↔ matrice",
"↔ fil noir ↔ borne − de l'alim."],
"Alim. réglée sur 5,0 V maxi !",
["Un pont = les fils se croisent", "sans se toucher."])
s.save("branchement.svg")
def branchement_sans_puce():
"""Solution A : pas d'adaptateur, la matrice est alimentée en 4,4 V."""
s = Svg(1200, 940, "Branchement sans 74AHCT125 (solution A) : matrice en 4,4 V, "
"Raspberry Pi relié directement")
_matrice_et_alimentation(s, "4.40 V")
pattes_x0 = 832 # le Pi doit tenir dans la largeur du dessin
# fil rouge de la fiche : isolé
s.fil("M880 386 V420", ROUGE)
s.rect(872, 418, 16, 16, "#f2c94c", 2)
s.texte(864, 431, "fil rouge : NON branché, isolé (scotch)", 13, "#b00020", "end", True)
# fil vert → 330 Ω → patte 12 ; fil blanc → patte 6
s.fil("M940 386 V440 H948 V470", VERT)
_resistance_v(s, 948, 470, ANNEAUX_330, "330 Ω", "(300 à 500 Ω)")
pattes = _raspberry_pi(s, pattes_x0, pas=14)
s.fil(f"M948 510 V620 H{pattes[12]} V661", JAUNE_GPIO)
s.fil(f"M910 386 V600 H{pattes[6]} V661", BLANC_FIL)
# encadré d'explication
s.rect(660, 455, 230, 120, "#fff8e1", 8, "#f2c94c", 2)
for i, (t, gras) in enumerate([("Pourquoi 4,4 V ?", True),
("Le « 1 » doit dépasser 70 %", False),
("de la tension des LED :", False),
("0,7 × 4,4 V ≈ 3,1 V", True),
("→ les 3,3 V du Pi suffisent.", False)]):
s.texte(675, 480 + i * 20, t, 13, "#7a5a00", gras=gras)
_legende(s, [(ROUGE, "rouge = + 4,4 V"), (NOIR, "noir = GND (masse)"),
(BLANC_FIL, "blanc = GND (masse)"), (VERT, "vert = données"),
(JAUNE_GPIO, "jaune = données 3,3 V")],
["Tous les GND sont reliés :", "Pi ↔ fil blanc ↔ matrice",
"↔ fil noir ↔ borne − de l'alim."],
"Alim. réglée sur 4,4 V !",
["Entre 4,2 et 4,5 V.", "Fil de données : moins de 30 cm."])
s.save("branchement_sans_puce.svg")
def branchement_transistor():
"""Solution B : un transistor NPN (2N3904) en inverseur, matrice en 5 V."""
s = Svg(1200, 940, "Branchement sans 74AHCT125 (solution B) : transistor 2N3904 "
"en adaptateur de niveau")
_matrice_et_alimentation(s)
s.rect(700, 425, 440, 190, "#f6f1e3", 8, "#d9cfb2", 2)
s.texte(1132, 608, "plaque d'essai", 12, "#a8997a", "end")
XC = 1030 # verticale du collecteur et de l'émetteur
XB = 1013 # barre de base du transistor
# rouge (5 V) → résistance de tirage 1 kΩ → nœud du collecteur
s.fil(f"M880 386 V440 H{XC} V455", ROUGE)
_resistance_v(s, XC, 455, ANNEAUX_1K, "1 kΩ", "tirage")
# vert (DIN) ← nœud du collecteur
s.fil(f"M940 386 V400 H1100 V505 H{XC}", VERT)
s.fil(f"M{XC} 495 V520", VERT)
s.point(XC, 505, VERT)
# transistor NPN
s.add(f'<circle cx="{XC - 8}" cy="540" r="24" fill="#fff" stroke="#333" stroke-width="2"/>')
s.add(f'<line x1="{XB}" y1="526" x2="{XB}" y2="554" stroke="#333" stroke-width="4"/>')
s.fil(f"M{XB} 534 L{XC} 520", "#333", 3)
s.fil(f"M{XB} 546 L{XC} 560 V585", "#333", 3)
s.add(f'<path d="M{XC - 9} 550 L{XC} 560 L{XC - 12} 561 Z" fill="#333"/>')
s.texte(XC + 10, 524, "C", 12, "#333", gras=True)
s.texte(XC + 10, 570, "E", 12, "#333", gras=True)
s.texte(XB - 4, 528, "B", 12, "#333", "end", True)
s.texte(XC + 26, 545, "2N3904", 13, "#333", gras=True)
s.texte(XC + 26, 561, "(NPN)", 12, "#555")
# base ← 1 kΩ ← GPIO 18
pattes_x0 = 843 - 80
_resistance_h(s, 930, 540, ANNEAUX_1K, "1 kΩ")
s.fil(f"M970 540 H{XB}", JAUNE_GPIO, 4)
s.fil(f"M843 661 V540 {hop_h(910, 1)} H930", JAUNE_GPIO)
# masses : blanc → rail → émetteur et Pi
s.fil(f"M910 386 V585 H{XC}", BLANC_FIL)
s.point(XC, 585, NOIR)
s.point(910, 585, BLANC_FIL)
pattes = _raspberry_pi(s, pattes_x0)
s.fil(f"M910 585 V630 {hop_h(843, -1)} H{pattes[6]} V661", NOIR, 4)
s.texte(712, 448, "fil rouge (5 V) : seulement", 11, ROUGE, gras=True)
s.texte(712, 461, "vers la résistance de tirage", 11, ROUGE, gras=True)
_legende(s, FILS_5V,
["Tous les GND sont reliés :", "Pi ↔ émetteur ↔ fil blanc",
"↔ matrice ↔ borne − de l'alim."],
"Dans matrice.py :",
["INVERSER_SIGNAL = True", "(le transistor inverse le signal)",
"Vérifier l'ordre E-B-C du", "transistor sur sa datasheet !"])
s.save("branchement_transistor.svg")
# =============================================================================
# 2. BROCHAGE DU 74AHCT125
# =============================================================================
@@ -285,7 +421,7 @@ def chaine():
("#c9682a", "3. Vérifier", ["verifier_animation.py", "+ simulateur", "sur l'ordinateur"]),
("#b08900", "4. Déposer", ["dossier « animations »", "carte SD ou réseau", "(01_, 02_… = ordre)"]),
("#1f7a3a", "5. Lire", ["Raspberry Pi", "lecteur.py : gamma,", "luminosité, serpentin"]),
("#2f6fc4", "6. Afficher", ["74AHCT125 (3,3 → 5 V)", "puis 256 LED", "WS2812B"]),
("#2f6fc4", "6. Afficher", ["adaptateur 3,3 → 5 V", "(ou matrice en 4,4 V)", "puis 256 LED WS2812B"]),
]
larg, ecart = 170, 28
for i, (c, titre, lignes) in enumerate(etapes):
@@ -311,6 +447,8 @@ def chaine():
if __name__ == "__main__":
os.makedirs(SORTIE, exist_ok=True)
branchement()
branchement_sans_puce()
branchement_transistor()
brochage()
chaine()
print("Schémas écrits dans", SORTIE)