魔術師Marlin
前回、Relicator2XのMightBoard故障による死をBigtreeTech社のSKR Pro 1.1を使って蘇生させる試みを始めた。8bit環境から32bit環境へ進化し、電源の容量も大幅にアップ、LEDも2個増えてpixel単位での制御が可能なものを取り付け、モータードライバーも最新のものを搭載し、その上ステッパーモーターまで新調した。完成すれば単に修理されたReplicator2Xが再生するのではない。大幅に機能が向上した状態で生まれ変わることになる。
新しくReplicator2Xの頭脳となったSKR Pro 1.1はファームウェアにオープンソースのMarlinを使う。自分が組んだCNC機器に合わせてconfigファイルを編集したうえでビルドして基板に書き込んで使う。SKR Pro 1.1のマニュアルに従い、VScodeでMarlinのソースコードを開いて、PlatformIOでビルドするとファームウェアのバイナリができる。これをMicroSDカードに入れて、SKR Pro 1.1に刺しこんで起動すると、ファームウェアを基板に書き込むことができる。Marlinはすごい。CoreXYから、デルタ型から、多色刷りの各種方式まで、いろんなパターンを網羅している。なので適切に設定してあげる必要がある。SKR pro用の設定はあらかじめMarlinに含まれているので適切に設定すれば動くはずだ。情報は全部GitHubのBigtreeTechのレポジトリのSKR proのプロジェクトで公開されている。
基本的に、基板の表面にプリントされている通りに線をつないでいけば問題がないはずだが、LEDをどこにつなぐか問題と、X軸とY軸のエンドストップスイッチを最大側にしたい問題の2点のところだけちょっと工夫が必要だった。
LEDをどこにつなぐか問題
BigtreeTechから発売されているSKR V1.4にはneoPixel対応LEDテープを接続する為の専用端子が用意されていた。だがSKR Pro 1.1には無い。その代わりに、DIY用にカスタマイズ可能なEXTENTION portが用意されている。LED用には、5VとGNDと信号用の3つピンがあればいい。EXTENSION-2の左端の3つのピンをLED用として使用することにして、前回購入したWS2812B Black PCBの60 IP30を結線した。具体的には下の図の赤枠のところだ。PD0をNeoPixel用にする。
Marlin側の設定は、configuration.hの下の方の以下の部分を編集した。NEOPIXEL_LEDのコメントアウトを外す。今回買ったWS2812BはRGBWではなくRGBなので、NEOPIXEL_TYPEにNEO_GRBにする。RGBWにすると光に白が混じってほんわかして柔らかい色になるが、今回はケースファンとして間接照明に使うので、ビビットな分かりやすい色の方がいいというチョイスである。気が変わったらあとからRGBWのLEDを買いなおすかもしれない。Replicato2Xの純正LEDは18個だったが、今回はパワーアップして20個になっているのでNEOPIXEL_PIXELSに20を設定する。さらに、PRINTER_EVENT_LEDSのコメントアウトを外しておくと、エラーが出たら赤くなったりプリントが終わったら緑になったり、プリンターの状態に合わせてLEDの色が変わるという豪華仕様になる。
// Support for Adafruit Neopixel LED driver
#define NEOPIXEL_LED
#if ENABLED(NEOPIXEL_LED)
#define NEOPIXEL_TYPE NEO_GRB // NEO_GRBW / NEO_GRB - four/three channel driver type (defined in Adafruit_NeoPixel.h)
#define NEOPIXEL_PIN PD0 // LED driving pin
//#define NEOPIXEL2_TYPE NEOPIXEL_TYPE
//#define NEOPIXEL2_PIN 5
#define NEOPIXEL_PIXELS 20 // Number of LEDs in the strip, larger of 2 strips if 2 neopixel strips are used
#define NEOPIXEL_IS_SEQUENTIAL // Sequential display for temperature change - LED by LED. Disable to change all LEDs at once.
#define NEOPIXEL_BRIGHTNESS 255 // Initial brightness (0-255)
#define NEOPIXEL_STARTUP_TEST // Cycle through colors at startup
// Use a single Neopixel LED for static (background) lighting
//#define NEOPIXEL_BKGD_LED_INDEX 0 // Index of the LED to use
//#define NEOPIXEL_BKGD_COLOR { 255, 255, 255, 0 } // R, G, B, W
#endif
/**
* Printer Event LEDs
*
* During printing, the LEDs will reflect the printer status:
*
* - Gradually change from blue to violet as the heated bed gets to target temp
* - Gradually change from violet to red as the hotend gets to temperature
* - Change to white to illuminate work surface
* - Change to green once print has finished
* - Turn off after the print has finished and the user has pushed a button
*/
#if ANY(BLINKM, RGB_LED, RGBW_LED, PCA9632, PCA9533, NEOPIXEL_LED)
#define PRINTER_EVENT_LEDS
#endif
加えて、configuration_adv.hでも、CASE_LIGHT_ENABLEのあたりをコメントアウトを外して、CASE_LIGHT_PINをPD0にしておく。これでNeoPixelのライトがケースライトとしても使用される。CASE_LIGHT_DEFAULT_ONをtrueにしておくととりあえず電源ONにしたときに光った状態になる。
/**
* M355 Case Light on-off / brightness
*/
#define CASE_LIGHT_ENABLE
#if ENABLED(CASE_LIGHT_ENABLE)
#define CASE_LIGHT_PIN PD0 // Override the default pin if needed
#define INVERT_CASE_LIGHT false // Set true if Case Light is ON when pin is LOW
#define CASE_LIGHT_DEFAULT_ON true // Set default power-up state on
#define CASE_LIGHT_DEFAULT_BRIGHTNESS 255 // Set default power-up brightness (0-255, requires PWM pin)
#define CASE_LIGHT_MAX_PWM 255 // Limit pwm
#define CASE_LIGHT_MENU // Add Case Light options to the LCD menu
//#define CASE_LIGHT_NO_BRIGHTNESS // Disable brightness control. Enable for non-PWM lighting.
#define CASE_LIGHT_USE_NEOPIXEL // Use Neopixel LED as case light, requires NEOPIXEL_LED.
#if ENABLED(CASE_LIGHT_USE_NEOPIXEL)
#define CASE_LIGHT_NEOPIXEL_COLOR { 255, 255, 255, 255 } // { Red, Green, Blue, White }
#endif
#endif
同じくconfiguration_adv.hのLED_CONTROL_MENUのコメントを外しておくと、LCDディスプレイのメニューからLEDライトを操作できるようになる。
/**
* LED Control Menu
* Add LED Control to the LCD menu
*/
#define LED_CONTROL_MENU
#if ENABLED(LED_CONTROL_MENU)
#define LED_COLOR_PRESETS // Enable the Preset Color menu option
#if ENABLED(LED_COLOR_PRESETS)
#define LED_USER_PRESET_RED 255 // User defined RED value
#define LED_USER_PRESET_GREEN 128 // User defined GREEN value
#define LED_USER_PRESET_BLUE 0 // User defined BLUE value
#define LED_USER_PRESET_WHITE 255 // User defined WHITE value
#define LED_USER_PRESET_BRIGHTNESS 255 // User defined intensity
#define LED_USER_PRESET_STARTUP // Have the printer display the user preset color on startup
#endif
#endif
これでLEDをどこにつなぐか問題が解決した。とってもきれいに光る。
ビルド領域の座標問題
3Dプリンターは、造形領域を3次元座標としてとらえることで立体的な造形を実現する。Replicator2XはホットエンドはZ方向には移動せず、ビルドプレートが上下することでZ軸の移動を実現している。そのため、ビルドプレートが一番高い位置にあるときZ軸の座標が最小となるので、ビルドプレートがホットエンドにぶつからないようにエンドストップが配置されており、エンドストップでビルドプレートの上昇がストップされた位置がZ軸座標0となる。
一方、Replicator2XのXY軸のエンドストップはY軸が奥側に、X軸が右側についている。エンドストップがZ軸と同様に最小を意味するとすれば、XY座標の原点(0, 0)は右奥となり、左手前へ行けば行くほど座標の値が大きくなることになる。しかし、スライサーなどの一般的な初期設定では、左手前が最小で右奥が最大となっているものが多い。Replicator2Xの純正の状態でもそうだったし、Makerbotのスライサーでも、Simplify3Dでも左手前が最小だ。
したがって、XY軸に関しては、エンドストップへのタッチが最大であるという事を意味するよう設定したい。具体的にはMarlinのconfiguration.hで以下の部分を設定する。Z軸用にはUSE_ZMIN_PLUGのコメントを外すことでエンドストップがMIN(最小)を意味するように設定する。逆にX軸はUSE_XMAX_PLUG、Y軸はUSE_YMAX_PLUGのコメントを外してエンドストップが最大を意味するように設定する。
ついでに、ENDSTOP_INVERTINGをtrueにしておく。ここでスイッチが入った時にストップするのか、スイッチが切れた時にストップするのかを切り替えることができる。これが反対になっていたら、初期位置に戻るHOMINGを行ったとき、エンドストップスイッチが効かずに限界以上に動こうとしてえらいことになる。そうならないために、g-codeのM119を使用してエンドストップの状態をモニターし、エンドストップを押した状態がTRIGERDになっていることを確認し、そうなっていなかった場合個々の値で反転させることができる。
// Specify here all the endstop connectors that are connected to any endstop or probe.
// Almost all printers will be using one per axis. Probes will use one or more of the
// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
//#define USE_XMIN_PLUG
//#define USE_YMIN_PLUG
#define USE_ZMIN_PLUG
#define USE_XMAX_PLUG
#define USE_YMAX_PLUG
//#define USE_ZMAX_PLUG
~中略~
// Mechanical endstop with COM to ground and NC to Signal uses "false" here (most common setup).
#define X_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Y_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Z_MIN_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
#define X_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
#define Y_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
#define Z_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Z_MIN_PROBE_ENDSTOP_INVERTING false // Set to true to invert the logic of the probe.
SKR Pro 1.1にはエンドストップスイッチ用の口は6つ用意されている。X-、Y-、Z-のそれぞれがエンドストップ用、E0、E1、E2がフィラメント切れセンサー用となっている。エンドストップ用には-がついていることから、MIN側で使われることが想定されている。
MarlinのSKR PRO用のピンアサインが定義されているpins_BTT_SKR_PRO_common.hを覗いてみると、E0、E1、E2のフィラメント切れ検知用ピンのそれぞれが、X_MAX_PIN、Y_MAX_PIN、Z_MAX_PINと兼用されている。X軸とY軸については、このファイルでフィラメント検知切れのピンはMAXと兼用するのではなくMINと兼用し、MAXはエンドストップ用に使うように設定すれば、エンドストップスイッチをMAX側として使用することができるようになる。よってX軸とY軸については、もともとの設定をコメントアウトして、MAXとMINの定数を入れ替える。
//
// Limit Switches
//
#ifdef X_STALL_SENSITIVITY
#define X_STOP_PIN X_DIAG_PIN
#if X_HOME_DIR < 0
#define X_MAX_PIN PE15 // E0
#else
#define X_MIN_PIN PE15 // E0
#endif
#else
#define X_MAX_PIN PB10 // X-
#define X_MIN_PIN PE15 // E0
//#define X_MIN_PIN PB10 // X-
//#define X_MAX_PIN PE15 // E0
#endif
#ifdef Y_STALL_SENSITIVITY
#define Y_STOP_PIN Y_DIAG_PIN
#if Y_HOME_DIR < 0
#define Y_MAX_PIN PE10 // E1
#else
#define Y_MIN_PIN PE10 // E1
#endif
#else
#define Y_MAX_PIN PE12 // Y-
#define Y_MIN_PIN PE10 // E1
//#define Y_MIN_PIN PE12 // Y-
//#define Y_MAX_PIN PE10 // E1
#endif
これで左手前が原点(0, 0)で右奥がMAXになり、尚且つHOMINGしたときに右奥のMAXをHOMEとする設定が出来上がった。
モーターのマイクロステップ問題
今回使っているステッパーモーターは全て1ステップで1.8°回る。つまり、1周360°まわすのに200ステップ必要となる。その1ステップをモータードライバーでさらにマイクロステップに分割することができる。今回使用しているTMC5160は最大256マイクロステップまで設定することができる。マイクロステップでステップを分割して1ステップ当たりの動きを小さくすればするほど、細かな動きができるようになるので造形できる解像度も高くなるが、トルクが失われてしまう。さらに、1mm当たりのステップ数の設定も数値が大きくなりボードが扱うステップ数の桁が大きくなって、桁あふれの可能性も高まる。ボードが1秒間あたりに扱えるステップ数には上限があり、限界を超えたステップ数を動かす必要が出た場合処理できない。その上、家庭用3Dプリンタで使われている程度の機械精度だとマイクロステップを265分割ほどに細かくしてもその細かさを伝えきれずに意味がないとも海外のWebフォーラムサイトのトピックで言われているのを目にしたことがある。
よって今回は、Marlin上でのマイクロステップは16として設定し、@section tmc_smartのINTERPOLATEの値をtrueとすることで、TMCのモータードライバー側でマイクロステップを256に補完する設定にする。以下は全部載せると長くなっちゃうので例としてX軸のモーターの設定だけ抜き出しているが、その下にあるY軸、Z軸、E0(エクストルーダー1)、E1(エクストルーダー2)の設定も同様に行う。ちなみにX_CURRENTの設定は820くらいが脱調もなくちょうどよかった。X_RSENSEはTMC5160の場合は0.075に設定する。
// @section tmc_smart
/**
* To use TMC2130, TMC2160, TMC2660, TMC5130, TMC5160 stepper drivers in SPI mode
* connect your SPI pins to the hardware SPI interface on your board and define
* the required CS pins in your `pins_MYBOARD.h` file. (e.g., RAMPS 1.4 uses AUX3
* pins `X_CS_PIN 53`, `Y_CS_PIN 49`, etc.).
* You may also use software SPI if you wish to use general purpose IO pins.
*
* To use TMC2208 stepper UART-configurable stepper drivers connect #_SERIAL_TX_PIN
* to the driver side PDN_UART pin with a 1K resistor.
* To use the reading capabilities, also connect #_SERIAL_RX_PIN to PDN_UART without
* a resistor.
* The drivers can also be used with hardware serial.
*
* TMCStepper library is required to use TMC stepper drivers.
* https://github.com/teemuatlut/TMCStepper
*/
#if HAS_TRINAMIC_CONFIG
#define HOLD_MULTIPLIER 0.5 // Scales down the holding current from run current
#define INTERPOLATE true // Interpolate X/Y/Z_MICROSTEPS to 256
#if AXIS_IS_TMC(X)
#define X_CURRENT 820 // (mA) RMS current. Multiply by 1.414 for peak current.
#define X_CURRENT_HOME X_CURRENT // (mA) RMS current for sensorless homing
#define X_MICROSTEPS 16 // 0..256
#define X_RSENSE 0.075
#define X_CHAIN_POS -1 // <=0 : Not chained. 1 : MCU MOSI connected. 2 : Next in chain, ...
#endif
ステップ数と移動距離
つづいて、造形物が意図したスケールで出力されるように、移動距離がちゃんと意図した分だけ動くように設定する。具体的には、各軸を1mm動かすのにステッパーモーターを何ステップ動かす必要があるかを計算して、DEFAULT_AXIS_STEPS_PER_UNITで指定する。Replicator2XはX軸Y軸はタイミングベルトで、Z軸はスクリューで動かしているので計算の方法が違う。
まずZ軸について計算する。Z軸はスクリューがくるくる回ることで上下する仕組みになっている。モーターについているスクリューは、2mmピッチの溝が4本渦巻いていた。よって一周回ると2mm×4本で8mm上下する。今回使うモーターでは1周が200ステップで、Marlin上では16マイクロステップで設定したので、Marlinの上では1周は200×16で3200ステップとなる。3200ステップで8mm動くということは、1mm動くためには、3200ステップ÷8mmで400ステップ必要であるという事になる。
X軸とY軸には、山の間隔が2mmピッチのタイミングベルトが使用されている。これをすべてのシャフトで20歯のプーリーで動かしていた。モーターが1周すると2mmピッチの山が20個動くことになるので、2mm×20歯で40mm動くことになる。Z軸の時見たのと同様の計算で、Marlin上での1周のステップ数は3200ステップだったので、1mm動くためには、3200ステップ÷40mmで80ステップ必要という事になる。
エクストルーダーギアについては、ギア部分の直径が10.56mmなので円周は10.56mm × 3.14で約33.1584mm。1周で約33.1584mmなので、1mm動くためには、3200ステップ÷33.1584mmでざっくり、約96.5ステップとなる。
これらの数値を、configuration.hのDEFAULT_AXIS_STEPS_PER_UNITの値に書き込んでいく。あくまでこれらは論理的な数値で、タイミングベルトは厳密に2mmピッチじゃなかったりするので、後で実際に動かしてみて機体の誤差を加味して実際の値を調整していく必要がある。
/**
* Default Axis Steps Per Unit (steps/mm)
* Override with M92
* X, Y, Z, E0 [, E1[, E2...]]
*/
//#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 96.5 }
なんだか長くなってしまったので今日はここまでにしたい。次回は、残りのMarlinの設定をやって、実際に動かしていくあたりが書けたらいいなぁと思っている。次回も言葉はいらぬ心意気のみ持ち来たれ!