# FLSun QQ-S sous Klipper

Machine : FLSun **QQ-S** (2020, non-Pro), carte **MKS Robin Mini** (STM32F103),
bowden Titan clone, hotend V6 clone à gaine PTFE (245 °C max), plateau verre
φ260, hauteur 370. Achetée janvier 2020, ~233 h et 970 m de filament sous le
firmware d'origine (Repetier, pas Marlin).

Depuis le **4 septembre 2026** elle tourne sous **Klipper**, hôte sur le laptop
(le Pi 3B reprendra ce rôle plus tard). Ce dépôt contient la config, les outils
et l'historique de ce qui a été trouvé.

---

## État de la machine (6 sept. 2026, midi)

| Domaine | État | Comment |
|---|---|---|
| Firmware MCU | Klipper f0892d8, STM32F103, 72 MHz, USART3 250000 | `build-firmware.sh` |
| Courant moteur | 800/1500 par PWM sur PA6/PA7/PB0 | `[output_pin motor_current_*]` |
| Géométrie delta | calibrée **à chaud** (7 pts au papier, 6 sept.) — angles A +0,93°, B +0,33°, rayon 141,29 | bloc `SAVE_CONFIG` |
| Zéro Z | gravé dans les 3 butées, à chaud (376,08 / 375,97 / 376,86) | `position_endstop` |
| Bed mesh | grille **7×7 / R120, 29 pts au papier, à chaud** ; centre plat ±0,1, bord avant −0,6 ; fade 1→10 mm | profil `default`, chargé par `START_PRINT` |
| Première couche | offset **−0,15** sur le zéro à chaud (−0,10 colle à peine, −0,20 fait une lèvre) ; spirale n°6 uniforme | `START_PRINT` |
| Pressure advance | **0,38** (square_tower, meilleur coin à 19 mm) | `[extruder]` |
| Timeout d'inactivité | 1 h (les passes de mesure dépassent les 10 min par défaut) | `[idle_timeout]` |
| Extrudeur | `rotation_distance` **7,716** (mesuré, contre-vérifié à 20,0 mm) | `[extruder]` |
| PID | buse 235 → 15,9/0,63/100,8 · plateau 75 → 68,7/1,58/747 | bloc `SAVE_CONFIG` |
| Protection thermique buse | fenêtre élargie (60 s / 10 °C / 1 °C) | `[verify_heater extruder]` |
| Palpeur | **désactivé** (module absent) — tout est manuel, au papier | `#[probe]` |
| Filament | PLA neuf (le PETG de la machine est saturé d'eau) | — |

Cube de contrôle du 6 sept. (après recalibration à chaud) : 20,3 × 20,4 × 20,00,
lèvre 0,1 par côté. Le résidu XY est du cordon, corrigé dans le profil de production.

---

## Ce qui a été trouvé — trois défauts d'origine, jamais vus en 233 h

1. **Angles de tours jamais calibrés.** L'EEPROM Repetier avait tous ses termes
   de correction à zéro. La calibration manuelle a trouvé +1,02° sur A et
   +0,45° sur B — distorsion dimensionnelle et vrillage invisibles à
   l'auto-leveling.
2. **Sous-extrusion de 11,5 %.** 367 pas/mm dans l'EEPROM ; la mesure des
   100 mm a donné 88,5. Chaque couche jamais posée par cette machine manquait
   d'un dixième de sa matière.
3. **Courant moteur piloté par PWM** — spécifique à la Robin Mini (`PA6`, `PA7`,
   `PB0`, cf. `pins_MKS_ROBIN_MINI.h` de Marlin). Repetier le fixait au
   démarrage ; **la config Klipper officielle de cette imprimante ne le fait
   pas** → moteurs sans couple, homings ratés. Corrigé par trois `[output_pin]`.

Et une cause de « fiabilité décevante » qui n'était pas la machine : le PETG
qui vivait dessus était **humide** (crépitement dans la buse, parois
mousseuses). À sécher (60–65 °C, 4–6 h) avant réutilisation.

---

## Fichiers

| Fichier | Rôle |
|---|---|
| `printer.cfg` | config Klipper — valeurs réelles de cette machine, bloc `SAVE_CONFIG` en fin |
| `klipper.md` | procédure d'installation (flash, hôte, calibration) |
| `eeprom-repetier.txt` | dump `M205` de l'EEPROM d'origine (source des valeurs de départ) |
| `start-klipper.sh` | `start` / `stop` / `restart` de klippy (fichier PID, jamais `pkill`) |
| `send-gcode.sh "…"` | envoie du G-code et rend la main |
| `calib.py` | pilotage clavier : homing, calibrations manuelles, vérification, baby-steps |
| `fix-mesh.py` | nivellement fin : la buse pointe chaque carré imprimé, saisie de l'épaisseur au micromètre (`Nt`), réécrit la mesh ; `--sans-saisie` reprend `mesures-mesh.json` |
| `mesh-to-7.py` | migration de la mesh vers 7×7 / R120 par rééchantillonnage (fait le 5 sept.) |
| `analyze-delta.py` | saisie guidée des 21 mesures de `calibrate_size` → `DELTA_ANALYZE` (bras) |
| `watch-print.py` | suivi d'une impression (état, paliers, offset, fin) |
| `build-firmware.sh` | recompile le firmware MCU (`Robin_mini.bin`) |
| `test-carte-sd.sh` | test d'intégrité d'une carte SD |
| `gsend.py` | console série pour le firmware d'origine (obsolète sous Klipper) |
| `slicer/` | profils PrusaSlicer CLI : `qqs-pla.ini` (tests, brut), **`qqs-pla-prod.ini`** (pièces : multiplier 0,95, XY −0,1, pied 0,1), `qqs-petg.ini`, un `.ini` par test |
| `gcodes/` | fichiers tranchés — c'est le `virtual_sdcard` |
| `squashfs-root/` | PrusaSlicer 2.8.1 extrait (l'AppImage bloque en direct) |
| `printer-2026*.cfg` | sauvegardes automatiques de `SAVE_CONFIG` |

---

## Mode d'emploi

### Démarrer

```bash
cd /home/sam/dev/perso/flsun
./start-klipper.sh start          # klippy, log /tmp/klippy.log
./send-gcode.sh STATUS            # -> Klipper state: Ready
```

L'écran tactile reste noir : c'est attendu, Klipper n'a pas de driver pour lui.
L'imprimante ne fonctionne que **laptop allumé et connecté en USB**.

### Imprimer

Trancher (profil PLA, ou `qqs-petg.ini`) :

```bash
env -u DISPLAY -u WAYLAND_DISPLAY ./squashfs-root/usr/bin/prusa-slicer \
  --export-gcode --load slicer/qqs-pla.ini piece.stl --output gcodes/piece.gcode
```

Le profil met déjà `START_PRINT BED=… HOTEND=…` / `END_PRINT` — ne rien
ajouter d'autre dans un slicer graphique. Puis :

```bash
./send-gcode.sh "SDCARD_PRINT_FILE FILENAME=piece.gcode"
./watch-print.py                  # suivi
```

Pendant l'impression, `./calib.py` : `[` / `]` ajustent la première couche
par 0,05, `p` lit l'offset. Toute autre touche est **refusée** tant qu'un print
tourne.

### Calibrer (au papier, sans palpeur)

`./calib.py`, puis :

- `h` homing · `s` calibration delta (7 points) · `m` bed mesh (13 points) ·
  `v` vérification : buse à Z=0,1 sur 7 points, carte des écarts
- à chaque point : `↓`/`j` 1 mm, `d` 0,1 mm, `-`/`+` bissection, `Entrée` valide
- `c` `c` sauvegarde (Klipper redémarre)

Ne jamais redémarrer Klipper pendant une passe : ça la perd.

### Recompiler le firmware

`./build-firmware.sh /run/media/sam/<carte>` — carte SD **≤ 8 Go, FAT32**,
fichier `Robin_mini.bin` à la racine, imprimante éteinte à l'insertion.
Le bootloader renomme en `.CUR` quand c'est pris.

---

## Reste à faire

- **Cotes** : validées le 6 sept. — cube 20,3 × 20,4 × 20,00, entraxe 65,0 sur la
  pièce à piliers ⇒ échelle juste, l'excès XY est du cordon ⇒ corrigé dans
  `qqs-pla-prod.ini`. Calibration des bras **non nécessaire**.
- **Input shaper** sans accéléromètre : `ringing_tower_pla.gcode` (1 h 23),
  `TUNING_TOWER COMMAND=SET_VELOCITY_LIMIT PARAMETER=ACCEL START=1500 STEP_DELTA=500 STEP_HEIGHT=5`.
- **Extrudeur OMG V2-S** (en stock) : monter en bowden **après** une pièce de
  référence — nouveau `rotation_distance`, `dir_pin` probablement à inverser,
  PA à refaire.
- **Pi 3B** en hôte : MainsailOS, `[include mainsail.cfg]` à remettre,
  USB court fixé près de la machine.
- Mécanique jamais vérifiée : tube PTFE contre la buse, siège de la thermistance.
- PETG à sécher (60–65 °C, 4–6 h) avant réutilisation.
### Nivellement — ce qui a marché, et ce qui n'a pas marché

**Ce qui a marché (6 sept.)** : tout recalibrer **à chaud** (plateau 60 °C, buse
froide), au papier, dans l'ordre `s` (7 points) → `c c` → `h` → `m` (29
points) → `c c`, puis une spirale de contrôle. 35 min. Résultat : spirale
uniforme, bord avant compris.

**Ce qui n'a pas marché (4–5 sept.)** : deux jours de passes de mesh par-dessus
une géométrie fausse. La retension des courroies faite entre la calibration
delta et sa vérification avait décalé les butées inégalement (0,38 mm entre A
et B) ; un +0,4 uniforme avait été appliqué à la main. La mesh compensait une
pente que le delta ne rend pas plane, et n'a jamais convergé.

**La méthode des carrés au micromètre** (`fix-mesh.py`) est **biaisée** là où
la buse est trop près : le carré écrasé fait une lèvre relevée, le micromètre
la lit « épais ». Elle n'est gardée que pour mémoire ; si on y revient, carrés
de 20 mm mesurés au centre.

**Règles** :
- calibrer dans l'état d'impression (à chaud), une seule méthode de mesure ;
- un nouveau zéro ⇒ re-régler l'offset de première couche (`square_pla` + `[` `]`), ne jamais reporter l'ancien ;
- pour recharger `printer.cfg`, envoyer `RESTART` en G-code ; `start-klipper.sh restart` peut laisser le MCU en arrêt (`FIRMWARE_RESTART` répare) ;
- toute retension de courroie → refaire `s` puis `m`, pas de raccourci ;
- la spirale (`spiral_pla`, 12 min) est le juge : rouge = trop près (raclé,
  cordon plat translucide), bleu = trop loin (cordon rond, non collé) ;
- quand deux mesures se contredisent, regarder le cordon à la loupe avant de
  raisonner.

## Historique

Les décisions, mesures et leçons des 4, 5 et 6 septembre 2026 sont dans
mempalace, aile `wing_flsun` (salles `hardware`, `mecanique`, `decisions`,
`livrables`, `recherche`).
