Ender5Pro+SKR3+OctoPrint+Klipperの設定【フィラメントセンサ編】

[前回](https://qiita.com/tanutanup/items/1da1edd8185b12224e9c)はBLTouchによるベッドレベリングを実装しました。今回はフィラメントセンサ機能の設定を行います。

# 記事一覧
[その他の3Dプリンタ記事はこちら。](https://qiita.com/tanutanup/items/be6a6166d814a5882c7f)

# 今回の目的
- フィラメントセンサを取り付ける
- フィラメント切れや供給不良などの異常を検出する
- 異常検出後、印刷を停止・問題解決後に再開させる

# フィラメントセンサ
3Dプリンタのフィラメントセンサとは、フィラメントがノズルに送られていないことを検出するセンサです。フィラメントが送られないまま印刷が進んでしまうと、印刷途中までしか造形されず時間も材料も無駄になってしまいます。そこでセンサで異常検出できれば、印刷を中断して問題を解決、そのまま印刷を再開できるので造形の失敗が防止できます。

## スイッチタイプ
機械的・光学的な手段でフィラメントが存在するかどうかを検出するセンサです。[Crealityフィラメントセンサ](https://www.amazon.co.jp/Creality-%E3%83%A9%E3%83%B3%E3%82%A2%E3%82%A6%E3%83%88%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC-%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%83%95%E3%82%A3%E3%83%A9%E3%83%A1%E3%83%B3%E3%83%88%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC-%E3%83%95%E3%82%A3%E3%83%A9%E3%83%A1%E3%83%B3%E3%83%88%E6%A4%9C%E5%87%BA-Ender-3Pro/dp/B0B3168BXT)など、3Dプリンタメーカがー最初から搭載している場合も多いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269597/08773639-dccc-660e-c740-57f56a732710.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269597/573a44a4-b27e-f964-6a70-d8768d895c11.png)

このセンサの特徴としては以下のとおりです。
- シンプル(重量・価格の低減につながる）
- スイッチのレベル変化がそのまま異常として判断可能
（シンプルな検出ロジック）
- フィラメントが **センサ～ノズルの間**で切れると検出不可
- フィラメントが**切れないと**検出不可

個人的にはとくに３・４番目の特徴は致命的だと考えています。実際の印刷失敗経験では、フィラメントが切れたことはほぼなく、ノズル詰まりやリールの絡みなどで、エクストルーダでモータが脱調 or フィラメントが削れてることによる供給不良がほとんどだったからです。
(最近は、フィラメントの品質も上がってきているので、余り切れることは無いんではないかと思ってます。PLAばっかり印刷しているので他の材料はそうではないかもしれませんが)

## エンコーダタイプ
フィラメントが**供給**できているとフィラメントが移動することを検出するタイプのセンサです。[Bigtreetech スマートフィラメントセンサ](https://www.amazon.co.jp/BIGTREETECH-%E3%82%B9%E3%83%9E%E3%83%BC%E3%83%88%E3%83%95%E3%82%A3%E3%83%A9%E3%83%A1%E3%83%B3%E3%83%88%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC-1-75mm-%E3%83%95%E3%82%A3%E3%83%A9%E3%83%A1%E3%83%B3%E3%83%88%E3%83%96%E3%83%AC%E3%83%BC%E3%82%AF-%E3%82%B9%E3%82%BF%E3%83%83%E3%82%AF%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E6%A4%9C%E5%87%BA%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%83%A2%E3%83%8B%E3%82%BF%E3%83%BC/dp/B07ZTM9CSQ/ref=sr_1_48?keywords=%E3%83%95%E3%82%A3%E3%83%A9%E3%83%A1%E3%83%B3%E3%83%88+%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC+3d&qid=1680505477&sprefix=%E3%83%95%E3%82%A3%E3%83%A9%E3%83%A1%E3%83%B3%E3%83%88+%E3%82%BB%E3%83%B3%E3%82%B5%2Caps%2C185&sr=8-48)などが挙げられます。

フィラメントに接触して回転するローラーに放射状の穴が空いており、フィラメント供給中はセンサが検出する光が断続的に変化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269597/0f89cdf7-d4a3-afbf-2a38-3b8a9a0ca037.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269597/bff8d082-31f9-0086-a990-f30c896b8cdc.png)

特徴としては以下の項目が挙げられます。
- 複雑(重量や値段の増加）
- エクストルーダの供給量とセンサのH/L変化数を紐づけて検出する必要がある
- フィラメントの供給そのものを検出しているので、取り付け場所の制約が無い
- フィラメントの供給そのものを検出しているので、ノズルのつまりやエクストルーダの脱調なども検出可能

# フィラメント異常検出機能の設定
## 取り付け
Bigtreetechのフィラメントセンサは取り付けるためのステーが無いので自作します。検索して出てくるモデルでも良いですが、いい形のものがなかったので自作しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269597/56c4952b-f000-9d81-ac14-46ac81f49317.png)

## 印刷の停止・再開
PAUSE/RESUMEコマンドで実行中の印刷を一時停止/再開することができますが、デフォルトでは使用できませんので追記します。
```printer.cfg
[pause_resume]
#recover_velocity: 50.
#   When capture/restore is enabled, the speed at which to return to
#   the captured position (in mm/s). Default is 50.0 mm/s.
```
適当なデータを印刷中にTerminalにPAUSE/RESUMEを入力して動作を確認します。各軸の動作が停止。温度はそのままになるはずです。

```Terminal
Send: PAUSE
Recv: // action:paused
Printer signalled that it paused, switching state...
Changing monitoring state from "Printing" to "Pausing"
Recv: ok
Changing monitoring state from "Pausing" to "Paused"
Send: M105
Recv: ok B:60.0 /60.0 T0:199.8 /200.0
Send: M105
Recv: ok B:60.0 /60.0 T0:200.3 /200.0
Send: RESUME
Recv: // action:resumed
Printer signalled that it resumed, switching state...
Changing monitoring state from "Paused" to "Resuming"
Recv: ok
Changing monitoring state from "Resuming" to "Printing"
```

## 異常検出
[公式ドキュメント](https://www.klipper3d.org/Config_Reference.html)とセンサメーカーの[github](https://github.com/bigtreetech/smart-filament-detection-module)を参照して設定します。

センサの接続先はPC2にしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269597/6f5a582e-2d00-2f93-9b9a-0c36e7ae3ee7.png)
また、エラー時の処置として、仮のメッセージを表示します。

```printer.cfg
[filament_motion_sensor EXT0_FMS]
detection_length: 7
#   The minimum length of filament pulled through the sensor to trigger
#   a state change on the switch_pin
#   Default is 7 mm.
extruder: extruder
#   The name of the extruder section this sensor is associated with.
#   This parameter must be provided.
switch_pin: PC2
# changing the switch_pin name according to your motherboard
#pause_on_runout: True
runout_gcode: ERR_RUNOUT
#insert_gcode:
#event_delay:
#pause_delay:
#   See the "filament_switch_sensor" section for a description of the
#   above parameters.
```

メッセージを表示用のマクロです。
(マクロを別ファイルに分けています)

```filament.cfg
[gcode_macro ERR_RUNOUT]
gcode:
    PAUSE
    M118 "!!EXT0 RUNOUT!!"
```

印刷中にフィラメントをカット(もしくはフィラメントセンサのコネクタを抜く）と、所定のメッセージが表示されて印刷が止まりました。

```
Recv: // action:paused
Printer signalled that it paused, switching state...
Changing monitoring state from "Printing" to "Pausing"
Recv: ok
Changing monitoring state from "Pausing" to "Paused"
Recv: // Print already paused
Recv: echo: "!!EXT0 RUNOUT!!"
```
## 異常検出処置
異常検出後にヘッドが印刷物の上にあると操作の邪魔になります。
ヘッド退避のコードをマクロにしておきます。
(Zを少し浮かせてから中央手前側に移動するコードです)

```commcr.cfg
[gcode_macro GO_TO_PARK_POSITION]
gcode:
    {% set Xdefpos_p = 0.5 %}
    {% set Ydefpos_p = 0.1 %}
    {% set X = params.X|default((printer.toolhead.axis_maximum.x - printer.toolhead.axis_minimum.x) * Xdefpos_p)|float %}
    {% set Y = params.Y|default((printer.toolhead.axis_maximum.y - printer.toolhead.axis_minimum.y) * Ydefpos_p)|float %}
    {% set Z = params.Z|default(10)|float %}
    G91
    G1 Z{Z} F3000
    G90
    G1 X{X} Y{Y} F3000
```
また、フィラメント供給異常検出時のマクロも追記します。
```filament.cfg
[include commcr.cfg]

[gcode_macro LOAD_FILAMENT]
gcode:
    G91                 # 相対座標モード
    G92 E0.0            # フィラメント供給量をリセット
    G1 E120 F3000       # 120mmフィラメントを送る
    G92 E0.0            # フィラメント供給量をリセット
    G90                 # 絶対座標モード

[gcode_macro UNLOAD_FILAMENT]
gcode:
    G91                 # 相対座標モード
    G92 E0.0            # フィラメント供給量をリセット
    G1 E-120 F3000      # 120mmフィラメントを抜く
    G92 E0.0            # フィラメント供給量をリセット
    G90                 # 絶対座標モード
```


書いたマクロを活用して異常処置のマクロを記載します。
```filament.cfg
[gcode_macro EXTRUNOUTCODE]
gcode:
    PAUSE
    GO_TO_PARK_POSITION
    UNLOAD_FILAMENT
```
フィラメント抜き差しのコマンドで、一度に50mm以上動かそうとするとエラーが出るため`max_extrude_only_distance`を定義・適当な長さにしておきます。また、テスト用のメッセージから異常処置のマクロの記載へ変更します。
```printer.cfg
[extruder]
step_pin: PD15
dir_pin: PD14
enable_pin: !PC7
microsteps: 16
rotation_distance: 30.613
nozzle_diameter: 0.400
max_extrude_only_distance: 150.0
filament_diameter: 1.750
heater_pin: PB3
#heater_pin: PB4
sensor_type: EPCOS 100K B57560G104F
sensor_pin: PA2
control: pid
pid_Kp: 22.2
pid_Ki: 1.08
pid_Kd: 114
min_temp: 0
max_temp: 250

#### 中略 ####

runout_gcode: EXTRUNOUTCODE

```

これでフィラメント切れの際に自動停止するので、原因に対処して`LOAD_FILAMENT`、`RESUME`とTerminalに記入すれば印刷再開が可能なはずです。

# 今後
フィラメントの抜き差しなどでいちいちPCを操作し、OctoprintのTerminalにコマンドを入力するのがそろそろ面倒になってきました。次回は何かしら画面やボタン操作で3Dプリンタを動かせるようにしたいと思います。