better 3x3 doc
This commit is contained in:
@@ -0,0 +1,293 @@
|
||||
# Maquette 3 × 3 : matrice de LED RGB multiplexée
|
||||
|
||||
Workshop « Vitrine pixels » : on fabrique un petit écran de **9 pixels** de
|
||||
couleur, soudé sur une plaque à pastilles et piloté par un Arduino.
|
||||
C'est la maquette d'apprentissage avant la grande matrice 7 × 39.
|
||||
|
||||

|
||||
|
||||
> **Le principe à retenir** : on n'allume jamais les 9 LED en même temps.
|
||||
> On allume **une ligne à la fois**, très vite (environ 333 fois par seconde),
|
||||
> et l'œil voit une image fixe. C'est le **multiplexage**. Tout est expliqué
|
||||
> en détail dans les commentaires de [`matrice_3x3.ino`](matrice_3x3.ino).
|
||||
|
||||
---
|
||||
|
||||
## Sommaire
|
||||
|
||||
1. [Le matériel](#1-le-matériel)
|
||||
2. [Reconnaître les composants](#2-reconnaître-les-composants)
|
||||
3. [Le schéma électrique](#3-le-schéma-électrique)
|
||||
4. [Le montage sur plaque à pastilles](#4-le-montage-sur-plaque-à-pastilles)
|
||||
5. [Souder, étape par étape](#5-souder-étape-par-étape)
|
||||
6. [Relier à l'Arduino](#6-relier-à-larduino)
|
||||
7. [Téléverser le programme et tester](#7-téléverser-le-programme-et-tester)
|
||||
8. [Ça ne marche pas ?](#8-ça-ne-marche-pas-)
|
||||
9. [Le fichier Fritzing](#9-le-fichier-fritzing)
|
||||
|
||||
---
|
||||
|
||||
## 1. Le matériel
|
||||
|
||||
| Quoi | Combien | Remarque |
|
||||
|---|---|---|
|
||||
| Arduino Uno + câble USB | 1 | |
|
||||
| LED RGB 5 mm **à cathode commune** | 9 | 4 pattes ; vérifier « common cathode » à l'achat |
|
||||
| Transistor **BC337** (NPN) | 3 | ou 2N2222 / S8050 : **attention, pattes dans un autre ordre** (voir 2) |
|
||||
| Résistance **220 Ω** | 3 | pour le rouge |
|
||||
| Résistance **150 Ω** | 6 | pour le vert et le bleu |
|
||||
| Résistance **1 kΩ** | 3 | pour les bases des transistors |
|
||||
| Plaque à pastilles (pas 2,54 mm) | 1 | au moins **32 × 34 trous** |
|
||||
| Fil nu étamé (ou chutes de pattes de résistances) | ~1 m | pour les liaisons côté soudures |
|
||||
| Fil isolé fin (monobrin) | ~50 cm | pour les 3 lignes de cathodes |
|
||||
| Fils souples avec embout mâle (« Dupont ») | 13 | vers l'Arduino : 9 rouges/verts/bleus, 3 jaunes, 1 noir |
|
||||
| Fer à souder, étain, pince coupante, pince plate | | |
|
||||
|
||||
---
|
||||
|
||||
## 2. Reconnaître les composants
|
||||
|
||||
### La LED RGB à cathode commune
|
||||
|
||||
Elle contient 3 petites LED (rouge, verte, bleue) qui partagent la même
|
||||
patte « moins » : la **cathode commune**, qui est **la patte la plus longue**.
|
||||
|
||||
```
|
||||
___
|
||||
/ \ Ordre des pattes le plus courant :
|
||||
| |
|
||||
|_____| R K G B
|
||||
| | | | │ │ │ └ bleu
|
||||
| | | | │ │ └──── vert
|
||||
R K | | │ └──────── cathode (la plus longue)
|
||||
G B └──────────── rouge (souvent côté du méplat)
|
||||
```
|
||||
|
||||
> ⚠️ L'ordre peut changer selon le fabricant. **Testez une LED avant de
|
||||
> souder** : cathode au GND de l'Arduino, et chaque autre patte, l'une après
|
||||
> l'autre, au 5V **à travers une résistance de 220 Ω** (jamais sans résistance !).
|
||||
|
||||
### Le transistor BC337
|
||||
|
||||
C'est un **interrupteur électronique** : quand un petit courant entre par la
|
||||
**base (B)**, il laisse passer un gros courant entre le **collecteur (C)** et
|
||||
l'**émetteur (E)**. Ici, chaque transistor allume ou éteint une ligne de LED.
|
||||
|
||||
Face plate vers vous, pattes vers le bas, de gauche à droite : **C – B – E**.
|
||||
|
||||
> ⚠️ Le **2N2222** et le **S8050** ont l'ordre inverse : **E – B – C**.
|
||||
> Si vous les utilisez, tournez-les d'un demi-tour (face plate vers le haut
|
||||
> de la plaque).
|
||||
|
||||
### Les résistances
|
||||
|
||||
Elles freinent le courant pour protéger les LED et l'Arduino. On lit leur
|
||||
valeur avec les anneaux de couleur :
|
||||
|
||||
| Valeur | Anneaux | Rôle |
|
||||
|---|---|---|
|
||||
| 220 Ω | rouge – rouge – marron | LED rouges |
|
||||
| 150 Ω | marron – vert – marron | LED vertes et bleues |
|
||||
| 1 kΩ | marron – noir – rouge | bases des transistors |
|
||||
|
||||
Une résistance n'a pas de sens : on peut la souder dans les deux sens.
|
||||
|
||||
---
|
||||
|
||||
## 3. Le schéma électrique
|
||||
|
||||

|
||||
|
||||
Comment le lire :
|
||||
|
||||
- **À gauche, l'Arduino**. Ses broches **D2 à D10** envoient la couleur,
|
||||
ses broches **D11 à D13** choisissent la ligne allumée.
|
||||
- **Les 9 lignes verticales** : chaque broche D2 à D10 passe par une
|
||||
résistance, puis rejoint **les anodes d'une même couleur dans une même
|
||||
colonne** de la matrice. Par exemple, D2 alimente le rouge des 3 LED de la
|
||||
colonne de gauche.
|
||||
- **Les 3 lignes horizontales** relient **les cathodes d'une même ligne**
|
||||
de LED, puis vont au **collecteur** d'un transistor.
|
||||
- **À droite, les transistors** : leur base est commandée par D11, D12 ou D13
|
||||
(à travers 1 kΩ), et leur émetteur est relié au **GND** (la masse).
|
||||
|
||||
Un pixel s'allume quand **sa ligne est active** (transistor passant) **et**
|
||||
que **sa colonne envoie de la couleur**. C'est le croisement des deux qui
|
||||
choisit le pixel.
|
||||
|
||||
| Broche Arduino | Rôle |
|
||||
|---|---|
|
||||
| D2, D3, D4 | rouge, vert, bleu de la **colonne 0** (gauche) |
|
||||
| D5, D6, D7 | rouge, vert, bleu de la **colonne 1** (milieu) |
|
||||
| D8, D9, D10 | rouge, vert, bleu de la **colonne 2** (droite) |
|
||||
| D11, D12, D13 | **lignes** 0 (haut), 1, 2 (bas), par les transistors T0, T1, T2 |
|
||||
| GND | masse : émetteurs des 3 transistors |
|
||||
|
||||
---
|
||||
|
||||
## 4. Le montage sur plaque à pastilles
|
||||
|
||||
Le plan en haut de cette page montre la plaque **des deux côtés** :
|
||||
|
||||
- **À gauche, côté composants** : ce qu'on voit quand la plaque est posée
|
||||
devant soi, composants vers le haut.
|
||||
- **À droite, côté soudures** : la plaque **retournée**. ⚠️ C'est une image
|
||||
**en miroir** : ce qui était à gauche se retrouve à droite. Les numéros de
|
||||
colonnes aident à s'y retrouver.
|
||||
|
||||
Les trous sont repérés par **colonne** (de 1 à 32, de gauche à droite côté
|
||||
composants) et **ligne** (de 1 à 34, de haut en bas).
|
||||
|
||||
### L'idée du câblage
|
||||
|
||||
- **Les colonnes de couleur** (anodes) sont des **fils nus verticaux**, côté
|
||||
soudures. Comme les 3 LED d'une colonne sont alignées, leurs pattes R
|
||||
tombent dans la même colonne de trous : un fil nu droit les relie toutes,
|
||||
puis rejoint la résistance.
|
||||
- **Les lignes de cathodes** croisent les colonnes : on ne peut pas les faire
|
||||
en fil nu du même côté (ça ferait un court-circuit !). On les fait donc en
|
||||
**fil isolé, côté composants**, qui passe **par-dessus**.
|
||||
- Chaque fil isolé arrive dans **le trou juste à côté** de la patte à
|
||||
relier ; on fait la liaison côté soudures avec une goutte d'étain ou un
|
||||
bout de fil nu.
|
||||
|
||||
### Où va chaque composant
|
||||
|
||||
| Composant | Trous (colonne, ligne) |
|
||||
|---|---|
|
||||
| Résistances 220 Ω (rouge) | col. 3, 9, 15 : lignes 3 → 7 |
|
||||
| Résistances 150 Ω (vert) | col. 5, 11, 17 : lignes 3 → 7 |
|
||||
| Résistances 150 Ω (bleu) | col. 6, 12, 18 : lignes 8 → 12 |
|
||||
| LED de la ligne 0 (haut) | ligne 19 ; colonnes 3-6, 9-12, 15-18 (pattes R K G B) |
|
||||
| LED de la ligne 1 | ligne 25 ; mêmes colonnes |
|
||||
| LED de la ligne 2 (bas) | ligne 31 ; mêmes colonnes |
|
||||
| Transistors T0, T1, T2 | lignes 20, 26, 32 ; colonnes 22 (C), 23 (B), 24 (E) |
|
||||
| Résistances 1 kΩ (bases) | lignes 21, 27, 33 ; colonnes 23 → 27 |
|
||||
|
||||
> **Pourquoi des LED espacées de 6 trous (15 mm) ?** Pour laisser de la place
|
||||
> aux fils et aux doigts. La matrice finale aura un pas de 10 mm. Pour tester
|
||||
> la diffusion de la lumière à 10 mm, on peut refaire une version au pas de
|
||||
> 4 trous (10,16 mm), mais le câblage est beaucoup plus serré.
|
||||
|
||||
---
|
||||
|
||||
## 5. Souder, étape par étape
|
||||
|
||||
**On soude des composants les plus bas aux plus hauts** : la plaque reste
|
||||
stable quand on la retourne.
|
||||
|
||||
1. **Les fils nus** (côté soudures) : les 9 colonnes de couleur, le bus de
|
||||
masse (colonne 31) et les petits ponts. Suivez le plan de droite.
|
||||
2. **Les 12 résistances**, couchées à plat contre la plaque (le long des
|
||||
colonnes pour les 9 résistances de couleur, le long des lignes pour les 1 kΩ).
|
||||
Vérifiez les couleurs : 220 Ω pour le rouge, 150 Ω pour le vert et le bleu,
|
||||
1 kΩ pour les bases.
|
||||
3. **Les 3 transistors**, face plate vers le bas de la plaque.
|
||||
Ne chauffez pas plus de 3 secondes par patte.
|
||||
4. **Les 9 LED** : patte la plus longue (K) en 2e position.
|
||||
**Testez chaque LED avant** (voir partie 2).
|
||||
5. **Les 3 fils isolés** des cathodes (côté composants).
|
||||
6. **Les 13 fils vers l'Arduino** (voir partie 6).
|
||||
|
||||
Conseils de soudure :
|
||||
|
||||
- Le fer chauffe **la pastille et la patte en même temps**, puis on apporte
|
||||
l'étain. Une bonne soudure est brillante et en forme de petit volcan.
|
||||
- Après chaque étape, **vérifiez qu'aucune goutte d'étain ne relie deux
|
||||
pastilles voisines** par erreur, surtout entre les colonnes de couleur
|
||||
voisines (G et B ne sont qu'à un trou d'écart !).
|
||||
- Coupez les pattes qui dépassent **après** avoir soudé. Gardez les chutes :
|
||||
elles font d'excellents fils nus.
|
||||
|
||||
---
|
||||
|
||||
## 6. Relier à l'Arduino
|
||||
|
||||
| Fil | Trou sur la plaque (col., ligne) | Broche Arduino |
|
||||
|---|---|---|
|
||||
| 🔴 rouge colonne 0 | 3, 2 | D2 |
|
||||
| 🟢 vert colonne 0 | 5, 2 | D3 |
|
||||
| 🔵 bleu colonne 0 | 6, 2 | D4 |
|
||||
| 🔴 rouge colonne 1 | 9, 2 | D5 |
|
||||
| 🟢 vert colonne 1 | 11, 2 | D6 |
|
||||
| 🔵 bleu colonne 1 | 12, 2 | D7 |
|
||||
| 🔴 rouge colonne 2 | 15, 2 | D8 |
|
||||
| 🟢 vert colonne 2 | 17, 2 | D9 |
|
||||
| 🔵 bleu colonne 2 | 18, 2 | D10 |
|
||||
| 🟡 ligne 0 | 28, 21 | D11 |
|
||||
| 🟡 ligne 1 | 29, 27 | D12 |
|
||||
| 🟡 ligne 2 | 30, 33 | D13 |
|
||||
| ⚫ masse | 31, 18 | GND (à côté de D13) |
|
||||
|
||||

|
||||
|
||||
> Pas besoin d'alimentation externe : 9 LED à 15 mA, une seule ligne à la fois,
|
||||
> c'est au maximum ~135 mA. Le port USB suffit.
|
||||
|
||||
---
|
||||
|
||||
## 7. Téléverser le programme et tester
|
||||
|
||||
1. Installez l'**IDE Arduino** et la bibliothèque **TimerOne**
|
||||
(Outils → Gérer les bibliothèques… → « TimerOne » → Installer).
|
||||
2. Ouvrez [`matrice_3x3.ino`](matrice_3x3.ino).
|
||||
3. Outils → Type de carte → **Arduino Uno** ; Outils → Port → le bon port.
|
||||
4. **Téléverser**.
|
||||
|
||||
La première animation, `animTestPixels`, allume **chaque pixel l'un après
|
||||
l'autre**, en rouge, puis en vert, puis en bleu, de gauche à droite et de haut
|
||||
en bas. C'est le test de câblage : notez tout pixel qui ne s'allume pas, ou
|
||||
pas au bon endroit, ou pas dans la bonne couleur.
|
||||
|
||||
Ensuite, les animations s'enchaînent : aplats de couleur, chenille, damier,
|
||||
balayages, scintillement. Pour créer les vôtres, lisez les parties 5 et 6 du
|
||||
programme.
|
||||
|
||||
---
|
||||
|
||||
## 8. Ça ne marche pas ?
|
||||
|
||||
| Symptôme | Cause probable | Solution |
|
||||
|---|---|---|
|
||||
| **Rien ne s'allume** | Fil de masse (GND) absent | Vérifier le fil noir et le bus de masse (col. 31) |
|
||||
| | Transistors à l'envers | Vérifier C-B-E (BC337) ou E-B-C (2N2222) |
|
||||
| **Une ligne entière reste éteinte** | Transistor mal soudé ou à l'envers | Vérifier T0, T1 ou T2 et sa résistance de base |
|
||||
| | Fil isolé de cathode mal soudé | Vérifier le pont entre la patte K et le fil |
|
||||
| **Une couleur manque sur toute une colonne** | Résistance ou fil nu de colonne mal soudé | Suivre la colonne côté soudures |
|
||||
| | Mauvais fil sur l'Arduino | Comparer avec le tableau de la partie 6 |
|
||||
| **Un seul pixel ne marche pas** | LED mal soudée, ou grillée | Ressouder, ou tester la LED seule |
|
||||
| **Couleurs mélangées** (rouge à la place du bleu…) | Ordre des pattes de la LED différent | Tester la LED (partie 2) ; corriger dans le code (`pinsCouleur`) |
|
||||
| **Deux couleurs s'allument ensemble** | Pont d'étain entre deux colonnes voisines | Chauffer et retirer l'étain en trop (tresse à dessouder) |
|
||||
| **Légers reflets sur des pixels éteints** (« fantômes ») | Normal si très faible | Le code éteint déjà les lignes avant de changer les couleurs |
|
||||
| **L'image clignote** | `DUREE_LIGNE_US` trop grand | Revenir à 1000 dans le code |
|
||||
| **La petite LED « L » de l'Arduino scintille** | Normal : elle est sur la broche 13 (ligne 2) | Rien à faire |
|
||||
|
||||
---
|
||||
|
||||
## 9. Le fichier Fritzing
|
||||
|
||||
[`matrice_3x3.fzz`](matrice_3x3.fzz) s'ouvre avec
|
||||
[Fritzing](https://fritzing.org) (version 1.0 ou plus récente). Il contient :
|
||||
|
||||
- la vue **Schéma** : le même circuit que la partie 3, avec les symboles
|
||||
de Fritzing ([aperçu](schemas/schema_fritzing.png)) ;
|
||||
- la vue **Platine d'essai** : la plaque à pastilles reliée à l'Arduino.
|
||||
Les fils gris sont les liaisons en fil nu (côté soudures), les fils noirs
|
||||
sur la plaque sont les fils isolés des cathodes.
|
||||
|
||||
La vue **Circuit imprimé** n'est pas utilisée (pièces non placées).
|
||||
|
||||
Les scripts du dossier [`outils/`](outils/) régénèrent le fichier Fritzing,
|
||||
le plan d'implantation et le schéma électrique si on modifie le montage :
|
||||
|
||||
```bash
|
||||
python3 outils/gen_fzz.py matrice_3x3.fzz
|
||||
```
|
||||
|
||||
```bash
|
||||
python3 outils/render_plaque.py schemas/implantation_plaque.svg
|
||||
```
|
||||
|
||||
```bash
|
||||
python3 outils/schema_electrique.py schemas/schema_electrique.svg
|
||||
```
|
||||
Binary file not shown.
@@ -0,0 +1,489 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Génère matrice_3x3.fzz : maquette 3x3 sur plaque à pastilles (vue platine)
|
||||
+ schéma électrique (vue schéma). Coordonnées en px Fritzing (90 dpi)."""
|
||||
import math, sys, zipfile, os
|
||||
from xml.sax.saxutils import escape
|
||||
|
||||
PARTS = "/usr/share/fritzing/fritzing-parts/core/"
|
||||
P = 9.0 # pas 0,1 pouce
|
||||
|
||||
# ---------------------------------------------------------------- modèle
|
||||
instances = [] # dict: id, module, path, title, props, views{view:{...}}
|
||||
idx = [1000]
|
||||
def nid():
|
||||
idx[0] += 1
|
||||
return idx[0]
|
||||
|
||||
conns = {} # (inst_id, view, connector) -> list of (other_id, other_connector, other_layer)
|
||||
def link(view, a, ca, la, b, cb, lb):
|
||||
conns.setdefault((a, view, ca), []).append((b, cb, lb))
|
||||
conns.setdefault((b, view, cb), []).append((a, ca, la))
|
||||
|
||||
# ---------------------------------------------------------------- géométries des pièces
|
||||
LED = dict(module="d4d5af9700923b8a114f57961f29a8a0ColorLEDModuleID",
|
||||
path=PARTS + "led-rgb-4pin-cathode_v5.fzp",
|
||||
legs={"connector0": (1.35, 40.6875), "connector1": (10.35, 40.6875),
|
||||
"connector2": (19.35, 40.6875), "connector3": (28.35, 40.6875)},
|
||||
size=(0.33 * 90, 0.4521 * 90))
|
||||
NPN = dict(module="2244EBEC10e", path=PARTS + "transistor_signal_NPN_TO92_CBE.fzp",
|
||||
# connector2 = C (gauche), connector1 = B, connector0 = E (droite)
|
||||
legs={"connector2": (1.35, 30.101), "connector1": (10.326, 30.101),
|
||||
"connector0": (19.309, 30.101)},
|
||||
size=(0.22954 * 90, 0.3344583 * 90))
|
||||
RES = dict(module="ResistorModuleID", path=PARTS + "resistor.fzp",
|
||||
legs={"connector0": (2.619, 4.5405), "connector1": (36.0063, 4.5405)},
|
||||
size=(0.42917 * 90, 0.0971 * 90))
|
||||
ARDUINO = dict(module="arduino_Uno_Rev3(fix)", path=PARTS + "arduino_Uno_Rev3(fix).fzp",
|
||||
size=(2.94961 * 90, 2.1 * 90))
|
||||
ARD_PIN = { # broche -> (connector id, x, y) dans le repère de la carte (non tournée)
|
||||
"D2": ("connector63", 229.47, 9.0), "D3": ("connector64", 220.46, 9.0),
|
||||
"D4": ("connector65", 211.46, 9.0), "D5": ("connector66", 202.46, 9.0),
|
||||
"D6": ("connector67", 193.46, 9.0), "D7": ("connector68", 184.47, 9.0),
|
||||
"D8": ("connector51", 170.06, 9.0), "D9": ("connector52", 161.06, 9.0),
|
||||
"D10": ("connector53", 152.06, 9.0), "D11": ("connector54", 143.06, 9.0),
|
||||
"D12": ("connector55", 134.06, 9.0), "D13": ("connector56", 125.06, 9.0),
|
||||
"GND": ("connector57", 116.06, 9.0),
|
||||
}
|
||||
|
||||
def rot_matrix(deg, w, h):
|
||||
"""Rotation autour du centre (w/2, h/2), au format QTransform de Fritzing."""
|
||||
cx, cy = w / 2, h / 2
|
||||
a = math.radians(deg)
|
||||
c, s = round(math.cos(a), 9), round(math.sin(a), 9)
|
||||
m11, m12, m21, m22 = c, s, -s, c
|
||||
m31 = cx - (m11 * cx + m21 * cy)
|
||||
m32 = cy - (m12 * cx + m22 * cy)
|
||||
return (m11, m12, m21, m22, m31, m32)
|
||||
|
||||
def apply(m, x, y):
|
||||
m11, m12, m21, m22, m31, m32 = m
|
||||
return (m11 * x + m21 * y + m31, m12 * x + m22 * y + m32)
|
||||
|
||||
def inv_apply(m, u, v):
|
||||
m11, m12, m21, m22, m31, m32 = m
|
||||
u, v = u - m31, v - m32
|
||||
det = m11 * m22 - m12 * m21
|
||||
return ((m22 * u - m21 * v) / det, (-m12 * u + m11 * v) / det)
|
||||
|
||||
# ---------------------------------------------------------------- vue platine (plaque à pastilles)
|
||||
COLS, ROWS = 32, 34
|
||||
BOARD = dict(id=nid(), module=f"{COLS}.{ROWS}PerfboardModuleID",
|
||||
path=":/resources/parts/core/perfboard.fzp", title="Plaque à pastilles",
|
||||
props={"size": f"{COLS}.{ROWS}"}, views={})
|
||||
BOARD["views"]["breadboardView"] = dict(layer="breadboardbreadboard", x=0, y=0, z=1.5)
|
||||
instances.append(BOARD)
|
||||
|
||||
def hole(c, r):
|
||||
return (9 + P * c, 9 + P * r)
|
||||
|
||||
def hole_id(c, r):
|
||||
return f"connector{r * 1000 + c}"
|
||||
|
||||
def add_part(spec, title, bb_pos, bb_rot=0, props=None, sch=None, legs_to=None):
|
||||
"""legs_to : {connector: (col, row)} trous de la plaque où arrivent les pattes."""
|
||||
inst = dict(id=nid(), module=spec["module"], path=spec["path"], title=title,
|
||||
props=props or {}, views={}, legs={})
|
||||
w, h = spec["size"]
|
||||
m = rot_matrix(bb_rot, w, h) if bb_rot else None
|
||||
inst["views"]["breadboardView"] = dict(layer="breadboard", x=bb_pos[0], y=bb_pos[1],
|
||||
z=2.5, m=m)
|
||||
if legs_to:
|
||||
for con, (c, r) in legs_to.items():
|
||||
sx, sy = spec["legs"][con]
|
||||
hx, hy = hole(c, r)
|
||||
u, v = hx - bb_pos[0], hy - bb_pos[1]
|
||||
lx, ly = inv_apply(m, u, v) if m else (u, v)
|
||||
inst["legs"][con] = ((sx, sy), (lx - sx, ly - sy))
|
||||
link("breadboardView", inst["id"], con, "breadboard", BOARD["id"],
|
||||
hole_id(c, r), "breadboardbreadboard")
|
||||
inst["sch"] = sch
|
||||
inst["holes"] = legs_to or {}
|
||||
instances.append(inst)
|
||||
return inst
|
||||
|
||||
def place_on_holes(spec, title, holes, rot=0, lift=1.0, props=None):
|
||||
"""Place la pièce pour que ses pattes soient au-dessus des trous, puis plie les
|
||||
pattes vers les trous. lift = longueur de patte visible, en pas de 0,1 po."""
|
||||
cons = list(holes)
|
||||
# centre des trous visés, centre des départs de pattes
|
||||
hx = sum(hole(*holes[c])[0] for c in cons) / len(cons)
|
||||
hy = sum(hole(*holes[c])[1] for c in cons) / len(cons)
|
||||
sx = sum(spec["legs"][c][0] for c in cons) / len(cons)
|
||||
sy = sum(spec["legs"][c][1] for c in cons) / len(cons)
|
||||
w, h = spec["size"]
|
||||
m = rot_matrix(rot, w, h) if rot else None
|
||||
tx, ty = apply(m, sx, sy) if m else (sx, sy)
|
||||
if rot == 0:
|
||||
pos = (hx - tx, hy - ty - lift * P)
|
||||
else:
|
||||
pos = (hx - tx, hy - ty)
|
||||
return add_part(spec, title, pos, rot, props, legs_to=holes)
|
||||
|
||||
wires = []
|
||||
board_wires = [] # (trou a, trou b, couleur) pour le plan d'implantation
|
||||
def bb_wire(a, b, color, title=None):
|
||||
"""Fil entre deux trous de la plaque (a, b = (col, row))."""
|
||||
(x1, y1), (x2, y2) = hole(*a), hole(*b)
|
||||
board_wires.append((a, b, color))
|
||||
w = dict(id=nid(), title=title or f"Fil{len(wires) + 1}", view="breadboardView",
|
||||
x=x1, y=y1, dx=x2 - x1, dy=y2 - y1, color=color, flags=64,
|
||||
layer="breadboardWire", z=(1.8 if color == NU else 3.5))
|
||||
for k, (c, r) in enumerate((a, b)):
|
||||
link("breadboardView", w["id"], f"connector{k}", "breadboardWire",
|
||||
BOARD["id"], hole_id(c, r), "breadboardbreadboard")
|
||||
wires.append(w)
|
||||
return w
|
||||
|
||||
ARD_POS = (40.0, -280.0)
|
||||
ARD_M = rot_matrix(180, *ARDUINO["size"])
|
||||
ARD = dict(id=nid(), module=ARDUINO["module"], path=ARDUINO["path"], title="Arduino Uno",
|
||||
props={}, views={}, legs={})
|
||||
ARD["views"]["breadboardView"] = dict(layer="breadboardbreadboard", x=ARD_POS[0],
|
||||
y=ARD_POS[1], z=1.6, m=ARD_M)
|
||||
instances.append(ARD)
|
||||
|
||||
def ard_pin_xy(name):
|
||||
_, px, py = ARD_PIN[name]
|
||||
u, v = apply(ARD_M, px, py)
|
||||
return (ARD_POS[0] + u, ARD_POS[1] + v)
|
||||
|
||||
def ard_wire(pin, hole_cr, color):
|
||||
x1, y1 = ard_pin_xy(pin)
|
||||
x2, y2 = hole(*hole_cr)
|
||||
w = dict(id=nid(), title=f"Fil {pin}", view="breadboardView", x=x1, y=y1,
|
||||
dx=x2 - x1, dy=y2 - y1, color=color, flags=64, layer="breadboardWire")
|
||||
link("breadboardView", w["id"], "connector0", "breadboardWire", ARD["id"],
|
||||
ARD_PIN[pin][0], "breadboardbreadboard")
|
||||
link("breadboardView", w["id"], "connector1", "breadboardWire", BOARD["id"],
|
||||
hole_id(*hole_cr), "breadboardbreadboard")
|
||||
wires.append(w)
|
||||
|
||||
# couleurs de fils Fritzing
|
||||
NU = "#a8a8a8" # fil nu étamé, côté soudure
|
||||
ROUGE, VERT, BLEU = "#cc1414", "#47cc79", "#418dd9"
|
||||
NOIR, JAUNE, ORANGE = "#404040", "#ffe24d", "#ff7033"
|
||||
|
||||
# --- implantation -------------------------------------------------------------
|
||||
PAS = 6 # pas entre LED, en trous (6 × 2,54 = 15,24 mm)
|
||||
X0, Y_LED = 2, (18, 24, 30) # LED (ligne r, colonne c) : pattes R K G B
|
||||
COUL = {"R": 0, "G": 2, "B": 3} # décalage de la patte dans la LED
|
||||
PIN_ANODE = {(c, k): f"D{2 + 3 * c + i}" for c in range(3) for i, k in enumerate("RGB")}
|
||||
RES_VAL = {"R": "220Ω", "G": "150Ω", "B": "150Ω"}
|
||||
COUL_FIL = {"R": ROUGE, "G": VERT, "B": BLEU}
|
||||
ard_jobs = [] # (broche, trou, couleur) routés à la fin
|
||||
|
||||
leds = {}
|
||||
for r in range(3):
|
||||
for c in range(3):
|
||||
x = X0 + PAS * c
|
||||
leds[(r, c)] = place_on_holes(
|
||||
LED, f"LED L{r}C{c}",
|
||||
{"connector0": (x, Y_LED[r]), "connector1": (x + 1, Y_LED[r]),
|
||||
"connector2": (x + 2, Y_LED[r]), "connector3": (x + 3, Y_LED[r])},
|
||||
lift=0.6)
|
||||
|
||||
res_anode = {}
|
||||
for c in range(3):
|
||||
for k, off in COUL.items():
|
||||
col = X0 + PAS * c + off
|
||||
top, bot = (2, 6) if k in "RG" else (7, 11)
|
||||
res_anode[(c, k)] = place_on_holes(
|
||||
RES, f"R {k}{c}", {"connector0": (col, top), "connector1": (col, bot)},
|
||||
rot=90, props={"resistance": RES_VAL[k]})
|
||||
bb_wire((col, 1), (col, top), NU)
|
||||
ard_jobs.append((PIN_ANODE[(c, k)], (col, 1), COUL_FIL[k]))
|
||||
bb_wire((col, bot), (col, Y_LED[0]), NU)
|
||||
bb_wire((col, Y_LED[0]), (col, Y_LED[1]), NU)
|
||||
bb_wire((col, Y_LED[1]), (col, Y_LED[2]), NU)
|
||||
|
||||
XC, XB, XE = 21, 22, 23 # pattes C, B, E
|
||||
X_GND = 30
|
||||
trans, res_base = {}, {}
|
||||
for r in range(3):
|
||||
y = Y_LED[r] + 1
|
||||
for c in range(3):
|
||||
xk = X0 + PAS * c + 1
|
||||
bb_wire((xk, Y_LED[r]), (xk, y), NU)
|
||||
bb_wire((X0 + 1, y), (X0 + 1 + PAS, y), NOIR)
|
||||
bb_wire((X0 + 1 + PAS, y), (X0 + 1 + 2 * PAS, y), NOIR)
|
||||
bb_wire((X0 + 1 + 2 * PAS, y), (XC - 1, y), NOIR)
|
||||
bb_wire((XC - 1, y), (XC, y), NU)
|
||||
trans[r] = place_on_holes(NPN, f"T{r} (BC337)",
|
||||
{"connector2": (XC, y), "connector1": (XB, y),
|
||||
"connector0": (XE, y)}, lift=0.6)
|
||||
res_base[r] = place_on_holes(RES, f"Rb{r}",
|
||||
{"connector0": (XB, y + 1), "connector1": (XB + 4, y + 1)},
|
||||
lift=0.0, props={"resistance": "1kΩ"})
|
||||
bb_wire((XB, y), (XB, y + 1), NU)
|
||||
xw = XB + 5 + r
|
||||
bb_wire((XB + 4, y + 1), (xw, y + 1), NU)
|
||||
ard_jobs.append((f"D{11 + r}", (xw, y + 1), JAUNE))
|
||||
bb_wire((XE, y), (X_GND, y), NU)
|
||||
yg = Y_LED[0] - 1
|
||||
bb_wire((X_GND, yg), (X_GND, Y_LED[0] + 1), NU)
|
||||
bb_wire((X_GND, Y_LED[0] + 1), (X_GND, Y_LED[1] + 1), NU)
|
||||
bb_wire((X_GND, Y_LED[1] + 1), (X_GND, Y_LED[2] + 1), NU)
|
||||
ard_jobs.append(("GND", (X_GND, yg), NOIR))
|
||||
|
||||
# routage des fils Arduino : descente, palier horizontal, descente (fils coudés)
|
||||
def chain(points, color, pin, hole_cr):
|
||||
ids = []
|
||||
for i in range(len(points) - 1):
|
||||
(x1, y1), (x2, y2) = points[i], points[i + 1]
|
||||
w = dict(id=nid(), title=f"Fil {pin}", view="breadboardView", x=x1, y=y1,
|
||||
dx=x2 - x1, dy=y2 - y1, color=color, flags=64, layer="breadboardWire")
|
||||
wires.append(w)
|
||||
ids.append(w["id"])
|
||||
link("breadboardView", ids[0], "connector0", "breadboardWire", ARD["id"],
|
||||
ARD_PIN[pin][0], "breadboardbreadboard")
|
||||
link("breadboardView", ids[-1], "connector1", "breadboardWire", BOARD["id"],
|
||||
hole_id(*hole_cr), "breadboardbreadboard")
|
||||
for a_, b_ in zip(ids, ids[1:]):
|
||||
link("breadboardView", a_, "connector1", "breadboardWire", b_, "connector0",
|
||||
"breadboardWire")
|
||||
|
||||
header_y = ard_pin_xy("D2")[1]
|
||||
jobs = [(pin, h, col, ard_pin_xy(pin)[0], hole(*h)[0]) for pin, h, col in ard_jobs]
|
||||
droite = sorted([j for j in jobs if j[4] > j[3] + 0.5], key=lambda j: j[3])
|
||||
gauche = sorted([j for j in jobs if j[4] < j[3] - 0.5], key=lambda j: -j[3])
|
||||
niveau = {}
|
||||
for groupe in (droite, gauche):
|
||||
n = len(groupe)
|
||||
for i, j in enumerate(groupe): # le plus à l'extérieur descend le plus bas
|
||||
niveau[j[0]] = n - i
|
||||
for pin, h, col, xp, xh in jobs:
|
||||
yp = header_y
|
||||
if pin in niveau:
|
||||
yl = header_y + 18 + 9 * niveau[pin]
|
||||
chain([(xp, yp), (xp, yl), (xh, yl), hole(*h)], col, pin, h)
|
||||
else:
|
||||
chain([(xp, yp), hole(*h)], col, pin, h)
|
||||
|
||||
# ---------------------------------------------------------------- vue schéma
|
||||
K = 90 / 96 # px Inkscape -> px Fritzing (SVG en pouces)
|
||||
SCH = { # terminaux dans le repère du symbole (px Fritzing)
|
||||
"LED": {"connector0": (5.126, 35.457), "connector2": (23.172, 35.457),
|
||||
"connector3": (41.297, 35.457), "connector1": (23.225, 1.5)},
|
||||
"NPN": {"connector1": (0.4375, 18.4375), "connector2": (18.4375, 0.4375),
|
||||
"connector0": (18.4375, 36.4375)},
|
||||
"RES": {"connector0": (0.4375, 3.87), "connector1": (36.4375, 3.87)},
|
||||
"RES_SIZE": (0.409722 * 90, 0.086 * 90),
|
||||
}
|
||||
def ard_sch(name):
|
||||
con = ARD_PIN[name][0]
|
||||
if name == "GND":
|
||||
return (72.0, 207.0)
|
||||
n = {"D2": 0, "D3": 1, "D4": 2, "D5": 3, "D6": 4, "D7": 5, "D8": 6, "D9": 7,
|
||||
"D10": 8, "D11": 9, "D12": 10, "D13": 11}[name]
|
||||
return (135.0, 54.0 + 9 * n)
|
||||
|
||||
def set_sch(inst, pos, rot=0, size=None):
|
||||
m = rot_matrix(rot, *size) if rot else None
|
||||
inst["views"]["schematicView"] = dict(layer="schematic", x=pos[0], y=pos[1], z=2.5, m=m)
|
||||
inst["sch_pos"], inst["sch_m"] = pos, m
|
||||
|
||||
def place_sch(inst, table, con, target, rot=0, size=None):
|
||||
"""Place le symbole pour que le terminal `con` tombe sur `target`."""
|
||||
m = rot_matrix(rot, *size) if rot else None
|
||||
lx, ly = SCH[table][con]
|
||||
if m:
|
||||
lx, ly = apply(m, lx, ly)
|
||||
set_sch(inst, (target[0] - lx, target[1] - ly), rot, size)
|
||||
|
||||
def term(inst, table, con):
|
||||
lx, ly = SCH[table][con]
|
||||
if inst.get("sch_m"):
|
||||
lx, ly = apply(inst["sch_m"], lx, ly)
|
||||
return (inst["sch_pos"][0] + lx, inst["sch_pos"][1] + ly)
|
||||
|
||||
ends = {} # point arrondi -> [(wire_id, connector)]
|
||||
def sch_poly(points, start=None, end=None):
|
||||
ids = []
|
||||
for (x1, y1), (x2, y2) in zip(points, points[1:]):
|
||||
w = dict(id=nid(), title="Fil", view="schematicView", x=x1, y=y1, dx=x2 - x1,
|
||||
dy=y2 - y1, color="#404040", flags=128, layer="schematicTrace",
|
||||
mils="9.7222", z=5.5)
|
||||
wires.append(w)
|
||||
ids.append(w["id"])
|
||||
for a_, b_ in zip(ids, ids[1:]):
|
||||
link("schematicView", a_, "connector1", "schematicTrace", b_, "connector0",
|
||||
"schematicTrace")
|
||||
if start:
|
||||
link("schematicView", ids[0], "connector0", "schematicTrace", start[0]["id"],
|
||||
start[1], "schematic")
|
||||
else:
|
||||
ends.setdefault((round(points[0][0], 2), round(points[0][1], 2)), []).append(
|
||||
(ids[0], "connector0"))
|
||||
if end:
|
||||
link("schematicView", ids[-1], "connector1", "schematicTrace", end[0]["id"],
|
||||
end[1], "schematic")
|
||||
else:
|
||||
ends.setdefault((round(points[-1][0], 2), round(points[-1][1], 2)), []).append(
|
||||
(ids[-1], "connector1"))
|
||||
|
||||
A_POS = (0.0, 450.0)
|
||||
ARD["views"]["schematicView"] = dict(layer="schematic", x=A_POS[0], y=A_POS[1], z=2.5)
|
||||
def apin(name):
|
||||
x, y = ard_sch(name)
|
||||
return (A_POS[0] + x, A_POS[1] + y)
|
||||
ARDP = lambda name: (ARD, ARD_PIN[name][0])
|
||||
|
||||
MX, MY, PASS = 225.0, 60.0, 90.0
|
||||
BUS_OFF = {"R": -27.0, "G": -18.0, "B": -9.0}
|
||||
PROF = {"R": 9.0, "G": 18.0, "B": 27.0}
|
||||
LEDCON = {"R": "connector0", "G": "connector2", "B": "connector3"}
|
||||
RES_TOP = {"R": 315.0, "G": 360.0, "B": 405.0}
|
||||
for (r, c), led in leds.items():
|
||||
set_sch(led, (MX + PASS * c, MY + PASS * r))
|
||||
for c in range(3):
|
||||
for k in "RGB":
|
||||
bx = MX + PASS * c + BUS_OFF[k]
|
||||
res = res_anode[(c, k)]
|
||||
# patte 1 (connector0) côté Arduino, en bas ; patte 2 côté LED, en haut
|
||||
place_sch(res, "RES", "connector1", (bx, RES_TOP[k]), rot=270, size=SCH["RES_SIZE"])
|
||||
top, bot = term(res, "RES", "connector1"), term(res, "RES", "connector0")
|
||||
pin = PIN_ANODE[(c, k)]
|
||||
px, py = apin(pin)
|
||||
sch_poly([(px, py), (bx, py), bot], start=ARDP(pin), end=(res, "connector0"))
|
||||
# bus : résistance -> jonctions des lignes 2, 1, 0
|
||||
pts = [top] + [(bx, MY + PASS * r + 35.457 + PROF[k]) for r in (2, 1, 0)]
|
||||
for i, (a_, b_) in enumerate(zip(pts, pts[1:])):
|
||||
sch_poly([a_, b_], start=(res, "connector1") if i == 0 else None)
|
||||
for r in range(3):
|
||||
led = leds[(r, c)]
|
||||
tx, ty = term(led, "LED", LEDCON[k])
|
||||
jy = MY + PASS * r + 35.457 + PROF[k]
|
||||
sch_poly([(tx, ty), (tx, jy), (bx, jy)], start=(led, LEDCON[k]))
|
||||
|
||||
XT = 545.0
|
||||
XV = {0: 462.0, 1: 471.0, 2: 480.0}
|
||||
X_GND_S, Y_GND_S = XT + 45.0, 690.0
|
||||
for r in range(3):
|
||||
yrl = MY + PASS * r + 1.5 - 9.0
|
||||
ks = [term(leds[(r, c)], "LED", "connector1") for c in range(3)]
|
||||
for c in range(3):
|
||||
sch_poly([ks[c], (ks[c][0], yrl)], start=(leds[(r, c)], "connector1"))
|
||||
t = trans[r]
|
||||
set_sch(t, (XT, yrl + 18.0 - 0.4375))
|
||||
cpt, bpt, ept = term(t, "NPN", "connector2"), term(t, "NPN", "connector1"), term(t, "NPN", "connector0")
|
||||
sch_poly([(ks[0][0], yrl), (ks[1][0], yrl)])
|
||||
sch_poly([(ks[1][0], yrl), (ks[2][0], yrl)])
|
||||
sch_poly([(ks[2][0], yrl), (cpt[0], yrl), cpt], end=(t, "connector2"))
|
||||
rb = res_base[r]
|
||||
# patte 1 (connector0) côté base, patte 2 côté Arduino
|
||||
place_sch(rb, "RES", "connector0", (bpt[0] - 9.0, bpt[1]), rot=180, size=SCH["RES_SIZE"])
|
||||
rbase, rard = term(rb, "RES", "connector0"), term(rb, "RES", "connector1")
|
||||
sch_poly([rbase, bpt], start=(rb, "connector0"), end=(t, "connector1"))
|
||||
pin = f"D{11 + r}"
|
||||
px, py = apin(pin)
|
||||
sch_poly([(px, py), (XV[r], py), (XV[r], rard[1]), rard], start=ARDP(pin), end=(rb, "connector1"))
|
||||
sch_poly([ept, (X_GND_S, ept[1])], start=(t, "connector0"))
|
||||
yE = ept[1]
|
||||
if r == 0:
|
||||
y_e0 = yE
|
||||
else:
|
||||
sch_poly([(X_GND_S, prev_e), (X_GND_S, yE)])
|
||||
prev_e = yE
|
||||
gx, gy = apin("GND")
|
||||
sch_poly([(X_GND_S, prev_e), (X_GND_S, Y_GND_S), (gx, Y_GND_S), (gx, gy)], end=ARDP("GND"))
|
||||
|
||||
for pt, lst in ends.items():
|
||||
for i in range(len(lst)):
|
||||
for j in range(i + 1, len(lst)):
|
||||
link("schematicView", lst[i][0], lst[i][1], "schematicTrace", lst[j][0],
|
||||
lst[j][1], "schematicTrace")
|
||||
|
||||
# ---------------------------------------------------------------- écriture XML
|
||||
def fmt(v):
|
||||
return f"{v:.4f}".rstrip("0").rstrip(".") if isinstance(v, float) else str(v)
|
||||
|
||||
def connects_xml(inst_id, view, con, indent):
|
||||
out = []
|
||||
for (oid, ocon, olayer) in conns.get((inst_id, view, con), []):
|
||||
out.append(f'{indent}<connect connectorId="{ocon}" modelIndex="{oid}" layer="{olayer}"/>')
|
||||
return "\n".join(out)
|
||||
|
||||
def part_xml(inst):
|
||||
L = []
|
||||
L.append(f'<instance moduleIdRef="{escape(inst["module"])}" modelIndex="{inst["id"]}" '
|
||||
f'path="{escape(inst["path"])}">')
|
||||
for k, v in inst["props"].items():
|
||||
L.append(f' <property name="{k}" value="{escape(v)}"/>')
|
||||
L.append(f' <title>{escape(inst["title"])}</title>')
|
||||
L.append(' <views>')
|
||||
for view, g in inst["views"].items():
|
||||
L.append(f' <{view} layer="{g["layer"]}">')
|
||||
if g.get("m"):
|
||||
m11, m12, m21, m22, m31, m32 = g["m"]
|
||||
L.append(f' <geometry z="{g["z"]}" x="{fmt(g["x"])}" y="{fmt(g["y"])}">')
|
||||
L.append(f' <transform m11="{fmt(m11)}" m12="{fmt(m12)}" m13="0" '
|
||||
f'm21="{fmt(m21)}" m22="{fmt(m22)}" m23="0" m31="{fmt(m31)}" '
|
||||
f'm32="{fmt(m32)}" m33="1"/>')
|
||||
L.append(' </geometry>')
|
||||
else:
|
||||
L.append(f' <geometry z="{g["z"]}" x="{fmt(g["x"])}" y="{fmt(g["y"])}"/>')
|
||||
cons = sorted({c for (i, v, c) in conns if i == inst["id"] and v == view}
|
||||
| (set(inst.get("legs", {})) if view == "breadboardView" else set()))
|
||||
if cons:
|
||||
L.append(' <connectors>')
|
||||
for con in cons:
|
||||
L.append(f' <connector connectorId="{con}" layer="{g["layer"]}">')
|
||||
if view == "breadboardView" and con in inst.get("legs", {}):
|
||||
(sx, sy), (lx, ly) = inst["legs"][con]
|
||||
L.append(f' <geometry x="{fmt(sx)}" y="{fmt(sy)}"/>')
|
||||
L.append(' <leg><point x="0" y="0"/><bezier/>'
|
||||
f'<point x="{fmt(lx)}" y="{fmt(ly)}"/><bezier/></leg>')
|
||||
else:
|
||||
L.append(' <geometry x="0" y="0"/>')
|
||||
L.append(' <connects>')
|
||||
L.append(connects_xml(inst["id"], view, con, " "))
|
||||
L.append(' </connects>')
|
||||
L.append(' </connector>')
|
||||
L.append(' </connectors>')
|
||||
L.append(f' </{view}>')
|
||||
L.append(' </views>')
|
||||
L.append('</instance>')
|
||||
return "\n".join(L)
|
||||
|
||||
def wire_xml(w):
|
||||
view, layer = w["view"], w["layer"]
|
||||
L = [f'<instance moduleIdRef="WireModuleID" modelIndex="{w["id"]}" '
|
||||
f'path=":/resources/parts/core/wire.fzp">',
|
||||
f' <title>{escape(w["title"])}</title>', ' <views>',
|
||||
f' <{view} layer="{layer}">',
|
||||
f' <geometry z="{w.get("z", 3.5)}" x="{fmt(w["x"])}" y="{fmt(w["y"])}" x1="0" y1="0" '
|
||||
f'x2="{fmt(w["dx"])}" y2="{fmt(w["dy"])}" wireFlags="{w["flags"]}"/>',
|
||||
f' <wireExtras mils="{w.get("mils", "22.2222")}" color="{w["color"]}" '
|
||||
f'opacity="1" banded="0"/>',
|
||||
' <connectors>']
|
||||
for k in ("connector0", "connector1"):
|
||||
L.append(f' <connector connectorId="{k}" layer="{layer}">')
|
||||
L.append(' <geometry x="0" y="0"/>')
|
||||
L.append(' <connects>')
|
||||
L.append(connects_xml(w["id"], view, k, " "))
|
||||
L.append(' </connects>')
|
||||
L.append(' </connector>')
|
||||
L += [' </connectors>', f' </{view}>', ' </views>', '</instance>']
|
||||
return "\n".join(L)
|
||||
|
||||
def build(out_path, ino_path=None):
|
||||
head = '''<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module fritzingVersion="1.0.5" icon=".png">
|
||||
<views>
|
||||
<view name="breadboardView" backgroundColor="#ffffff" gridSize="0.1in" showGrid="1" alignToGrid="1" viewFromBelow="0" colorWiresByLength="0"/>
|
||||
<view name="schematicView" backgroundColor="#ffffff" gridSize="0.1in" showGrid="1" alignToGrid="1" viewFromBelow="0"/>
|
||||
<view name="pcbView" backgroundColor="#333333" gridSize="0.05in" showGrid="1" alignToGrid="1" viewFromBelow="0"/>
|
||||
</views>
|
||||
<instances>
|
||||
'''
|
||||
body = "\n".join(part_xml(i) for i in instances) + "\n" + "\n".join(wire_xml(w) for w in wires)
|
||||
xml = head + body + "\n</instances>\n</module>\n"
|
||||
name = os.path.splitext(os.path.basename(out_path))[0]
|
||||
with zipfile.ZipFile(out_path, "w", zipfile.ZIP_DEFLATED) as z:
|
||||
z.writestr(name + ".fz", xml)
|
||||
if ino_path:
|
||||
z.write(ino_path, os.path.basename(ino_path))
|
||||
|
||||
if __name__ == "__main__" and sys.argv[1] != "/dev/null":
|
||||
build(sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else None)
|
||||
print(len(instances), "pièces,", len(wires), "fils")
|
||||
@@ -0,0 +1,200 @@
|
||||
#!/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'<text x="{x:.1f}" y="{y:.1f}" font-size="{size}" text-anchor="{anchor}" '
|
||||
f'fill="{fill}" font-weight="{weight}"{tr}>{s}</text>')
|
||||
|
||||
A(f'<svg xmlns="http://www.w3.org/2000/svg" width="{LARG}" height="{HAUT}" '
|
||||
f'viewBox="0 0 {LARG} {HAUT}" font-family="Helvetica, Arial, sans-serif">')
|
||||
A('<title>Implantation de la matrice 3x3 sur plaque à pastilles</title>')
|
||||
A(f'<rect width="{LARG}" height="{HAUT}" fill="#ffffff"/>')
|
||||
|
||||
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'<rect x="{x0 - 8}" y="{MARGE_Y - 8}" width="{COLS * PX + 16}" height="{ROWS * PX + 16}" '
|
||||
f'rx="6" fill="#e3c58f" stroke="#b8975c"/>')
|
||||
# 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'<circle cx="{x:.1f}" cy="{y:.1f}" r="4.6" fill="#c9a063"/>'
|
||||
f'<circle cx="{x:.1f}" cy="{y:.1f}" r="1.8" fill="#fff8ec"/>')
|
||||
|
||||
# ---------------------------------------------------------------- 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'<circle cx="{cx:.1f}" cy="{cy:.1f}" r="{PX * 1.0:.1f}" fill="#ffffff" '
|
||||
f'fill-opacity="0.85" stroke="#555" stroke-width="1.5"/>')
|
||||
for (c, r), lettre, coul in zip(hs, "RKGB", ("#cc1414", "#222", "#2a9d3a", "#2f6fc4")):
|
||||
x, y = xy(c, r, pan)
|
||||
A(f'<circle cx="{x:.1f}" cy="{y:.1f}" r="2.6" fill="{coul}"/>')
|
||||
txt(x, y - 6, lettre, 9, fill=coul, weight="bold")
|
||||
else:
|
||||
A(f'<circle cx="{cx:.1f}" cy="{cy:.1f}" r="{PX * 1.0:.1f}" fill="none" '
|
||||
f'stroke="#9a7b4a" stroke-dasharray="3 3"/>')
|
||||
|
||||
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'<line x1="{xa:.1f}" y1="{ya:.1f}" x2="{xb:.1f}" y2="{yb:.1f}" stroke="#8c8c8c" '
|
||||
f'stroke-width="2"/>')
|
||||
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'<rect x="{mx - w / 2:.1f}" y="{my - h / 2:.1f}" width="{w:.1f}" height="{h:.1f}" '
|
||||
f'rx="3" {style}/>')
|
||||
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'<path d="{d}" fill="#2b2b2b" fill-opacity="0.9"/>')
|
||||
for con, lettre in (("connector2", "C"), ("connector1", "B"), ("connector0", "E")):
|
||||
x, yy = xy(*hs[con], pan)
|
||||
A(f'<circle cx="{x:.1f}" cy="{yy:.1f}" r="2.6" fill="#ddd"/>')
|
||||
txt(x, yy - 6, lettre, 9, fill="#fff", weight="bold")
|
||||
txt(cx, y - R + 2, nom, 10, fill="#222", weight="bold")
|
||||
else:
|
||||
A(f'<path d="{d}" fill="none" stroke="#9a7b4a" stroke-dasharray="3 3"/>')
|
||||
|
||||
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'<line x1="{xa:.1f}" y1="{ya:.1f}" x2="{xb:.1f}" y2="{yb:.1f}" stroke="{coul}" '
|
||||
f'stroke-width="5" stroke-linecap="round"/>')
|
||||
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'<circle cx="{x:.1f}" cy="{y:.1f}" r="5.5" fill="none" stroke="{coul}" stroke-width="3"/>')
|
||||
if r <= 2: # entrées en haut de la plaque : étiquette verticale au-dessus
|
||||
A(f'<line x1="{x:.1f}" y1="{y - 6:.1f}" x2="{x:.1f}" y2="{MARGE_Y - 26:.1f}" '
|
||||
f'stroke="{coul}" stroke-width="2"/>')
|
||||
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'<line x1="{xa:.1f}" y1="{ya:.1f}" x2="{xb:.1f}" y2="{yb:.1f}" stroke="#7d7d7d" '
|
||||
f'stroke-width="4" stroke-linecap="round"/>')
|
||||
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'<circle cx="{x:.1f}" cy="{y:.1f}" r="4.4" fill="#bfbfbf" stroke="#6f6f6f"/>')
|
||||
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'<circle cx="{x:.1f}" cy="{y:.1f}" r="2.2" fill="{coul}"/>')
|
||||
for pin, h, coul in ard_jobs:
|
||||
x, y = xy(*h, 1)
|
||||
A(f'<circle cx="{x:.1f}" cy="{y:.1f}" r="2.2" fill="{coul}"/>')
|
||||
|
||||
# ---------------------------------------------------------------- légende
|
||||
ly = MARGE_Y + ROWS * PX + 56
|
||||
txt(MARGE_X, ly, "Légende", 15, "start", "#222", "bold")
|
||||
items = [
|
||||
('<circle cx="{x}" cy="{y}" r="9" fill="#fff" stroke="#555" stroke-width="1.5"/>',
|
||||
"LED RGB vue de dessus : pattes R, K (cathode, la plus longue), G, B"),
|
||||
('<rect x="{xm}" y="{ym}" width="22" height="9" rx="3" fill="#e8d3a8" stroke="#a88a52"/>',
|
||||
"Résistance (valeur en ohms : 220, 150, 1k = 1000)"),
|
||||
('<path d="M{xl} {y4} A11 11 0 0 1 {xr} {y4} Z" fill="#2b2b2b"/>',
|
||||
"Transistor BC337, face plate vers le bas : pattes C, B, E de gauche à droite"),
|
||||
('<line x1="{xl}" y1="{y}" x2="{xr}" y2="{y}" stroke="#404040" stroke-width="5" stroke-linecap="round"/>',
|
||||
"Fil isolé, côté composants (cathodes des lignes)"),
|
||||
('<line x1="{xl}" y1="{y}" x2="{xr}" y2="{y}" stroke="#7d7d7d" stroke-width="4" stroke-linecap="round"/>',
|
||||
"Fil nu (ou patte repliée), côté soudures"),
|
||||
('<circle cx="{x}" cy="{y}" r="5.5" fill="none" stroke="#cc1414" stroke-width="3"/>',
|
||||
"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("</svg>")
|
||||
with open(OUT, "w") as f:
|
||||
f.write("\n".join(out))
|
||||
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Dessine schemas/schema_electrique.svg : schéma de la maquette 3 x 3,
|
||||
avec les symboles normalisés (résistances rectangulaires) et des fils colorés.
|
||||
Usage : python3 outils/schema_electrique.py schemas/schema_electrique.svg"""
|
||||
import sys
|
||||
|
||||
ROUGE, VERT, BLEU = "#d62828", "#2a9d3a", "#2f6fc4"
|
||||
TEINTE = {ROUGE: "#fbd5d5", VERT: "#d3f0d8", BLEU: "#d6e3f7"}
|
||||
LIGNE, BASE, MASSE, TEXTE = "#3a3a3a", "#c98a00", "#222222", "#333333"
|
||||
|
||||
LX = [170, 370, 570] # x de la diode rouge de chaque colonne
|
||||
LY = [330, 480, 630] # y des anodes de chaque ligne
|
||||
DX = 48 # écart entre les diodes R, G, B d'une LED
|
||||
COULEURS = [("R", ROUGE, "220 Ω"), ("G", VERT, "150 Ω"), ("B", BLEU, "150 Ω")]
|
||||
XT = 790 # centre des transistors
|
||||
XD = {0: 900, 1: 930, 2: 960} # descentes D11, D12, D13
|
||||
X_GND = 1000
|
||||
Y_PIN = 170 # bas du bloc Arduino
|
||||
|
||||
out = []
|
||||
A = out.append
|
||||
|
||||
def ligne(x1, y1, x2, y2, c, w=2.2):
|
||||
A(f'<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" stroke="{c}" stroke-width="{w}" '
|
||||
f'stroke-linecap="round"/>')
|
||||
|
||||
def chemin(d, c, w=2.2):
|
||||
A(f'<path d="{d}" fill="none" stroke="{c}" stroke-width="{w}" stroke-linecap="round" '
|
||||
f'stroke-linejoin="round"/>')
|
||||
|
||||
def point(x, y, c):
|
||||
A(f'<circle cx="{x}" cy="{y}" r="4" fill="{c}"/>')
|
||||
|
||||
def texte(x, y, s, taille=13, ancre="middle", c=TEXTE, gras=False, rot=None, italique=False):
|
||||
tr = f' transform="rotate({rot} {x} {y})"' if rot else ""
|
||||
A(f'<text x="{x}" y="{y}" font-size="{taille}" text-anchor="{ancre}" fill="{c}"'
|
||||
f'{" font-weight=\"bold\"" if gras else ""}{" font-style=\"italic\"" if italique else ""}'
|
||||
f'{tr}>{s}</text>')
|
||||
|
||||
def resistance_v(x, y1, y2, c, valeur):
|
||||
"""Résistance verticale entre y1 et y2 (rectangle de 50 px au milieu)."""
|
||||
m = (y1 + y2) / 2
|
||||
ligne(x, y1, x, m - 25, c)
|
||||
ligne(x, m + 25, x, y2, c)
|
||||
A(f'<rect x="{x - 7}" y="{m - 25}" width="14" height="50" rx="2" fill="#fff" '
|
||||
f'stroke="{c}" stroke-width="2.2"/>')
|
||||
texte(x + 19, m, valeur, 12, c=c, rot=-90)
|
||||
|
||||
def resistance_h(x1, x2, y, c, valeur):
|
||||
m = (x1 + x2) / 2
|
||||
ligne(x1, y, m - 25, y, c)
|
||||
ligne(m + 25, y, x2, y, c)
|
||||
A(f'<rect x="{m - 25}" y="{y - 7}" width="50" height="14" rx="2" fill="#fff" '
|
||||
f'stroke="{c}" stroke-width="2.2"/>')
|
||||
texte(m, y - 13, valeur, 12, c=c)
|
||||
|
||||
def diode(x, ya, c):
|
||||
"""Diode verticale : anode en haut (ya), cathode en bas (ya + 32)."""
|
||||
ligne(x, ya, x, ya + 8, c)
|
||||
A(f'<path d="M{x - 9} {ya + 8} L{x + 9} {ya + 8} L{x} {ya + 22} Z" fill="{TEINTE[c]}" '
|
||||
f'stroke="{c}" stroke-width="2" stroke-linejoin="round"/>')
|
||||
ligne(x - 9, ya + 22, x + 9, ya + 22, c, 2.4)
|
||||
ligne(x, ya + 22, x, ya + 32, LIGNE)
|
||||
for dy in (0, 7): # lumière émise
|
||||
x1, y1, x2, y2 = x + 9, ya + 15 + dy, x + 18, ya + 6 + dy
|
||||
ligne(x1, y1, x2, y2, c, 1.4)
|
||||
A(f'<path d="M{x2} {y2} l-5 1 l4 4 Z" fill="{c}"/>')
|
||||
|
||||
def masse(x, y):
|
||||
ligne(x - 11, y, x + 11, y, MASSE, 2.4)
|
||||
ligne(x - 7, y + 5, x + 7, y + 5, MASSE, 2.4)
|
||||
ligne(x - 3, y + 10, x + 3, y + 10, MASSE, 2.4)
|
||||
|
||||
def transistor(r, yt):
|
||||
"""NPN dessiné en miroir : base à droite, collecteur en haut à gauche,
|
||||
émetteur en bas à gauche (vers la masse)."""
|
||||
xb = XT + 8
|
||||
A(f'<circle cx="{XT - 1}" cy="{yt}" r="25" fill="#fafafa" stroke="{TEXTE}" stroke-width="1.6"/>')
|
||||
ligne(xb, yt - 13, xb, yt + 13, TEXTE, 3)
|
||||
ligne(xb, yt - 6, XT - 12, yt - 20, LIGNE) # collecteur
|
||||
ligne(xb, yt + 6, XT - 12, yt + 20, MASSE) # émetteur
|
||||
A(f'<path d="M{XT - 12} {yt + 20} l3 -9 l5 7 Z" fill="{MASSE}"/>')
|
||||
ligne(xb, yt, XT + 40, yt, BASE) # base
|
||||
texte(XT - 44, yt - 2, f"T{r}", 14, gras=True)
|
||||
texte(XT - 44, yt + 14, "BC337", 11, c="#666")
|
||||
texte(XT + 22, yt + 18, "B", 10, c="#888")
|
||||
texte(XT - 22, yt - 26, "C", 10, c="#888")
|
||||
texte(XT - 26, yt + 28, "E", 10, c="#888")
|
||||
|
||||
W, H = 1080, 970
|
||||
A(f'<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" viewBox="0 0 {W} {H}" '
|
||||
f'font-family="Helvetica, Arial, sans-serif">')
|
||||
A('<title>Schéma électrique de la maquette 3 x 3</title>')
|
||||
A(f'<rect width="{W}" height="{H}" fill="#ffffff"/>')
|
||||
texte(40, 38, "Maquette 3 × 3 : schéma électrique", 22, "start", "#111", True)
|
||||
texte(40, 60, "9 LED RGB à cathode commune, allumées ligne par ligne (multiplexage)",
|
||||
14, "start", "#666")
|
||||
|
||||
# ---------------------------------------------------------------- Arduino
|
||||
A(f'<rect x="100" y="80" width="930" height="{Y_PIN - 80}" rx="10" fill="#e8f4f5" '
|
||||
f'stroke="#00878f" stroke-width="2.4"/>')
|
||||
texte(565, 112, "Arduino Uno", 20, gras=True, c="#00666d")
|
||||
texte(565, 132, "alimenté par le câble USB", 12, c="#4d8f94")
|
||||
broches = {}
|
||||
for c in range(3):
|
||||
for k, (_, coul, _) in enumerate(COULEURS):
|
||||
broches[f"D{2 + 3 * c + k}"] = (LX[c] + DX * k - 22, coul)
|
||||
for r in range(3):
|
||||
broches[f"D{11 + r}"] = (XD[r], BASE)
|
||||
broches["GND"] = (X_GND, MASSE)
|
||||
for nom, (x, coul) in broches.items():
|
||||
ligne(x, Y_PIN, x, Y_PIN + 20, coul)
|
||||
texte(x, Y_PIN - 10, nom, 12, gras=True, c=coul if coul != BASE else "#9a6a00")
|
||||
masse(X_GND, Y_PIN + 20)
|
||||
|
||||
# ---------------------------------------------------------------- colonnes (anodes)
|
||||
for c in range(3):
|
||||
for k, (_, coul, val) in enumerate(COULEURS):
|
||||
xb = LX[c] + DX * k - 22
|
||||
resistance_v(xb, Y_PIN + 20, 265, coul, val)
|
||||
y_fin = LY[2] - 12
|
||||
ligne(xb, 265, xb, y_fin, coul)
|
||||
for r in range(3):
|
||||
xd, ys = LX[c] + DX * k, LY[r] - 12
|
||||
chemin(f"M{xb} {ys} H{xd} V{LY[r]}", coul)
|
||||
if r < 2:
|
||||
point(xb, ys, coul)
|
||||
texte(LX[c] + DX, LY[2] + 100, f"colonne {c}", 14, c="#555", gras=True)
|
||||
|
||||
# ---------------------------------------------------------------- LED
|
||||
for r in range(3):
|
||||
for c in range(3):
|
||||
x0 = LX[c]
|
||||
A(f'<rect x="{x0 - 14}" y="{LY[r] - 4}" width="{2 * DX + 28}" height="40" rx="8" '
|
||||
f'fill="#f2f2f2"/>')
|
||||
texte(x0 + DX + 2, LY[r] - 22, f"L{r}C{c}", 11, c="#888", gras=True)
|
||||
for r in range(3):
|
||||
for c in range(3):
|
||||
for k, (_, coul, _) in enumerate(COULEURS):
|
||||
diode(LX[c] + DX * k, LY[r], coul)
|
||||
|
||||
# ---------------------------------------------------------------- lignes (cathodes)
|
||||
bus_x = sorted(LX[c] + DX * k - 22 for c in range(3) for k in range(3))
|
||||
for r in range(3):
|
||||
y = LY[r] + 60
|
||||
for c in range(3):
|
||||
for k in range(3):
|
||||
xd = LX[c] + DX * k
|
||||
ligne(xd, LY[r] + 32, xd, y, LIGNE)
|
||||
if not (c == 0 and k == 0):
|
||||
point(xd, y, LIGNE)
|
||||
# ligne horizontale avec des « ponts » là où elle croise une colonne
|
||||
d = f"M{LX[0]} {y}"
|
||||
if r < 2:
|
||||
for xb in bus_x:
|
||||
if LX[0] < xb < XT - 12:
|
||||
d += f" H{xb - 6} a6 6 0 0 1 12 0"
|
||||
d += f" H{XT - 12} V{y + 40 - 20}"
|
||||
chemin(d, LIGNE)
|
||||
texte(XT - 56, y - 8, f"ligne {r}", 13, "end", c="#555", gras=True)
|
||||
yt = y + 40
|
||||
transistor(r, yt)
|
||||
ligne(XT - 12, yt + 20, XT - 12, yt + 36, MASSE)
|
||||
masse(XT - 12, yt + 36)
|
||||
resistance_h(XT + 40, XD[r], yt, BASE, "1 kΩ")
|
||||
ligne(XD[r], yt, XD[r], Y_PIN + 20, BASE)
|
||||
|
||||
# ---------------------------------------------------------------- légende
|
||||
ly = 840
|
||||
A(f'<rect x="40" y="{ly - 26}" width="{W - 80}" height="136" rx="10" fill="#fafafa" stroke="#e2e2e2"/>')
|
||||
texte(60, ly, "Légende", 15, "start", "#111", True)
|
||||
items = [
|
||||
(lambda x, y: (ligne(x, y, x + 30, y, ROUGE), ligne(x + 34, y, x + 64, y, VERT),
|
||||
ligne(x + 68, y, x + 98, y, BLEU)),
|
||||
"colonnes : anodes R, G, B (D2 à D10)"),
|
||||
(lambda x, y: ligne(x, y, x + 98, y, LIGNE), "lignes : cathodes communes"),
|
||||
(lambda x, y: ligne(x, y, x + 98, y, BASE), "commande des lignes (D11 à D13)"),
|
||||
(lambda x, y: masse(x + 49, y - 6), "masse (GND) : symboles tous reliés"),
|
||||
(lambda x, y: point(x + 49, y, LIGNE), "point = fils connectés"),
|
||||
(lambda x, y: chemin(f"M{x} {y} H{x + 43} a6 6 0 0 1 12 0 H{x + 98}", LIGNE),
|
||||
"pont = croisement sans contact"),
|
||||
]
|
||||
for i, (dessin, legende) in enumerate(items):
|
||||
col, lig = i % 3, i // 3
|
||||
x, y = (60, 400, 700)[col], ly + 30 + lig * 32
|
||||
dessin(x, y)
|
||||
texte(x + 110, y + 4, legende, 12, "start")
|
||||
texte(60, ly + 98, "Un pixel s'allume quand sa ligne est active (D11, D12 ou D13 à HIGH : le "
|
||||
"transistor relie les cathodes à la masse) et que sa couleur l'est aussi (D2 à D10).",
|
||||
12, "start", "#555", italique=True)
|
||||
A("</svg>")
|
||||
|
||||
with open(sys.argv[1], "w") as f:
|
||||
f.write("\n".join(out))
|
||||
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 272 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 578 KiB |
@@ -0,0 +1,501 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1080" height="970" viewBox="0 0 1080 970" font-family="Helvetica, Arial, sans-serif">
|
||||
<title>Schéma électrique de la maquette 3 x 3</title>
|
||||
<rect width="1080" height="970" fill="#ffffff"/>
|
||||
<text x="40" y="38" font-size="22" text-anchor="start" fill="#111" font-weight="bold">Maquette 3 × 3 : schéma électrique</text>
|
||||
<text x="40" y="60" font-size="14" text-anchor="start" fill="#666">9 LED RGB à cathode commune, allumées ligne par ligne (multiplexage)</text>
|
||||
<rect x="100" y="80" width="930" height="90" rx="10" fill="#e8f4f5" stroke="#00878f" stroke-width="2.4"/>
|
||||
<text x="565" y="112" font-size="20" text-anchor="middle" fill="#00666d" font-weight="bold">Arduino Uno</text>
|
||||
<text x="565" y="132" font-size="12" text-anchor="middle" fill="#4d8f94">alimenté par le câble USB</text>
|
||||
<line x1="148" y1="170" x2="148" y2="190" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="148" y="160" font-size="12" text-anchor="middle" fill="#d62828" font-weight="bold">D2</text>
|
||||
<line x1="196" y1="170" x2="196" y2="190" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="196" y="160" font-size="12" text-anchor="middle" fill="#2a9d3a" font-weight="bold">D3</text>
|
||||
<line x1="244" y1="170" x2="244" y2="190" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="244" y="160" font-size="12" text-anchor="middle" fill="#2f6fc4" font-weight="bold">D4</text>
|
||||
<line x1="348" y1="170" x2="348" y2="190" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="348" y="160" font-size="12" text-anchor="middle" fill="#d62828" font-weight="bold">D5</text>
|
||||
<line x1="396" y1="170" x2="396" y2="190" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="396" y="160" font-size="12" text-anchor="middle" fill="#2a9d3a" font-weight="bold">D6</text>
|
||||
<line x1="444" y1="170" x2="444" y2="190" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="444" y="160" font-size="12" text-anchor="middle" fill="#2f6fc4" font-weight="bold">D7</text>
|
||||
<line x1="548" y1="170" x2="548" y2="190" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="548" y="160" font-size="12" text-anchor="middle" fill="#d62828" font-weight="bold">D8</text>
|
||||
<line x1="596" y1="170" x2="596" y2="190" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="596" y="160" font-size="12" text-anchor="middle" fill="#2a9d3a" font-weight="bold">D9</text>
|
||||
<line x1="644" y1="170" x2="644" y2="190" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="644" y="160" font-size="12" text-anchor="middle" fill="#2f6fc4" font-weight="bold">D10</text>
|
||||
<line x1="900" y1="170" x2="900" y2="190" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="900" y="160" font-size="12" text-anchor="middle" fill="#9a6a00" font-weight="bold">D11</text>
|
||||
<line x1="930" y1="170" x2="930" y2="190" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="930" y="160" font-size="12" text-anchor="middle" fill="#9a6a00" font-weight="bold">D12</text>
|
||||
<line x1="960" y1="170" x2="960" y2="190" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="960" y="160" font-size="12" text-anchor="middle" fill="#9a6a00" font-weight="bold">D13</text>
|
||||
<line x1="1000" y1="170" x2="1000" y2="190" stroke="#222222" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="1000" y="160" font-size="12" text-anchor="middle" fill="#222222" font-weight="bold">GND</text>
|
||||
<line x1="989" y1="190" x2="1011" y2="190" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="993" y1="195" x2="1007" y2="195" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="997" y1="200" x2="1003" y2="200" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="148" y1="190" x2="148" y2="202.5" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="148" y1="252.5" x2="148" y2="265" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="141" y="202.5" width="14" height="50" rx="2" fill="#fff" stroke="#d62828" stroke-width="2.2"/>
|
||||
<text x="167" y="227.5" font-size="12" text-anchor="middle" fill="#d62828" transform="rotate(-90 167 227.5)">220 Ω</text>
|
||||
<line x1="148" y1="265" x2="148" y2="618" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M148 318 H170 V330" fill="none" stroke="#d62828" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="148" cy="318" r="4" fill="#d62828"/>
|
||||
<path d="M148 468 H170 V480" fill="none" stroke="#d62828" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="148" cy="468" r="4" fill="#d62828"/>
|
||||
<path d="M148 618 H170 V630" fill="none" stroke="#d62828" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<line x1="196" y1="190" x2="196" y2="202.5" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="196" y1="252.5" x2="196" y2="265" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="189" y="202.5" width="14" height="50" rx="2" fill="#fff" stroke="#2a9d3a" stroke-width="2.2"/>
|
||||
<text x="215" y="227.5" font-size="12" text-anchor="middle" fill="#2a9d3a" transform="rotate(-90 215 227.5)">150 Ω</text>
|
||||
<line x1="196" y1="265" x2="196" y2="618" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M196 318 H218 V330" fill="none" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="196" cy="318" r="4" fill="#2a9d3a"/>
|
||||
<path d="M196 468 H218 V480" fill="none" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="196" cy="468" r="4" fill="#2a9d3a"/>
|
||||
<path d="M196 618 H218 V630" fill="none" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<line x1="244" y1="190" x2="244" y2="202.5" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="244" y1="252.5" x2="244" y2="265" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="237" y="202.5" width="14" height="50" rx="2" fill="#fff" stroke="#2f6fc4" stroke-width="2.2"/>
|
||||
<text x="263" y="227.5" font-size="12" text-anchor="middle" fill="#2f6fc4" transform="rotate(-90 263 227.5)">150 Ω</text>
|
||||
<line x1="244" y1="265" x2="244" y2="618" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M244 318 H266 V330" fill="none" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="244" cy="318" r="4" fill="#2f6fc4"/>
|
||||
<path d="M244 468 H266 V480" fill="none" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="244" cy="468" r="4" fill="#2f6fc4"/>
|
||||
<path d="M244 618 H266 V630" fill="none" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="218" y="730" font-size="14" text-anchor="middle" fill="#555" font-weight="bold">colonne 0</text>
|
||||
<line x1="348" y1="190" x2="348" y2="202.5" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="348" y1="252.5" x2="348" y2="265" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="341" y="202.5" width="14" height="50" rx="2" fill="#fff" stroke="#d62828" stroke-width="2.2"/>
|
||||
<text x="367" y="227.5" font-size="12" text-anchor="middle" fill="#d62828" transform="rotate(-90 367 227.5)">220 Ω</text>
|
||||
<line x1="348" y1="265" x2="348" y2="618" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M348 318 H370 V330" fill="none" stroke="#d62828" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="348" cy="318" r="4" fill="#d62828"/>
|
||||
<path d="M348 468 H370 V480" fill="none" stroke="#d62828" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="348" cy="468" r="4" fill="#d62828"/>
|
||||
<path d="M348 618 H370 V630" fill="none" stroke="#d62828" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<line x1="396" y1="190" x2="396" y2="202.5" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="396" y1="252.5" x2="396" y2="265" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="389" y="202.5" width="14" height="50" rx="2" fill="#fff" stroke="#2a9d3a" stroke-width="2.2"/>
|
||||
<text x="415" y="227.5" font-size="12" text-anchor="middle" fill="#2a9d3a" transform="rotate(-90 415 227.5)">150 Ω</text>
|
||||
<line x1="396" y1="265" x2="396" y2="618" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M396 318 H418 V330" fill="none" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="396" cy="318" r="4" fill="#2a9d3a"/>
|
||||
<path d="M396 468 H418 V480" fill="none" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="396" cy="468" r="4" fill="#2a9d3a"/>
|
||||
<path d="M396 618 H418 V630" fill="none" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<line x1="444" y1="190" x2="444" y2="202.5" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="444" y1="252.5" x2="444" y2="265" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="437" y="202.5" width="14" height="50" rx="2" fill="#fff" stroke="#2f6fc4" stroke-width="2.2"/>
|
||||
<text x="463" y="227.5" font-size="12" text-anchor="middle" fill="#2f6fc4" transform="rotate(-90 463 227.5)">150 Ω</text>
|
||||
<line x1="444" y1="265" x2="444" y2="618" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M444 318 H466 V330" fill="none" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="444" cy="318" r="4" fill="#2f6fc4"/>
|
||||
<path d="M444 468 H466 V480" fill="none" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="444" cy="468" r="4" fill="#2f6fc4"/>
|
||||
<path d="M444 618 H466 V630" fill="none" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="418" y="730" font-size="14" text-anchor="middle" fill="#555" font-weight="bold">colonne 1</text>
|
||||
<line x1="548" y1="190" x2="548" y2="202.5" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="548" y1="252.5" x2="548" y2="265" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="541" y="202.5" width="14" height="50" rx="2" fill="#fff" stroke="#d62828" stroke-width="2.2"/>
|
||||
<text x="567" y="227.5" font-size="12" text-anchor="middle" fill="#d62828" transform="rotate(-90 567 227.5)">220 Ω</text>
|
||||
<line x1="548" y1="265" x2="548" y2="618" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M548 318 H570 V330" fill="none" stroke="#d62828" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="548" cy="318" r="4" fill="#d62828"/>
|
||||
<path d="M548 468 H570 V480" fill="none" stroke="#d62828" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="548" cy="468" r="4" fill="#d62828"/>
|
||||
<path d="M548 618 H570 V630" fill="none" stroke="#d62828" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<line x1="596" y1="190" x2="596" y2="202.5" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="596" y1="252.5" x2="596" y2="265" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="589" y="202.5" width="14" height="50" rx="2" fill="#fff" stroke="#2a9d3a" stroke-width="2.2"/>
|
||||
<text x="615" y="227.5" font-size="12" text-anchor="middle" fill="#2a9d3a" transform="rotate(-90 615 227.5)">150 Ω</text>
|
||||
<line x1="596" y1="265" x2="596" y2="618" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M596 318 H618 V330" fill="none" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="596" cy="318" r="4" fill="#2a9d3a"/>
|
||||
<path d="M596 468 H618 V480" fill="none" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="596" cy="468" r="4" fill="#2a9d3a"/>
|
||||
<path d="M596 618 H618 V630" fill="none" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<line x1="644" y1="190" x2="644" y2="202.5" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="644" y1="252.5" x2="644" y2="265" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="637" y="202.5" width="14" height="50" rx="2" fill="#fff" stroke="#2f6fc4" stroke-width="2.2"/>
|
||||
<text x="663" y="227.5" font-size="12" text-anchor="middle" fill="#2f6fc4" transform="rotate(-90 663 227.5)">150 Ω</text>
|
||||
<line x1="644" y1="265" x2="644" y2="618" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M644 318 H666 V330" fill="none" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="644" cy="318" r="4" fill="#2f6fc4"/>
|
||||
<path d="M644 468 H666 V480" fill="none" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="644" cy="468" r="4" fill="#2f6fc4"/>
|
||||
<path d="M644 618 H666 V630" fill="none" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="618" y="730" font-size="14" text-anchor="middle" fill="#555" font-weight="bold">colonne 2</text>
|
||||
<rect x="156" y="326" width="124" height="40" rx="8" fill="#f2f2f2"/>
|
||||
<text x="220" y="308" font-size="11" text-anchor="middle" fill="#888" font-weight="bold">L0C0</text>
|
||||
<rect x="356" y="326" width="124" height="40" rx="8" fill="#f2f2f2"/>
|
||||
<text x="420" y="308" font-size="11" text-anchor="middle" fill="#888" font-weight="bold">L0C1</text>
|
||||
<rect x="556" y="326" width="124" height="40" rx="8" fill="#f2f2f2"/>
|
||||
<text x="620" y="308" font-size="11" text-anchor="middle" fill="#888" font-weight="bold">L0C2</text>
|
||||
<rect x="156" y="476" width="124" height="40" rx="8" fill="#f2f2f2"/>
|
||||
<text x="220" y="458" font-size="11" text-anchor="middle" fill="#888" font-weight="bold">L1C0</text>
|
||||
<rect x="356" y="476" width="124" height="40" rx="8" fill="#f2f2f2"/>
|
||||
<text x="420" y="458" font-size="11" text-anchor="middle" fill="#888" font-weight="bold">L1C1</text>
|
||||
<rect x="556" y="476" width="124" height="40" rx="8" fill="#f2f2f2"/>
|
||||
<text x="620" y="458" font-size="11" text-anchor="middle" fill="#888" font-weight="bold">L1C2</text>
|
||||
<rect x="156" y="626" width="124" height="40" rx="8" fill="#f2f2f2"/>
|
||||
<text x="220" y="608" font-size="11" text-anchor="middle" fill="#888" font-weight="bold">L2C0</text>
|
||||
<rect x="356" y="626" width="124" height="40" rx="8" fill="#f2f2f2"/>
|
||||
<text x="420" y="608" font-size="11" text-anchor="middle" fill="#888" font-weight="bold">L2C1</text>
|
||||
<rect x="556" y="626" width="124" height="40" rx="8" fill="#f2f2f2"/>
|
||||
<text x="620" y="608" font-size="11" text-anchor="middle" fill="#888" font-weight="bold">L2C2</text>
|
||||
<line x1="170" y1="330" x2="170" y2="338" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M161 338 L179 338 L170 352 Z" fill="#fbd5d5" stroke="#d62828" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="161" y1="352" x2="179" y2="352" stroke="#d62828" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="170" y1="352" x2="170" y2="362" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="179" y1="345" x2="188" y2="336" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M188 336 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="179" y1="352" x2="188" y2="343" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M188 343 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="218" y1="330" x2="218" y2="338" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M209 338 L227 338 L218 352 Z" fill="#d3f0d8" stroke="#2a9d3a" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="209" y1="352" x2="227" y2="352" stroke="#2a9d3a" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="218" y1="352" x2="218" y2="362" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="227" y1="345" x2="236" y2="336" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M236 336 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="227" y1="352" x2="236" y2="343" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M236 343 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="266" y1="330" x2="266" y2="338" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M257 338 L275 338 L266 352 Z" fill="#d6e3f7" stroke="#2f6fc4" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="257" y1="352" x2="275" y2="352" stroke="#2f6fc4" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="266" y1="352" x2="266" y2="362" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="275" y1="345" x2="284" y2="336" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M284 336 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="275" y1="352" x2="284" y2="343" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M284 343 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="370" y1="330" x2="370" y2="338" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M361 338 L379 338 L370 352 Z" fill="#fbd5d5" stroke="#d62828" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="361" y1="352" x2="379" y2="352" stroke="#d62828" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="370" y1="352" x2="370" y2="362" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="379" y1="345" x2="388" y2="336" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M388 336 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="379" y1="352" x2="388" y2="343" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M388 343 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="418" y1="330" x2="418" y2="338" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M409 338 L427 338 L418 352 Z" fill="#d3f0d8" stroke="#2a9d3a" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="409" y1="352" x2="427" y2="352" stroke="#2a9d3a" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="418" y1="352" x2="418" y2="362" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="427" y1="345" x2="436" y2="336" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M436 336 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="427" y1="352" x2="436" y2="343" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M436 343 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="466" y1="330" x2="466" y2="338" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M457 338 L475 338 L466 352 Z" fill="#d6e3f7" stroke="#2f6fc4" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="457" y1="352" x2="475" y2="352" stroke="#2f6fc4" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="466" y1="352" x2="466" y2="362" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="475" y1="345" x2="484" y2="336" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M484 336 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="475" y1="352" x2="484" y2="343" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M484 343 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="570" y1="330" x2="570" y2="338" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M561 338 L579 338 L570 352 Z" fill="#fbd5d5" stroke="#d62828" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="561" y1="352" x2="579" y2="352" stroke="#d62828" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="570" y1="352" x2="570" y2="362" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="579" y1="345" x2="588" y2="336" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M588 336 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="579" y1="352" x2="588" y2="343" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M588 343 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="618" y1="330" x2="618" y2="338" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M609 338 L627 338 L618 352 Z" fill="#d3f0d8" stroke="#2a9d3a" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="609" y1="352" x2="627" y2="352" stroke="#2a9d3a" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="618" y1="352" x2="618" y2="362" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="627" y1="345" x2="636" y2="336" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M636 336 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="627" y1="352" x2="636" y2="343" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M636 343 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="666" y1="330" x2="666" y2="338" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M657 338 L675 338 L666 352 Z" fill="#d6e3f7" stroke="#2f6fc4" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="657" y1="352" x2="675" y2="352" stroke="#2f6fc4" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="666" y1="352" x2="666" y2="362" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="675" y1="345" x2="684" y2="336" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M684 336 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="675" y1="352" x2="684" y2="343" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M684 343 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="170" y1="480" x2="170" y2="488" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M161 488 L179 488 L170 502 Z" fill="#fbd5d5" stroke="#d62828" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="161" y1="502" x2="179" y2="502" stroke="#d62828" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="170" y1="502" x2="170" y2="512" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="179" y1="495" x2="188" y2="486" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M188 486 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="179" y1="502" x2="188" y2="493" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M188 493 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="218" y1="480" x2="218" y2="488" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M209 488 L227 488 L218 502 Z" fill="#d3f0d8" stroke="#2a9d3a" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="209" y1="502" x2="227" y2="502" stroke="#2a9d3a" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="218" y1="502" x2="218" y2="512" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="227" y1="495" x2="236" y2="486" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M236 486 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="227" y1="502" x2="236" y2="493" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M236 493 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="266" y1="480" x2="266" y2="488" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M257 488 L275 488 L266 502 Z" fill="#d6e3f7" stroke="#2f6fc4" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="257" y1="502" x2="275" y2="502" stroke="#2f6fc4" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="266" y1="502" x2="266" y2="512" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="275" y1="495" x2="284" y2="486" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M284 486 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="275" y1="502" x2="284" y2="493" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M284 493 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="370" y1="480" x2="370" y2="488" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M361 488 L379 488 L370 502 Z" fill="#fbd5d5" stroke="#d62828" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="361" y1="502" x2="379" y2="502" stroke="#d62828" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="370" y1="502" x2="370" y2="512" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="379" y1="495" x2="388" y2="486" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M388 486 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="379" y1="502" x2="388" y2="493" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M388 493 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="418" y1="480" x2="418" y2="488" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M409 488 L427 488 L418 502 Z" fill="#d3f0d8" stroke="#2a9d3a" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="409" y1="502" x2="427" y2="502" stroke="#2a9d3a" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="418" y1="502" x2="418" y2="512" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="427" y1="495" x2="436" y2="486" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M436 486 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="427" y1="502" x2="436" y2="493" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M436 493 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="466" y1="480" x2="466" y2="488" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M457 488 L475 488 L466 502 Z" fill="#d6e3f7" stroke="#2f6fc4" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="457" y1="502" x2="475" y2="502" stroke="#2f6fc4" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="466" y1="502" x2="466" y2="512" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="475" y1="495" x2="484" y2="486" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M484 486 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="475" y1="502" x2="484" y2="493" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M484 493 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="570" y1="480" x2="570" y2="488" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M561 488 L579 488 L570 502 Z" fill="#fbd5d5" stroke="#d62828" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="561" y1="502" x2="579" y2="502" stroke="#d62828" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="570" y1="502" x2="570" y2="512" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="579" y1="495" x2="588" y2="486" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M588 486 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="579" y1="502" x2="588" y2="493" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M588 493 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="618" y1="480" x2="618" y2="488" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M609 488 L627 488 L618 502 Z" fill="#d3f0d8" stroke="#2a9d3a" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="609" y1="502" x2="627" y2="502" stroke="#2a9d3a" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="618" y1="502" x2="618" y2="512" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="627" y1="495" x2="636" y2="486" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M636 486 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="627" y1="502" x2="636" y2="493" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M636 493 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="666" y1="480" x2="666" y2="488" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M657 488 L675 488 L666 502 Z" fill="#d6e3f7" stroke="#2f6fc4" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="657" y1="502" x2="675" y2="502" stroke="#2f6fc4" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="666" y1="502" x2="666" y2="512" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="675" y1="495" x2="684" y2="486" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M684 486 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="675" y1="502" x2="684" y2="493" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M684 493 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="170" y1="630" x2="170" y2="638" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M161 638 L179 638 L170 652 Z" fill="#fbd5d5" stroke="#d62828" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="161" y1="652" x2="179" y2="652" stroke="#d62828" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="170" y1="652" x2="170" y2="662" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="179" y1="645" x2="188" y2="636" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M188 636 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="179" y1="652" x2="188" y2="643" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M188 643 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="218" y1="630" x2="218" y2="638" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M209 638 L227 638 L218 652 Z" fill="#d3f0d8" stroke="#2a9d3a" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="209" y1="652" x2="227" y2="652" stroke="#2a9d3a" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="218" y1="652" x2="218" y2="662" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="227" y1="645" x2="236" y2="636" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M236 636 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="227" y1="652" x2="236" y2="643" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M236 643 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="266" y1="630" x2="266" y2="638" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M257 638 L275 638 L266 652 Z" fill="#d6e3f7" stroke="#2f6fc4" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="257" y1="652" x2="275" y2="652" stroke="#2f6fc4" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="266" y1="652" x2="266" y2="662" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="275" y1="645" x2="284" y2="636" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M284 636 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="275" y1="652" x2="284" y2="643" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M284 643 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="370" y1="630" x2="370" y2="638" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M361 638 L379 638 L370 652 Z" fill="#fbd5d5" stroke="#d62828" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="361" y1="652" x2="379" y2="652" stroke="#d62828" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="370" y1="652" x2="370" y2="662" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="379" y1="645" x2="388" y2="636" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M388 636 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="379" y1="652" x2="388" y2="643" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M388 643 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="418" y1="630" x2="418" y2="638" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M409 638 L427 638 L418 652 Z" fill="#d3f0d8" stroke="#2a9d3a" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="409" y1="652" x2="427" y2="652" stroke="#2a9d3a" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="418" y1="652" x2="418" y2="662" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="427" y1="645" x2="436" y2="636" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M436 636 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="427" y1="652" x2="436" y2="643" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M436 643 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="466" y1="630" x2="466" y2="638" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M457 638 L475 638 L466 652 Z" fill="#d6e3f7" stroke="#2f6fc4" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="457" y1="652" x2="475" y2="652" stroke="#2f6fc4" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="466" y1="652" x2="466" y2="662" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="475" y1="645" x2="484" y2="636" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M484 636 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="475" y1="652" x2="484" y2="643" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M484 643 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="570" y1="630" x2="570" y2="638" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M561 638 L579 638 L570 652 Z" fill="#fbd5d5" stroke="#d62828" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="561" y1="652" x2="579" y2="652" stroke="#d62828" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="570" y1="652" x2="570" y2="662" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="579" y1="645" x2="588" y2="636" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M588 636 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="579" y1="652" x2="588" y2="643" stroke="#d62828" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M588 643 l-5 1 l4 4 Z" fill="#d62828"/>
|
||||
<line x1="618" y1="630" x2="618" y2="638" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M609 638 L627 638 L618 652 Z" fill="#d3f0d8" stroke="#2a9d3a" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="609" y1="652" x2="627" y2="652" stroke="#2a9d3a" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="618" y1="652" x2="618" y2="662" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="627" y1="645" x2="636" y2="636" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M636 636 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="627" y1="652" x2="636" y2="643" stroke="#2a9d3a" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M636 643 l-5 1 l4 4 Z" fill="#2a9d3a"/>
|
||||
<line x1="666" y1="630" x2="666" y2="638" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M657 638 L675 638 L666 652 Z" fill="#d6e3f7" stroke="#2f6fc4" stroke-width="2" stroke-linejoin="round"/>
|
||||
<line x1="657" y1="652" x2="675" y2="652" stroke="#2f6fc4" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="666" y1="652" x2="666" y2="662" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="675" y1="645" x2="684" y2="636" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M684 636 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="675" y1="652" x2="684" y2="643" stroke="#2f6fc4" stroke-width="1.4" stroke-linecap="round"/>
|
||||
<path d="M684 643 l-5 1 l4 4 Z" fill="#2f6fc4"/>
|
||||
<line x1="170" y1="362" x2="170" y2="390" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="218" y1="362" x2="218" y2="390" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="218" cy="390" r="4" fill="#3a3a3a"/>
|
||||
<line x1="266" y1="362" x2="266" y2="390" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="266" cy="390" r="4" fill="#3a3a3a"/>
|
||||
<line x1="370" y1="362" x2="370" y2="390" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="370" cy="390" r="4" fill="#3a3a3a"/>
|
||||
<line x1="418" y1="362" x2="418" y2="390" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="418" cy="390" r="4" fill="#3a3a3a"/>
|
||||
<line x1="466" y1="362" x2="466" y2="390" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="466" cy="390" r="4" fill="#3a3a3a"/>
|
||||
<line x1="570" y1="362" x2="570" y2="390" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="570" cy="390" r="4" fill="#3a3a3a"/>
|
||||
<line x1="618" y1="362" x2="618" y2="390" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="618" cy="390" r="4" fill="#3a3a3a"/>
|
||||
<line x1="666" y1="362" x2="666" y2="390" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="666" cy="390" r="4" fill="#3a3a3a"/>
|
||||
<path d="M170 390 H190 a6 6 0 0 1 12 0 H238 a6 6 0 0 1 12 0 H342 a6 6 0 0 1 12 0 H390 a6 6 0 0 1 12 0 H438 a6 6 0 0 1 12 0 H542 a6 6 0 0 1 12 0 H590 a6 6 0 0 1 12 0 H638 a6 6 0 0 1 12 0 H778 V410" fill="none" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="734" y="382" font-size="13" text-anchor="end" fill="#555" font-weight="bold">ligne 0</text>
|
||||
<circle cx="789" cy="430" r="25" fill="#fafafa" stroke="#333333" stroke-width="1.6"/>
|
||||
<line x1="798" y1="417" x2="798" y2="443" stroke="#333333" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="798" y1="424" x2="778" y2="410" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="798" y1="436" x2="778" y2="450" stroke="#222222" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M778 450 l3 -9 l5 7 Z" fill="#222222"/>
|
||||
<line x1="798" y1="430" x2="830" y2="430" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="746" y="428" font-size="14" text-anchor="middle" fill="#333333" font-weight="bold">T0</text>
|
||||
<text x="746" y="444" font-size="11" text-anchor="middle" fill="#666">BC337</text>
|
||||
<text x="812" y="448" font-size="10" text-anchor="middle" fill="#888">B</text>
|
||||
<text x="768" y="404" font-size="10" text-anchor="middle" fill="#888">C</text>
|
||||
<text x="764" y="458" font-size="10" text-anchor="middle" fill="#888">E</text>
|
||||
<line x1="778" y1="450" x2="778" y2="466" stroke="#222222" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="767" y1="466" x2="789" y2="466" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="771" y1="471" x2="785" y2="471" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="775" y1="476" x2="781" y2="476" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="830" y1="430" x2="840.0" y2="430" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="890.0" y1="430" x2="900" y2="430" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="840.0" y="423" width="50" height="14" rx="2" fill="#fff" stroke="#c98a00" stroke-width="2.2"/>
|
||||
<text x="865.0" y="417" font-size="12" text-anchor="middle" fill="#c98a00">1 kΩ</text>
|
||||
<line x1="900" y1="430" x2="900" y2="190" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="170" y1="512" x2="170" y2="540" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="218" y1="512" x2="218" y2="540" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="218" cy="540" r="4" fill="#3a3a3a"/>
|
||||
<line x1="266" y1="512" x2="266" y2="540" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="266" cy="540" r="4" fill="#3a3a3a"/>
|
||||
<line x1="370" y1="512" x2="370" y2="540" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="370" cy="540" r="4" fill="#3a3a3a"/>
|
||||
<line x1="418" y1="512" x2="418" y2="540" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="418" cy="540" r="4" fill="#3a3a3a"/>
|
||||
<line x1="466" y1="512" x2="466" y2="540" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="466" cy="540" r="4" fill="#3a3a3a"/>
|
||||
<line x1="570" y1="512" x2="570" y2="540" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="570" cy="540" r="4" fill="#3a3a3a"/>
|
||||
<line x1="618" y1="512" x2="618" y2="540" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="618" cy="540" r="4" fill="#3a3a3a"/>
|
||||
<line x1="666" y1="512" x2="666" y2="540" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="666" cy="540" r="4" fill="#3a3a3a"/>
|
||||
<path d="M170 540 H190 a6 6 0 0 1 12 0 H238 a6 6 0 0 1 12 0 H342 a6 6 0 0 1 12 0 H390 a6 6 0 0 1 12 0 H438 a6 6 0 0 1 12 0 H542 a6 6 0 0 1 12 0 H590 a6 6 0 0 1 12 0 H638 a6 6 0 0 1 12 0 H778 V560" fill="none" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="734" y="532" font-size="13" text-anchor="end" fill="#555" font-weight="bold">ligne 1</text>
|
||||
<circle cx="789" cy="580" r="25" fill="#fafafa" stroke="#333333" stroke-width="1.6"/>
|
||||
<line x1="798" y1="567" x2="798" y2="593" stroke="#333333" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="798" y1="574" x2="778" y2="560" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="798" y1="586" x2="778" y2="600" stroke="#222222" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M778 600 l3 -9 l5 7 Z" fill="#222222"/>
|
||||
<line x1="798" y1="580" x2="830" y2="580" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="746" y="578" font-size="14" text-anchor="middle" fill="#333333" font-weight="bold">T1</text>
|
||||
<text x="746" y="594" font-size="11" text-anchor="middle" fill="#666">BC337</text>
|
||||
<text x="812" y="598" font-size="10" text-anchor="middle" fill="#888">B</text>
|
||||
<text x="768" y="554" font-size="10" text-anchor="middle" fill="#888">C</text>
|
||||
<text x="764" y="608" font-size="10" text-anchor="middle" fill="#888">E</text>
|
||||
<line x1="778" y1="600" x2="778" y2="616" stroke="#222222" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="767" y1="616" x2="789" y2="616" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="771" y1="621" x2="785" y2="621" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="775" y1="626" x2="781" y2="626" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="830" y1="580" x2="855.0" y2="580" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="905.0" y1="580" x2="930" y2="580" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="855.0" y="573" width="50" height="14" rx="2" fill="#fff" stroke="#c98a00" stroke-width="2.2"/>
|
||||
<text x="880.0" y="567" font-size="12" text-anchor="middle" fill="#c98a00">1 kΩ</text>
|
||||
<line x1="930" y1="580" x2="930" y2="190" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="170" y1="662" x2="170" y2="690" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="218" y1="662" x2="218" y2="690" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="218" cy="690" r="4" fill="#3a3a3a"/>
|
||||
<line x1="266" y1="662" x2="266" y2="690" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="266" cy="690" r="4" fill="#3a3a3a"/>
|
||||
<line x1="370" y1="662" x2="370" y2="690" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="370" cy="690" r="4" fill="#3a3a3a"/>
|
||||
<line x1="418" y1="662" x2="418" y2="690" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="418" cy="690" r="4" fill="#3a3a3a"/>
|
||||
<line x1="466" y1="662" x2="466" y2="690" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="466" cy="690" r="4" fill="#3a3a3a"/>
|
||||
<line x1="570" y1="662" x2="570" y2="690" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="570" cy="690" r="4" fill="#3a3a3a"/>
|
||||
<line x1="618" y1="662" x2="618" y2="690" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="618" cy="690" r="4" fill="#3a3a3a"/>
|
||||
<line x1="666" y1="662" x2="666" y2="690" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<circle cx="666" cy="690" r="4" fill="#3a3a3a"/>
|
||||
<path d="M170 690 H778 V710" fill="none" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="734" y="682" font-size="13" text-anchor="end" fill="#555" font-weight="bold">ligne 2</text>
|
||||
<circle cx="789" cy="730" r="25" fill="#fafafa" stroke="#333333" stroke-width="1.6"/>
|
||||
<line x1="798" y1="717" x2="798" y2="743" stroke="#333333" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="798" y1="724" x2="778" y2="710" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="798" y1="736" x2="778" y2="750" stroke="#222222" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<path d="M778 750 l3 -9 l5 7 Z" fill="#222222"/>
|
||||
<line x1="798" y1="730" x2="830" y2="730" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="746" y="728" font-size="14" text-anchor="middle" fill="#333333" font-weight="bold">T2</text>
|
||||
<text x="746" y="744" font-size="11" text-anchor="middle" fill="#666">BC337</text>
|
||||
<text x="812" y="748" font-size="10" text-anchor="middle" fill="#888">B</text>
|
||||
<text x="768" y="704" font-size="10" text-anchor="middle" fill="#888">C</text>
|
||||
<text x="764" y="758" font-size="10" text-anchor="middle" fill="#888">E</text>
|
||||
<line x1="778" y1="750" x2="778" y2="766" stroke="#222222" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="767" y1="766" x2="789" y2="766" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="771" y1="771" x2="785" y2="771" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="775" y1="776" x2="781" y2="776" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="830" y1="730" x2="870.0" y2="730" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="920.0" y1="730" x2="960" y2="730" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="870.0" y="723" width="50" height="14" rx="2" fill="#fff" stroke="#c98a00" stroke-width="2.2"/>
|
||||
<text x="895.0" y="717" font-size="12" text-anchor="middle" fill="#c98a00">1 kΩ</text>
|
||||
<line x1="960" y1="730" x2="960" y2="190" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<rect x="40" y="814" width="1000" height="136" rx="10" fill="#fafafa" stroke="#e2e2e2"/>
|
||||
<text x="60" y="840" font-size="15" text-anchor="start" fill="#111" font-weight="bold">Légende</text>
|
||||
<line x1="60" y1="870" x2="90" y2="870" stroke="#d62828" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="94" y1="870" x2="124" y2="870" stroke="#2a9d3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<line x1="128" y1="870" x2="158" y2="870" stroke="#2f6fc4" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="170" y="874" font-size="12" text-anchor="start" fill="#333333">colonnes : anodes R, G, B (D2 à D10)</text>
|
||||
<line x1="400" y1="870" x2="498" y2="870" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="510" y="874" font-size="12" text-anchor="start" fill="#333333">lignes : cathodes communes</text>
|
||||
<line x1="700" y1="870" x2="798" y2="870" stroke="#c98a00" stroke-width="2.2" stroke-linecap="round"/>
|
||||
<text x="810" y="874" font-size="12" text-anchor="start" fill="#333333">commande des lignes (D11 à D13)</text>
|
||||
<line x1="98" y1="896" x2="120" y2="896" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="102" y1="901" x2="116" y2="901" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<line x1="106" y1="906" x2="112" y2="906" stroke="#222222" stroke-width="2.4" stroke-linecap="round"/>
|
||||
<text x="170" y="906" font-size="12" text-anchor="start" fill="#333333">masse (GND) : symboles tous reliés</text>
|
||||
<circle cx="449" cy="902" r="4" fill="#3a3a3a"/>
|
||||
<text x="510" y="906" font-size="12" text-anchor="start" fill="#333333">point = fils connectés</text>
|
||||
<path d="M700 902 H743 a6 6 0 0 1 12 0 H798" fill="none" stroke="#3a3a3a" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<text x="810" y="906" font-size="12" text-anchor="start" fill="#333333">pont = croisement sans contact</text>
|
||||
<text x="60" y="938" font-size="12" text-anchor="start" fill="#555" font-style="italic">Un pixel s'allume quand sa ligne est active (D11, D12 ou D13 à HIGH : le transistor relie les cathodes à la masse) et que sa couleur l'est aussi (D2 à D10).</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 46 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 119 KiB |
Reference in New Issue
Block a user