今回のやること
前回の続きで、今回は実際のKlipperマクロを書こうと思います。
デバッグの準備
マクロを書くにあたり、デバッグができないとかなり苦労します。
幸い、M118という、シリアルで文字や変数を送信するコマンドが存在ます。これがあればprintfデバッグの要領で動作の確認が可能です。
[respond]
default_type: echo
# Sets the default prefix of the "M118" and "RESPOND" output to one
# of the following:
# echo: "echo: " (This is the default)
# command: "// "
# error: "!! "
default_prefix: echo:
# Directly sets the default prefix. If present, this value will
# override the "default_type".
使い方としては、こんな感じです。
[gcode_macro HELLO_WORLD]
gcode:
M118 "HELLO WORLD {params.V}"
応答はこんな感じ。
Send: HELLO_WORLD
Recv: echo: "HELLO WORLD"
実際のマクロ例
実際にいつくかマクロを書いてみて練習します。
プログラミング
jinja2の構文が使えます。
入力
コマンドに続いてパラメータを入力できます。また、パラメータが省略された場合のデフォルト値を設定できます。
[gcode_macro TEST_INPUT]
gcode:
M118 "X = {params.X|default(0)|float}"
いくつかの入力を試してみました。
Send: TEST_INPUT
Recv: echo: "X = 0.0"
Send: TEST_INPUT X=1.2
Recv: echo: "X = 1.2"
Send: TEST_INPUT X123
Recv: !! Malformed command 'TEST_INPUT X123'
Klipperのマクロでは、既存のGコード(例:G1 X1 Y2.0 Z3.0 E-1 F300
)のように"="がない場合は受け付けてくれないようです。これではKlipperにないコマンド(例:G29、M600)をマクロで再現するときに互換性が無くなってしまいます。どうしてこうなった。
一応、rawparamsでは文字列をそのまま受け取れますので、jinja2でパーサーを組めばやりたいことができるはずです。以下は公式githubにあるサンプルで、コメント開始記号を置き換える処理です。(もう少し役に立つパーサーのサンプルをよこせ)
[gcode_macro TEST_RAW]
gcode:
{% if rawparams %}
{% set escaped_msg = rawparams.split(';', 1)[0].split('\x23', 1)[0]|replace('"', '\\"') %}
M118 "{escaped_msg}"
{% else %}
M118 "NOT RAW"
{% endif %}
変数&演算
マクロ内で変数を設定できます。変数にはコマンドの入力値も扱えます。また変数同士を演算することが可能です。
[gcode_macro TEST_VAL]
gcode:
{% set X = params.X|default(1.0)|float %}
{% set Y = params.Y|default(1.0)|float %}
M118 "X + Y = {X + Y}"
M118 "X - Y = {X - Y}"
M118 "X * Y = {X * Y}"
M118 "X / Y = {X / Y}"
パラメータを変えながら実行してみました。またゼロ割も試してみました(もちろんちゃんとエラーになりました)。
Send: TEST_VAL
Recv: echo: "X + Y = 2.0"
Recv: echo: "X - Y = 0.0"
Recv: echo: "X * Y = 1.0"
Recv: echo: "X / Y = 1.0"
Send: TEST_VAL X=2 Y=1.2
Recv: echo: "X + Y = 3.2"
Recv: echo: "X - Y = 0.8"
Recv: echo: "X * Y = 2.4"
Recv: echo: "X / Y = 1.66666666667"
Send: TEST_VAL X=1.5 Y=0
Recv: !! Error evaluating 'gcode_macro TEST_VAL:gcode': ZeroDivisionError: float division by zero
制御文
よくあるFizzBuzz問題を解いてみました。
ifやforが使えます。
[gcode_macro TEST_CTRLFLW]
gcode:
{% set count_range = 30 %}
{% for count in range(count_range) %}
{% set num = count + 1 %}
{% if num % 15 == 0 %}
M118 "Fizz Buzz"
{% elif num % 3 == 0 %}
M118 "Fizz"
{% elif num % 5 == 0 %}
M118 "Buzz"
{% else %}
M118 {num}
{% endif %}
{% endfor %}
結果はこんな感じです。
Send: TEST_CTRLFLW
Recv: echo: 1
Recv: echo: 2
Recv: echo: "Fizz"
Recv: echo: 4
Recv: echo: "Buzz"
Recv: echo: "Fizz"
Recv: echo: 7
Recv: echo: 8
Recv: echo: "Fizz"
Recv: echo: "Buzz"
Recv: echo: 11
Recv: echo: "Fizz"
Recv: echo: 13
Recv: echo: 14
Recv: echo: "Fizz Buzz"
Recv: echo: 16
Recv: echo: 17
Recv: echo: "Fizz"
Recv: echo: 19
Recv: echo: "Buzz"
Recv: echo: "Fizz"
Recv: echo: 22
Recv: echo: 23
Recv: echo: "Fizz"
Recv: echo: "Buzz"
Recv: echo: 26
Recv: echo: "Fizz"
Recv: echo: 28
Recv: echo: 29
Recv: echo: "Fizz Buzz"
内部パラメータの表示
3Dプリンタが持つパラメータを変数として取り扱えます。使える変数は公式ページにある通りです。
[gcode_macro MACRO_TEST2]
gcode:
M118 "{printer.toolhead.axis_minimum.x}"
M118 "{printer.toolhead.axis_minimum.y}"
M118 "{printer.toolhead.axis_minimum.z}"
M118 "{printer.toolhead.axis_maximum.x}"
M118 "{printer.toolhead.axis_maximum.y}"
M118 "{printer.toolhead.axis_maximum.z}"
Send: MACRO_TEST2
Recv: echo: "0.0"
Recv: echo: "0.0"
Recv: echo: "-10.0"
Recv: echo: "220.0"
Recv: echo: "220.0"
Recv: echo: "287.5"
今後
実用的なコードを書いてみる。