#!/usr/bin/env python3 """Plan d'implantation vu de dessus : côté composants + côté soudures (miroir).""" import runpy, sys OUT = sys.argv[1] sys.argv = ["x", "/dev/null"] g = runpy.run_path(sys.path[0] + "/gen_fzz.py", run_name="gen") COLS, ROWS = g["COLS"], g["ROWS"] NU = g["NU"] leds, res_anode, res_base, trans = g["leds"], g["res_anode"], g["res_base"], g["trans"] board_wires, ard_jobs = g["board_wires"], g["ard_jobs"] PX = 16 # pas d'affichage MARGE_X, MARGE_Y = 44, 120 PANNEAU = COLS * PX + 2 * MARGE_X LARG = 2 * PANNEAU + 40 HAUT = MARGE_Y + ROWS * PX + 270 out = [] A = out.append def xy(c, r, panneau): if panneau == 1: # côté soudures : plaque retournée gauche/droite c = COLS - 1 - c return (panneau * (PANNEAU + 40) + MARGE_X + c * PX + PX / 2, MARGE_Y + r * PX + PX / 2) def txt(x, y, s, size=11, anchor="middle", fill="#333", weight="normal", rot=None): tr = f' transform="rotate({rot} {x:.1f} {y:.1f})"' if rot else "" A(f'{s}') A(f'') A('Implantation de la matrice 3x3 sur plaque à pastilles') A(f'') for pan, titre, sous in ((0, "Côté composants (vu de dessus)", "on pose les composants et les fils isolés"), (1, "Côté soudures (plaque retournée)", "on soude et on relie avec du fil nu. Attention : image en miroir !")): x0 = pan * (PANNEAU + 40) + MARGE_X txt(x0, 34, titre, 18, "start", "#222", "bold") txt(x0, 54, sous, 13, "start", "#666") # plaque A(f'') # numéros de colonnes et de lignes (comptés à partir de 1) for c in range(COLS): x, _ = xy(c, 0, pan) if (c + 1) % 5 == 0 or c == 0: txt(x, MARGE_Y + ROWS * PX + 22, str(c + 1), 10, fill="#8a6d3b") for r in range(ROWS): _, y = xy(0, r, pan) if (r + 1) % 5 == 0 or r == 0: txt(x0 - 14, y + 4, str(r + 1), 10, fill="#8a6d3b") # pastilles for c in range(COLS): for r in range(ROWS): x, y = xy(c, r, pan) A(f'' f'') # ---------------------------------------------------------------- côté composants def contour_led(inst, pan, plein): hs = list(inst["holes"].values()) xs = [xy(c, r, pan)[0] for c, r in hs] cx, cy = sum(xs) / 4, xy(*hs[0], pan)[1] if plein: A(f'') for (c, r), lettre, coul in zip(hs, "RKGB", ("#cc1414", "#222", "#2a9d3a", "#2f6fc4")): x, y = xy(c, r, pan) A(f'') txt(x, y - 6, lettre, 9, fill=coul, weight="bold") else: A(f'') def contour_res(inst, pan, plein, valeur): (c1, r1), (c2, r2) = inst["holes"].values() (xa, ya), (xb, yb) = xy(c1, r1, pan), xy(c2, r2, pan) if plein: A(f'') vertical = abs(xa - xb) < 1 L = 0.55 * (abs(ya - yb) if vertical else abs(xa - xb)) mx, my = (xa + xb) / 2, (ya + yb) / 2 w, h = (9, L) if vertical else (L, 9) style = ('fill="#e8d3a8" stroke="#a88a52"' if plein else 'fill="none" stroke="#9a7b4a" stroke-dasharray="3 3"') A(f'') if plein: txt(mx + (0 if vertical else 0), my + (3 if not vertical else 3), valeur, 8, fill="#5a4310", weight="bold", rot=(-90 if vertical else None)) def contour_npn(inst, pan, plein, nom): hs = inst["holes"] xc, y = xy(*hs["connector2"], pan) xe, _ = xy(*hs["connector0"], pan) cx = (xc + xe) / 2 R = PX * 1.25 # demi-cercle, face plate vers le bas de la plaque d = f'M{cx - R:.1f} {y + 5:.1f} A{R:.1f} {R:.1f} 0 0 1 {cx + R:.1f} {y + 5:.1f} Z' if plein: A(f'') for con, lettre in (("connector2", "C"), ("connector1", "B"), ("connector0", "E")): x, yy = xy(*hs[con], pan) A(f'') txt(x, yy - 6, lettre, 9, fill="#fff", weight="bold") txt(cx, y - R + 2, nom, 10, fill="#222", weight="bold") else: A(f'') def composants(pan, plein): for k, inst in res_anode.items(): contour_res(inst, pan, plein, inst["props"]["resistance"].replace("Ω", "")) for r, inst in res_base.items(): contour_res(inst, pan, plein, "1k") for inst in leds.values(): contour_led(inst, pan, plein) for r, inst in trans.items(): contour_npn(inst, pan, plein, f"T{r}") # fils isolés (côté composants) for a, b, coul in board_wires: if coul == NU: continue (xa, ya), (xb, yb) = xy(*a, 0), xy(*b, 0) A(f'') composants(0, True) # arrivées des fils de l'Arduino for pin, (c, r), coul in ard_jobs: x, y = xy(c, r, 0) A(f'') if r <= 2: # entrées en haut de la plaque : étiquette verticale au-dessus A(f'') txt(x + 4, MARGE_Y - 30, pin, 11, "start", coul if coul != "#ffe24d" else "#b39b00", "bold", rot=-90) else: txt(x + 9, y + 4, pin, 11, "start", "#222", "bold") # ---------------------------------------------------------------- côté soudures composants(1, False) for a, b, coul in board_wires: (xa, ya), (xb, yb) = xy(*a, 1), xy(*b, 1) if coul == NU: A(f'') soudures = set() for inst in list(leds.values()) + list(res_anode.values()) + list(res_base.values()) + list(trans.values()): soudures.update(inst["holes"].values()) for a, b, coul in board_wires: soudures.update((a, b)) for _, h, _ in ard_jobs: soudures.add(h) for c, r in soudures: x, y = xy(c, r, 1) A(f'') for a, b, coul in board_wires: # bouts des fils isolés qui traversent if coul != NU: for h in (a, b): x, y = xy(*h, 1) A(f'') for pin, h, coul in ard_jobs: x, y = xy(*h, 1) A(f'') # ---------------------------------------------------------------- légende ly = MARGE_Y + ROWS * PX + 56 txt(MARGE_X, ly, "Légende", 15, "start", "#222", "bold") items = [ ('', "LED RGB vue de dessus : pattes R, K (cathode, la plus longue), G, B"), ('', "Résistance (valeur en ohms : 220, 150, 1k = 1000)"), ('', "Transistor BC337, face plate vers le bas : pattes C, B, E de gauche à droite"), ('', "Fil isolé, côté composants (cathodes des lignes)"), ('', "Fil nu (ou patte repliée), côté soudures"), ('', "Arrivée d'un fil vers l'Arduino (D2 à D13, GND)"), ] for i, (forme, texte) in enumerate(items): col, lig = i % 2, i // 2 bx = MARGE_X + col * (LARG / 2) by = ly + 30 + lig * 30 A(forme.format(x=bx + 11, y=by - 4, xm=bx, ym=by - 8, xl=bx, xr=bx + 22, y4=by + 2)) txt(bx + 34, by, texte, 12, "start", "#333") txt(MARGE_X, ly + 140, "Pas entre LED : 6 trous = 15,24 mm. Les numéros de colonnes et de " "lignes sont ceux du côté composants ; côté soudures, gauche et droite sont inversées.", 12, "start", "#666") txt(MARGE_X, ly + 160, "Correspondance avec le code : colonne c de la matrice = LED Lr Cc ; " "ligne r = transistor Tr (broche D11 + r).", 12, "start", "#666") A("") with open(OUT, "w") as f: f.write("\n".join(out))