Ein Kettenoktopus wollte nicht auf dem Druckbett bleiben. Die Ursache war eine fehlende Zeile in der Klipper-Konfiguration – und der Weg dorthin führte über drei falsche Fährten, einen abstürzenden CAN-Bus und eine Konfigurationsdatei, die gar nicht geladen war.
Zwei Vermessungen desselben Druckbetts, im Abstand von zehn Stunden. Dazwischen liegt genau eine hinzugefügte Konfigurationszeile:
| Vermessung | Mittelwert | Bedeutung |
|---|---|---|
| vorher | −0,144 mm | gesamte Fläche unter null – konstanter Versatz |
| nachher | −0,001 mm | streut um null – echte Formkorrektur |
Der Unterschied beträgt 143 Mikrometer. Das ist weniger als zwei Blatt Papier. Es hat gereicht, um vier Drucke hintereinander vom Bett zu reißen.
Der fehlende Nullbezug
Klipper rechnet den Wert aus dem Bed Mesh auf die angeforderte Z-Höhe auf. Damit das eine Formkorrektur ist und kein Versatz, muss das Mesh auf den Punkt normiert sein, an dem der Drucker seine Z-Null gefunden hat. Genau dafür gibt es zero_reference_position. Fehlt die Zeile, normiert Klipper nicht – und jeder Messwert wirkt absolut.
In meiner Konfiguration fehlte sie. Das Mesh lag im Mittel bei −0,144 mm unter der Grundfläche des Objekts, an keinem einzigen der zwölf Messpunkte dort über null. Die Düse fuhr also über die ganze Fläche 0,14 mm tiefer, als der G-Code sagte.
# btt_eddy.cfg
[bed_mesh]
horizontal_move_z: 2
speed: 200
zero_reference_position: 199, 200 # identisch zu safe_z_homeEin korrekt normiertes Mesh streut um null. Liegt deines komplett im Minus oder komplett im Plus, ist das kein krummes Bett – das ist ein fehlender Nullbezug.
Der Test ist billig: BED_MESH_CALIBRATE laufen lassen und den Mittelwert ansehen. Ein reales Bett ist an manchen Stellen höher und an anderen tiefer. Ein Mesh, dessen Vorzeichen sich nie ändert, beschreibt keine Bettform.
Anzeige · Affiliate-Link – kaufst du darüber, erhalte ich ggf. eine Provision. Für dich ändert sich am Preis nichts.
Warum PETG verzieh
Der Fehler war seit Monaten in der Konfiguration und ist nie aufgefallen. Der Grund ist Arithmetik: Solange die erste Schicht dick genug angesetzt war, blieb nach Abzug der 0,14 mm immer noch eine brauchbare Schicht übrig.
Wirksame erste Schicht = Nominalwert + Mesh-Mittel unter dem Objekt
| Druck | nominal | vorher | nachher | Ergebnis |
|---|---|---|---|---|
| PETG, gelungen | 0,40 mm | 0,256 mm | 0,399 mm | hielt |
| PLA, erster Versuch | 0,22 mm | 0,076 mm | 0,219 mm | löste sich |
| PLA, aktuelles Profil | 0,32 mm | 0,176 mm | 0,319 mm | hält |
0,076 mm Düsenabstand bei 0,22 mm Materialauftrag heißt: die Düse versperrt ihren eigenen Ausgang. Was herauskommt, wird geschmiert statt gelegt. Es haftet nicht, weil fast nichts da ist, das haften könnte.
Bitter daran: Ausgelöst habe ich das selbst. Meine allererste Änderung an diesem Abend war, die erste Schicht von 0,40 auf 0,20 mm zu senken – „für besseren Squish". Das war die Änderung, die den Fehler aus der Latenz geholt hat. Der Fehler war vorher schon da; ich habe ihm nur die Reserve genommen.
Der zweite, versteckte Nullpunkt
Nach dem Mesh-Fix war die Haftung in Ordnung – aber die erste Schicht saß jetzt spürbar zu locker. Meine erste Reaktion war, einen Babystep nach unten zu empfehlen. Das war zu schnell geraten: Der Drucker zeigte einen aktiven Z-Offset von +0,1014 mm, obwohl niemand etwas eingestellt hatte und ein Firmware-Neustart ihn kurz zuvor nachweislich auf null zurückgesetzt hatte.
homing_origin wird in Klipper ausschließlich durch SET_GCODE_OFFSET gesetzt – nicht durch das Mesh, nicht durch Z-Tilt, nicht durch die Sondenmessung. Irgendetwas hatte den Befehl also abgesetzt. Die Suche über die geladenen Makros förderte ein Paket zutage, das zur Eddy-Installation gehört und Klippers Originalbefehl überschreibt:
[gcode_macro SET_GCODE_OFFSET] # überschreibt den Originalbefehl
[gcode_macro SET_Z_FROM_PROBE] # wendet ihn beim Homing an
[gcode_macro Z_OFFSET_APPLY_PROBE] # schreibt ihn nach variables.cfg
[delayed_gcode RESTORE_PROBE_OFFSET] # holt ihn beim Start zurück
# variables.cfg
[Variables]
nvm_offset = 0.10000000000000002Die Rechnung geht exakt auf:
probe.last_z_result +0.0014 mm # die aktuelle Eddy-Messung
runtime_offset +0.1000 mm # gespeichert, aus variables.cfg
----------
homing_origin Z +0.1014 mmEs war also kein Bedienfehler, sondern ein Wert aus einer früheren Kalibrierung, der bei jedem Start still wiederhergestellt wird. Und jetzt wird es interessant – denn warum stand er auf +0,100?
| Zwei Korrekturen, die dasselbe kompensieren sollten | vor dem Mesh-Fix | nach dem Mesh-Fix |
|---|---|---|
| Mesh unter dem Objekt | −0,144 mm | −0,001 mm |
gespeicherter nvm_offset | +0,100 mm | +0,100 mm |
| netto | −0,044 mm | +0,099 mm |
Die gespeicherten +0,100 mm waren eingemessen worden, um das nicht normierte Mesh auszugleichen. Sie haben den Fehler jahrelang halbwegs erträglich gemacht – und ihn damit unsichtbar gehalten. Als die Ursache behoben war, wurde die Kompensation selbst zum Fehler.
Genau das ist die Falle bei zwei übereinanderliegenden Korrekturen: Solange sie sich gegenseitig aufheben, wirkt alles normal. Repariert man eine, kippt das System in die andere Richtung – und es sieht aus, als hätte die Reparatur das Problem verursacht.
Der richtige Wert für nvm_offset ist nach der Normierung nahe null. Zu wissen, welches Makro-Paket geladen ist, ändert dabei auch das Vorgehen: Dieses Z_OFFSET_APPLY_PROBE schreibt nicht – wie das Original – in den Sondenabschnitt der printer.cfg, sondern per SAVE_VARIABLE nach variables.cfg. Kein SAVE_CONFIG, kein Neustart.
SET_GCODE_OFFSET Z_ADJUST=-0.02 # in Schritten, während der ersten Schicht
Z_OFFSET_APPLY_PROBE # schreibt runtime_offset nach variables.cfgMessen, bevor es warm ist
Ein dritter Punkt gehört in dieselbe Kette, weil er jede Kalibrierung unbrauchbar macht. Das Startmakro hatte eine Reihenfolge, die im Alltag nicht auffällt:
M104 S{HOTEND} ; Düse anheizen, nicht warten
M140 S{BED} ; Bett anheizen, NICHT warten
G28
Z_TILT_ADJUST
BED_MESH_CALIBRATE ; <- hier ist das Bett noch nicht warm
; ...
M190 S{BED} ; erst JETZT auf das Bett wartenIm Log steht, was das bedeutet: target=60 temp=37.1 pwm=1.000. Das Mesh entstand bei 37 °C, gedruckt wurde bei 60.
Der eigentliche Schaden ist nicht der Messfehler, sondern seine Unbeständigkeit. Wie warm das Bett beim Messen ist, hängt davon ab, wie lange die Maschine vorher lief. Ein heute eingemessener Z-Offset stimmt morgen nicht mehr – man kalibriert gegen ein bewegliches Ziel.
M140 S{params.BED} ; Bett anheizen
M104 S{[150, params.HOTEND|int]|min} ; Düse nur vorwärmen
M190 S{params.BED} ; auf Betttemperatur WARTEN
G4 P120000 ; 2 min durchwärmen
G28
Z_TILT_ADJUST
BED_MESH_CALIBRATE
M109 S{params.HOTEND} ; jetzt erst auf DrucktemperaturDie Düse bleibt beim Messen auf 150 °C – warm genug, dass das Aufheizen danach kurz ist, kalt genug, dass sie nicht in das frische Mesh sabbert. Kosten: zwei bis drei Minuten pro Druck.
Die Kette aus drei Korrekturen
Was am Ende blieb, ist weniger eine Liste von Einstellungen als eine Kette von drei Korrekturen, die sich über Monate gegenseitig verdeckt hatten: ein Mesh ohne Nullbezug, ein gespeicherter Offset, der ihn ausglich, und eine erste Schicht, die dick genug war, damit beides zusammen funktionierte. Es brauchte nur eine einzige Änderung an der dünnsten Stelle dieser Kette – und alles fiel gleichzeitig auseinander.
Der gespeicherte nvm_offset steht übrigens weiterhin auf +0,100 mm, obwohl er nach der Normierung nahe null gehören dürfte. Er ist mit Abstand der größte verbliebene Fehler in der Z-Kette und zugleich der billigste zu beheben.
Drucker: HevORT, Klipper v0.13.0-743, BTT Eddy USB, Phaetus Rapido 2, 0,4-mm-Düse. Slicer: OrcaSlicer 2.4.2.
Alle Zahlen stammen aus Messungen an dieser Maschine – aus klippy.log, der Moonraker-API und der Rollenaufschlüsselung des Slicers. Sie gelten für diesen Drucker, nicht allgemein.
Diese Serie
Ein Abend Fehlersuche an einem Kettenoktopus hat vier Themen ergeben, die sich unabhängig voneinander lesen lassen:
- Der fehlende Nullbezug – dieser Artikel
- Print-in-Place: Schichthöhe entscheidet über die Gelenke
- OrcaSlicer & Klipper: 34 % weniger Druckzeit (erscheint in Kürze)
- Sieben Fehlschlüsse bei der Klipper-Fehlersuche (erscheint in Kürze)
Anzeige · Affiliate-Link – kaufst du darüber, erhalte ich ggf. eine Provision. Für dich ändert sich am Preis nichts.