Files
vitrine-pixels/8x32 PI/CODER_EN_PYTHON.md
T
2026-10-08 15:25:14 +02:00

266 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Coder ses animations en Python
Krita sert à **dessiner** des animations image par image. Le code sert à les
**calculer** : du hasard, des mouvements continus, des formules, des
réactions à un capteur… des choses très longues, voire impossibles, à
dessiner à la main.
Ce guide s'adresse à ceux qui ont joué avec le code Arduino
([`matrice_8x32.ino`](../matrice_8x32/matrice_8x32.ino)) et veulent continuer
sur le Raspberry Pi. Le fichier de travail est
[`mes_animations.py`](mes_animations.py) : **les mêmes animations que sur
l'Arduino, traduites en Python**. Ouvrez les deux côte à côte !
---
## Sommaire
1. [Lancer un programme](#1-lancer-un-programme)
2. [Python pour qui connaît l'Arduino](#2-python-pour-qui-connaît-larduino)
3. [Les outils de dessin](#3-les-outils-de-dessin)
4. [Exercices](#4-exercices)
5. [Mélanger code et images](#5-mélanger-code-et-images)
6. [Transformer son code en GIF](#6-transformer-son-code-en-gif)
7. [Comment est construit le moteur](#7-comment-est-construit-le-moteur)
---
## 1. Lancer un programme
Pas de téléversement en Python : on **lance** le fichier directement.
| Où | Commande |
|---|---|
| Sur son ordinateur, avec le simulateur | `python3 mes_animations.py --simulateur` (Windows : `py` au lieu de `python3`) |
| Sur le Pi, sur la vraie matrice | `sudo ~/vitrine-env/bin/python mes_animations.py` |
**Ctrl + C** (ou fermer la fenêtre du simulateur) pour arrêter.
> Sur le Pi, si le lecteur tourne déjà en mode vitrine, arrêtez-le d'abord :
> `sudo systemctl stop vitrine-pixels`. Un seul programme à la fois peut
> parler à la matrice.
Pour **éditer** le fichier : sur l'ordinateur, n'importe quel éditeur de
texte (le plus confortable : **Thonny**, <https://thonny.org>, conçu pour
apprendre Python, ou **VS Code**). Sur le Pi : `nano mes_animations.py`.
---
## 2. Python pour qui connaît l'Arduino
| | Arduino (C++) | Python |
|---|---|---|
| Fin d'instruction | `;` obligatoire | rien |
| Bloc (dans une boucle, une fonction…) | entre `{ }` | **décalé de 4 espaces** après un `:` |
| Commentaire | `// texte` | `# texte` |
| Variable | `int x = 3;` | `x = 3` |
| Fonction | `void anim() { … }` | `def anim():` + bloc décalé |
| Boucle « pour » | `for (int x = 0; x < 32; x++) { … }` | `for x in range(32):` |
| Compte à rebours | `for (int y = 7; y > 0; y--)` | `for y in range(7, 0, -1):` |
| Condition | `if (x > 3) { … } else { … }` | `if x > 3:` … `else:` … |
| « et », « ou », « non » | `&&`, `\|\|`, `!` | `and`, `or`, `not` |
| Vrai / faux | `true` / `false` | `True` / `False` (majuscule !) |
| Tableau | `int t[3] = {1, 2, 3};` | `t = [1, 2, 3]` (une « liste ») |
| Couleur | `CRGB(255, 0, 0)` | `(255, 0, 0)` (un « tuple ») |
| Couleur par teinte | `CHSV(160, 255, 255)` | `teinte(160)` |
| Hasard | `random(32)` | `random.randrange(32)` |
| Attendre 100 ms | `delay(100);` | `attendre(100)` |
| Afficher | `FastLED.show();` | `montrer()` |
| Boucle principale | `void loop() { … }` | `while True:` + bloc décalé |
**Le piège n° 1 de Python : l'indentation.** Les espaces en début de ligne
ne sont pas décoratifs, ils **sont** la structure du programme :
```python
for x in range(32):
pixel(x, 0, ROUGE) # dans la boucle : exécuté 32 fois
montrer() # dans la boucle aussi
attendre(1000) # APRÈS la boucle : exécuté une fois
```
Utilisez toujours **4 espaces** (Thonny et VS Code le font tout seuls avec
la touche Tab). Ne mélangez jamais espaces et tabulations.
**Le message d'erreur est votre ami.** Python indique le fichier, la ligne
et la nature de l'erreur, tout en bas :
```
File "mes_animations.py", line 72
attendre(20
^
SyntaxError: '(' was never closed
```
---
## 3. Les outils de dessin
Définis dans [`matrice.py`](matrice.py), disponibles dans `mes_animations.py`
grâce à la ligne `from matrice import *`.
| Outil | Effet |
|---|---|
| `pixel(x, y, couleur)` | colore le pixel de la colonne `x` (0 à 31) et de la ligne `y` (0 à 7). En dehors : ignoré |
| `lire_pixel(x, y)` | renvoie la couleur actuelle d'un pixel |
| `effacer()` | éteint toute la toile |
| `effacer(couleur)` | remplit toute la toile d'une couleur |
| `assombrir(25)` | assombrit toute la toile de 25 % (pour les traînées) |
| `montrer()` | **affiche** la toile. Rien n'apparaît tant qu'on ne l'appelle pas ! |
| `montrer(image)` | affiche une image Pillow de 32 × 8 (voir partie 5) |
| `attendre(100)` | attend 100 millisecondes |
| `teinte(t)` | couleur de l'arc-en-ciel : 0 rouge, 32 orange, 64 jaune, 96 vert, 128 cyan, 160 bleu, 192 violet, 224 rose |
| `teinte(t, saturation, valeur)` | idem, avec saturation (0 = blanc) et valeur (0 = noir), de 0 à 255 |
**Couleurs nommées** : `NOIR`, `BLANC`, `ROUGE`, `ORANGE`, `JAUNE`, `VERT`,
`CYAN`, `BLEU`, `VIOLET`, `MAGENTA`, `ROSE`.
**Dimensions** : `LARGEUR` (32), `HAUTEUR` (8).
Le point `(0, 0)` est **en haut à gauche**, comme dans Krita.
---
## 4. Exercices
Pour chaque exercice, écrivez une nouvelle fonction `def anim_…():` dans
`mes_animations.py` et ajoutez son nom dans `playlist()`. Testez dans le
simulateur.
**1. Le point qui traverse.** Un pixel blanc va de gauche à droite sur la
ligne 3, puis revient. *(Indice : deux boucles `for`, la seconde avec
`range(31, -1, -1)`.)*
**2. Le balayage.** Une colonne entière (8 pixels) balaie la matrice de
gauche à droite. *(Indice : une boucle sur `x`, et dedans une boucle sur `y`.)*
**3. Le dégradé fixe.** Remplissez la matrice d'un arc-en-ciel immobile, de
`teinte(0)` à gauche à `teinte(255)` à droite. Puis faites-le défiler.
*(Comparez avec `anim_arc_en_ciel`.)*
**4. La balle qui rebondit.** Un pixel avance d'un pas en `x` et en `y` à
chaque image, et change de sens quand il touche un bord.
```python
def anim_balle():
x, y = 0, 0 # position
dx, dy = 1, 1 # vitesse (pas par image)
for image in range(300):
effacer()
pixel(x, y, ORANGE)
montrer()
attendre(40)
x = x + dx
y = y + dy
if x <= 0 or x >= LARGEUR - 1:
dx = -dx # rebond sur un bord gauche/droite
if y <= 0 or y >= HAUTEUR - 1:
dy = -dy # rebond en haut/en bas
```
Variante : laissez une traînée en remplaçant `effacer()` par `assombrir(30)`.
**5. Le ciel étoilé.** Des pixels blancs apparaissent au hasard, très
faiblement, puis s'allument et s'éteignent doucement. *(Indice : `assombrir`
et `random.randrange`.)*
**6. Le feu.** Le bas de la matrice est orange vif, des « flammes » montent
au hasard en s'assombrissant et en tirant vers le rouge. *(Indice : partez
de `anim_pluie`, et faites monter au lieu de descendre.)*
**7. Le dessin en lettres.** Modifiez `DESSIN` dans `mes_animations.py` pour
faire défiler votre propre motif. Créez-en un deuxième, et faites-les défiler
l'un derrière l'autre.
---
## 5. Mélanger code et images
Le code peut **lire les images de l'équipe Krita** et les transformer. On
utilise Pillow, la bibliothèque d'images :
```python
from PIL import Image
def anim_logo_qui_defile():
# Remplacez par le chemin d'une image de 32 × 8 exportée depuis Krita.
logo = Image.open("animations/logo.png").convert("RGB")
for i in range(100):
effacer()
# On « colle » le logo deux fois, côte à côte, décalé de i pixels :
# ce qui sort à droite rentre à gauche (défilement en boucle).
toile.paste(logo, (i % LARGEUR - LARGEUR, 0))
toile.paste(logo, (i % LARGEUR, 0))
montrer()
attendre(60)
```
Ici `toile` est l'image de 32 × 8 sur laquelle dessinent `pixel()` et
`effacer()`. Tout ce que sait faire Pillow (coller, retourner, changer les
couleurs, écrire du texte…) fonctionne dessus. Documentation :
<https://pillow.readthedocs.io>.
---
## 6. Transformer son code en GIF
Une animation codée peut devenir un **fichier GIF**, que le lecteur jouera
en vitrine avec les dessins de l'équipe Krita :
```bash
python3 mes_animations.py --enregistrer animations/10_mes_animations.gif
```
Au lieu d'afficher, le moteur **enregistre** chaque image montrée par
`montrer()`, avec la durée de l'`attendre()` qui suit. La playlist est jouée
**une seule fois**, puis le GIF est écrit. Vérifiez-le ensuite :
```bash
python3 outils/verifier_animation.py animations/10_mes_animations.gif
```
> **Attention au hasard** : un GIF enregistre **une** version de
> l'animation. Si votre animation utilise `random`, elle sera identique à
> chaque passage dans le GIF, alors qu'en direct elle change à chaque fois.
---
## 7. Comment est construit le moteur
Pour les curieux, [`matrice.py`](matrice.py) est découpé comme le programme
Arduino, et commenté partie par partie :
1. **Réglages** : taille, broche GPIO, luminosité, limite de courant,
orientation, gamma.
2. **Couleurs** : les noms, et `teinte()` (l'équivalent de `CHSV`).
3. **`XY()`** : la même fonction que sur l'Arduino, qui transforme une
position (x, y) en numéro de LED dans le serpentin.
4. **Gamma et courant** : `preparer_valeurs()` corrige les couleurs avec une
table calculée au démarrage, applique la luminosité, estime le courant
et assombrit l'image si elle consomme trop (comme
`setMaxPowerInVoltsAndMilliamps` de FastLED).
5. **Les écrans** : trois « classes » qui savent toutes `afficher()`,
`attendre()` et `eteindre()` :
- `MatriceReelle` : envoie les couleurs aux LED avec `rpi_ws281x` ;
- `Simulateur` : dessine 256 ronds dans une fenêtre `tkinter` ;
- `Enregistreur` : accumule les images dans un GIF.
Le reste du programme ne sait pas lequel il utilise : c'est le principe
d'une **interface commune**. Ajouter un 4e écran (une page web, une
deuxième matrice…) ne demanderait pas de toucher aux animations.
6. **Outils de dessin** : `pixel()`, `effacer()`, `montrer()`…, qui
travaillent sur la `toile`.
Et [`lecteur.py`](lecteur.py) n'est qu'une boucle : lister le dossier,
charger chaque fichier en liste de couples (image, durée), et les montrer
l'un après l'autre.
### Idées pour aller plus loin
- **Un bouton** branché sur une broche GPIO pour passer à l'animation
suivante (bibliothèque `gpiozero`, déjà installée sur Raspberry Pi OS).
- **Un capteur de présence** (PIR) : la matrice s'anime quand quelqu'un
passe devant la vitrine.
- **L'heure ou la météo** en texte défilant (la police 5 × 7 est dans
[`outils/generer_exemples.py`](outils/generer_exemples.py)).
- **Une page web** sur le Pi pour choisir l'animation depuis son téléphone
(bibliothèque `flask`).