Klipper のマクロを使って Step by step 印刷を実現する方法
前置き
2022年8月18日に3Dプリンタユーザーが集まっている Discord のサーバーの klipper_jp で「GCode をスタートボタンを押して1行ずつ実行する方法はないか」という質問がありました。
そこで、1行ずつ実行する方法を調べたのですが、その過程でレイヤー切り替え毎に手動で一時停止・印刷再開を行う方法を編み出せましたので、誰かの参考になればと思い方法をまとめました。
必要な手順の概要
printer.cfg
に save_variables セクションを追加して一時停止フラグを格納するファイルのファイル名を指定する- SAVE_VARIABLE マクロを使って一時停止フラグのオン・オフを切り替えるマクロを
printer.cfg
に追加する PAUSE
マクロとRESUME
マクロを定義する(定義済みならこの作業は不要)- 一時停止フラグの状態に応じて
PAUSE
マクロを実行するマクロを追加する
実際のコード
1#printer.cfg
2
3[gcode_macro PAUSE]
4rename_existing: BASE_PAUSE
5gcode:
6 SAVE_GCODE_STATE NAME=PAUSE_state
7 BASE_PAUSE
8 G91
9 G1 E-0.5 F100
10 G1 Z5
11 G90
12 #G1 X{X} Y{Y} F6000
13
14[gcode_macro RESUME]
15rename_existing: BASE_RESUME
16gcode:
17 G91
18 G1 E0.5 F100
19 G90
20 RESTORE_GCODE_STATE NAME=PAUSE_state MOVE=1
21 BASE_RESUME
22
23[gcode_macro PAUSE_FLAG_OFF]
24gcode:
25 SAVE_VARIABLE VARIABLE=pause_flag VALUE=0
26
27[gcode_macro PAUSE_FLAG_ON]
28gcode:
29 SAVE_VARIABLE VARIABLE=pause_flag VALUE=1
30
31[gcode_macro ECHO_PAUSE_FLAG]
32gcode:
33 RESPOND MSG="PAUSE_FLAG is {printer.save_variables.variables.pause_flag}"
34
35[gcode_macro STEP_BY_STEP_PRINT]
36description: Controls step-by-step printing, pausing at each layer
37gcode:
38 {% if printer.save_variables.variables.pause_flag == 1 %}
39 RESPOND TYPE=command MSG="PAUSE_FLAG ON"
40 PAUSE
41 {% else %}
42 RESPOND TYPE=command MSG="PAUSE_FLAG OFF"
43 {% endif %}
44
45[save_variables]
46filename: ~/variables.cfg
各処理の説明
一時停止フラグの準備
フラグの格納場所
スライサーで作成した GCode にグローバル変数を埋め込むことはできないので、一時停止フラグは、Raspberry Pi のローカルファイルに格納します。
Klipper 独自の GCode には、変数をローカルファイルに書き込むSAVE_VARIABLE というマクロが用意されており、ここで格納した変数は printer.save_variables.variables.変数名
で呼び出せます。
このマクロを使うには、printer.cfg
にsave_variables セクションを追加し、変数を書き込むファイルを filename: ~/variables.cfg
と指定する必要があります(ファイル名は任意の名前でOKだと思います)。
1[save_variables]
2filename: ~/variables.cfg
フラグの切り替え
フラグを格納する場所を指定しましたので、次は SAVE_VARIABLE
マクロを使ってフラグを立てるマクロとフラグを下ろすマクロを次のとおり作成します。なお、フラグの名前は pause_flag
としています。
1[gcode_macro PAUSE_FLAG_ON]
2gcode:
3 SAVE_VARIABLE VARIABLE=pause_flag VALUE=1
4
5[gcode_macro PAUSE_FLAG_OFF]
6gcode:
7 SAVE_VARIABLE VARIABLE=pause_flag VALUE=0
また、現在のフラグの状態を表示するマクロがあると便利なので、そちらも用意します。
1[gcode_macro ECHO_PAUSE_FLAG]
2gcode:
3 RESPOND MSG="PAUSE_FLAG is {printer.save_variables.variables.pause_flag}"
ここでは、引数で渡されたメッセージをコンソールに出力するRESPOND マクロを使って現在のフラグの状態をコンソールに出力しています。現在のフラグの状態は printer.save_variables.variables.pause_flag
で確認できますので、{...}
で囲んでメッセージに埋め込んでいます。
なお、変数を {...}
で囲む理由は、Klipper のドキュメントで次のように説明されているためです。
Template expansion
The gcode_macro gcode: config section is evaluated using the Jinja2 template language. One can evaluate expressions at run-time by wrapping them in { } characters or use conditional statements wrapped in {% %}. See the Jinja2 documentation for further information on the syntax.
jinja2 で変数展開するには {...}
ではなく {{...}}
で囲むはずなのですが、Klipper のマクロでは {...}
で囲めば変数が展開されると書かれていますので、それに従ってコードを書いています。
一時停止フラグの状態に応じた条件分岐
これで一時停止フラグを切り替えられるようになりましたので、一時停止フラグの状態に応じて一時停止するか通常通り印刷するかの条件分岐を行うマクロを追加します。
マクロの gcode:
セクションで条件分岐する場合、if
文は {% ... %}
で囲みますので、コードは次のとおりとなります。
1[gcode_macro STEP_BY_STEP_PRINT]
2gcode:
3 {% if printer.save_variables.variables.pause_flag == 1 %}
4 RESPOND TYPE=command MSG="PAUSE_FLAG ON"
5 PAUSE
6 {% else %}
7 RESPOND TYPE=command MSG="PAUSE_FLAG OFF"
8 {% endif %}
{% if printer.save_variables.variables.pause_flag == 1 %}
でフラグが立っているか確認し、フラグが立っていれば PAUSE
マクロを実行しています。
これで printer.cfg
側で行う準備は完了です。
スライサー側の設定
PrusaSlicer/SuperSlicer の「Printer Settings」の「Custom G-code」の「Before layer change g-code」に PAUSE_FLAG_OFF
と STEP_BY_STEP_PRINT
マクロを追加します。PAUSE_FLAG_OFF
マクロも追加するのは、意図しない一時停止を発生させないためです。
1;BEFORE_LAYER_CHANGE
2;[layer_z]
3PAUSE_FLAG_OFF
4STEP_BY_STEP_PRINT
これで STL ファイルをスライスするだけでレイヤー切り替え直前に一時停止するかどうかの条件分岐が行われるようになりました。また、printer.cfg
にマクロを設定したことにより、Mainsail の Macros タブに PAUSE_FLAG_ON、PAUSE_FLAG_OFF ボタンが追加されていますので、この2つのボタンでフラグを切り替えて印刷を制御します。
この2つのボタンを使って印刷を制御している様子を動画にしていますので、よろしければご覧ください。
以上で説明は完了です。
補足
フラグを立てる処理で SAVE_VARIABLE VARIABLE=pause_flag VALUE=1
というコードを実行していますが、条件分岐では変数の値だけでなく型もチェックされているようですので、 SAVE_VARIABLE VARIABLE=pause_flag VALUE=1
を実行してから次のマクロを実行した場合、コンソールには PAUSE_FLAG is numeric 1
が表示されます。
1[gcode_macro TEST]
2gcode:
3 {% if printer.save_variables.variables.pause_flag == '1' %}
4 RESPOND TYPE=command MSG="PAUSE_FLAG is string '1'"
5 {% endif %}
6 {% if printer.save_variables.variables.pause_flag == 1 %}
7 RESPOND TYPE=command MSG="PAUSE_FLAG is numeric 1"
8 {% endif %}
また、 SAVE_VARIABLE
マクロを使った変数のローカルファイルへの格納は、実行してから保存されるまで若干のタイムラグがあるようです。pause_flag
の値が 0
の状態で次のコードを実行すると、コンソールに表示される値は 1
ではなく 0
になりました。
1[gcode_macro PAUSE_FLAG_ON]
2gcode:
3 SAVE_VARIABLE VARIABLE=pause_flag VALUE=1
4 RESPOND MSG="PAUSE_FLAG is {printer.save_variables.variables.pause_flag}"
そのため、SAVE_VARIABLE
マクロを実行した直後に条件分岐のコードを追加した場合、意図した動作にならない可能性があります。