TouchDesignerとGrblでやる貧乏人のためのステッピングピングモーター制御入門

この記事は[TouchDesigner Advent Calendar 2020](https://qiita.com/advent-calendar/2020/touchdesigner)の4日目の記事です。

前日（3日目）の記事は @shks さんの[「ParsecTOP : ParsecをTouchDesignerで使って低遅延60FPSストリーミング送受信」](https://qiita.com/shks/items/411cc41ae69d9551d31b)です。

翌日（5日目）の記事は@camikura さんの「[SHOTOKU VRクレーンをTouchDesignerから使う](https://qiita.com/camikura/items/fbe53525dd11488f698d)」です。

---
こんにちは。フリーランスでハードウェア制御開発などをしているユースケと申します。
皆さんはTouchDesignerでビジュアルを作るか、ハードウェア制御ではDMXで照明制御などをする方が大半だと思います。どうもハードウェア制御は電子回路やマイコンプログラミングが絡んでくるのでとっつきにくいかと思いますが、DMX以外にも（比較的）手軽にTouchDesignerからハードウェア制御をする方法もあるんですよね。今回はチープにステッピングモーター制御する方法を書きたいと思います。
![IMG_2185.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/cb107b9c-a599-1b5b-6e65-a34b40705bfa.gif)
↑なんかモーター制御したときにテープ回すのが流行ってるみたいなのでしてみた。


# 最初に
最近[Ponoor Experiments](https://ponoor.com/)の堀尾寛太さんの作られた高性能ステッピングモータードライバーの[STEP400](https://ponoor.com/products/step400/)がクラウドファンディング成功しました。（おめでとうございます！）とても使いやすい、かつ高性能なデバイスなのでクライアント案件等であればそちらをご利用ください。この記事は個人製作で、そこまでバジェットがないけど気軽にTDからモーターで何か制御してみたいという（僕のようなビンボーな）方向きです。
[STEP400についてはこちら](https://ponoor.com/products/step400/)
今回使用するGrblは元々DIYの[CNCマシン](https://ja.m.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E6%95%B0%E5%80%A4%E5%88%B6%E5%BE%A1)の制御のために書かれたものですが、Gｰcodeというスクリプトをシリアル経由で通信することで比較的簡単にステッピングモーターを制御できます。また、制御地点を繋ぐようにスムーズに速度変化をしてくれるため（まあまあ）スムーズな速度変化が実現できます。その一方でCNC制御のためのソフトなので位置制御しかしてくれず、モーターをずっと回転させるような回転数制御には向いていません。思ったように制御するためには設定のちょっとした手間はかかりますが、位置制御くらいであればマイコンプログラミングをしなくてもステッピングモーターが制御できます。

## 準備
全てオープンソースソフトウェアです。（TouchDesigner以外…）
- [ArduinoIDE](https://www.arduino.cc/en/software) おなじみのArduino。
- [Universal Gcode Sender Platform](https://winder.github.io/ugs_website/download/) 本制御には使わないが、接続確認、設定のために使用。
- [Grbl](https://github.com/gnea/grbl) シリアルで送られてきたGCodeをパースし、ステッピングモーターを制御するソフトウェア。読み方はよくわからない。（グルーブル？）

### 必要機材
- [Arduino Uno](https://www.switch-science.com/catalog/789/)
- [CNC Shield](https://www.amazon.co.jp/HiLetgo-2%E5%80%8B%E3%82%BB%E3%83%83%E3%83%88-%E6%8B%A1%E5%BC%B5%E3%83%9C%E3%83%BC%E3%83%89-%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89-Arduino%E3%81%A8%E4%BA%92%E6%8F%9B/dp/B01D2HL9T8/ref=sr_1_6?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=cnc+shield&qid=1606620119&sr=8-6)
- (ステッピングモーター（NEMA17型の12Vくらいのやつ。1回転あたりのステップ数が200のものが多い）[例えばこれとか](https://www.amazon.co.jp/Quimat-17%E3%82%B9%E3%83%86%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%83%A2%E3%83%BC%E3%82%BF-3D%E3%83%97%E3%83%AA%E3%83%B3%E3%82%BF%E3%83%BC%E7%94%A8-36-8oz-3D%E3%83%97%E3%83%AA%E3%83%B3%E3%82%BF%E3%83%BC/dp/B06XRFGTR4/ref=sr_1_9?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=AQVNXLO0K2DR&dchild=1&keywords=%E3%82%B9%E3%83%86%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%83%A2%E3%83%BC%E3%82%BF%E3%83%BC+12v&qid=1606620154&sprefix=%E3%82%B9%E3%83%86%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%83%A2%E3%83%BC%E3%82%BF%E3%83%BC%E3%80%80%EF%BC%91%EF%BC%92%2Caps%2C247&sr=8-9)
- (ステッピングモータードライバー（[A4988など](https://www.pololu.com/product/1182)）
- [12V電源](https://www.amazon.co.jp/Salcar%E3%80%90PSE%E5%8F%96%E5%BE%97%E6%B8%88%E3%81%BF%E3%80%91AC-%E9%9B%BB%E6%BA%90%E3%82%A2%E3%83%80%E3%83%97%E3%82%BF%E3%83%BC-%E6%9C%80%E5%A4%A7%E5%87%BA%E5%8A%9B24W-%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81%E3%83%B3%E3%82%B0%E5%BC%8F-%E5%A4%96%E5%BE%845-5mm%C3%97%E5%86%85%E5%BE%842-5mm/dp/B08CNDKN9F/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=3POU04IINBU4Z&dchild=1&keywords=12v+%E9%9B%BB%E6%BA%90&qid=1606620401&sprefix=12v%2Caps%2C278&sr=8-5)
- USB-Bケーブル
- [ジャンパピン](https://www.amazon.co.jp/%E3%82%B5%E3%83%B3%E3%83%AF%E3%82%B5%E3%83%97%E3%83%A9%E3%82%A4-TK-JMP1-%E3%82%B8%E3%83%A3%E3%83%B3%E3%83%91%E3%83%94%E3%83%B3/dp/B00076YM1K/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=%E3%82%B8%E3%83%A3%E3%83%B3%E3%83%91%E3%83%94%E3%83%B3&qid=1606620460&sr=8-5)

とりあえず一式そろってる[こういうもの](https://www.amazon.co.jp/Quimat-Arduino%E3%81%AB%E4%BA%A4%E6%8F%9B-CNC%E3%82%B7%E3%83%BC%E3%83%AB%E3%83%89V3-A4988%E3%83%89%E3%83%A9%E3%82%A4%E3%83%90-17%E3%82%B9%E3%83%86%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%83%A2%E3%83%BC%E3%82%BF/dp/B06XS6XH4R/ref=sr_1_12?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=a4988&qid=1606400472&sr=8-12)も売ってます。おっと、これだとジャンパピンと12V電源は追加で必要ですね。

### タームの解説
- [Gcode](https://en.wikipedia.org/wiki/G-code): 主にCNC（3Dプリンタも）の制御に使われるスクリプト。制御対象により色々拡張されている。
- [ステッピングモーター](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%86%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0%E3%83%A2%E3%83%BC%E3%82%BF%E3%83%BC):英語名Stepper Motor。正確な位置制御や回転数制御に適している。動作音は比較的大きい。効率は低い。NEMA17型というサイズで様々な出力のものが入手できる。他にも工業用のデカいものから模型用の小さいものまで色々ある。
- マイクロステッピング:ステッピングモーターは1回転あたりのステップが決まっており（例えば1回転200パルスなど）それにより1回転の解像度が決まってしまうが、入力するパルスをPWM制御することによりそれより細かい解像度で回転が制御できる。マイクロステッピングの単位は1/2, 1/4となり、200ステップのモーターの場合はそれぞれ400ステップ、800ステップの細かい制御ができる。ただしその分出力トルクが落ちるので注意。

## セットアップ

### Grblダウンロード、焼き込み
- [ArduinoIDE](https://www.arduino.cc/en/software)をダウンロード、インストールする
- [Grblプロジェクト](https://github.com/gnea/grbl)をダウンロードする
- Grblプロジェクトのコンパイル、焼き込み。手順については[こちらを参照](https://github.com/gnea/grbl/wiki/Compiling-Grbl)。Arduinoのスケッチを焼きこむのと同じ手順です。

### 配線
- CNC ShieldとモータードライバをArduinoに取り付け（電源切ってね！）

    - Arduino UnoからUSBケーブルを抜く
    - CNCShieldをArduino Unoの上に差し込む
    - マイクロステッピングを制御するためにジャンパピンをショートする
        - とりあえず１個だけモーター制御するので一番左上、X軸用のドライバだけセットします。他も同様。
        - 右下の赤いソケットはZ軸と同じ信号が入るので注意、4軸制御はできません。3軸まで。
    - ジャンパピンは1/8となるように設定。M0, M1だけつなげてM2を開放したままにする。
    - 詳しい設定は[こちらに](https://www.pololu.com/product/1182)
    ![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/e1aff4ff-df1b-7f84-4b55-74cca28f7ba4.jpeg)
        - ジャンパピンがない場合もマイクロステッピングができないだけで動作はする。ただし動きは荒くなる。
    - モータードライバを1のソケットに差し込む（極性に注意）
![ECD9D2D6-5281-491E-A4D9-D6CCDB940E9D.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/93e47525-ee63-6566-4a07-a7cec3a2e73e.jpeg)
![25B57271-A911-4FEA-BB1F-B3B9A0DE470E.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/3fce7415-ef1f-4b30-604e-635c3ceda433.jpeg)
- モーターとCNCシールドを繋ぐ
    - 今差したモータードライバーの右にあるピン（4ピン）にモーターからのケーブルを接続
    - 逆接続もできてしまうが、しても逆回転するだけなのでとりあえず極性は気にしないでよし
![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/f07c9ad7-906c-e052-fc34-a90a167d2f43.jpeg)
    - 本来はここでモーターの電流設定もする必要があるが今回はとりあえずテストするため省略。[こちらのPololuのページ](https://www.pololu.com/product/1182)に詳しく設定する方法があるので長時間稼働させる際など、必ず設定するようにしてください。設定していないと異常に発熱してしまう可能性があります。
    - なおモータードライバーA4998にはセットでヒートシンクがついてくるのですが、これが基板上の端子と接触するとショートする可能性があるため、取り付ける際はほかの部品に接触していないか、よく確認して下さい。


### Grblのセットアップ
- [Universal Gcode Sender Platform](https://winder.github.io/ugs_website/download/)をダウンロード＆インストール
- CNC Shieldに12V電源をつなぐ。USBケーブルをArduinoに再度つなぐ
- Universal Gcode Sender（以下UGS）を起動する
    - Winだと実行ファイルは */bin/ugsplatform64.exe* にある。Macでも同じはず 
![ugs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/137b4ae8-5ea4-b7be-d91f-18a4bbf90c71.png)

- シリアルポートからデバイスを選択する
- 通信速度を115200に設定する
![ugs_Interface.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/2e6f31f5-05c1-6121-3cab-c98f42e94ff8.png)
- 接続ボタンを押す。接続メッセージがコンソールに出たらOK
![ugs_msg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/81adcda6-f314-1b05-1a23-b7abc788b4aa.png)

- 1mmあたりのステップ数設定
    - 使用するステッピングモーターのステップ数を調べる。（必ず載っているはず）わからなければ200。Amazonの表記とかは結構適当なので注意。
![step_rev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/473f8fba-b5b3-00f3-0290-8e2220b4e7a9.png)

    - CNCであれば変速比を考慮する必要があるが、今回はテストのため、とりあえず回すだけであればとりあえず200と設定する。設定単位はSteps/mmとなっているため1mm動かすには200ステップ必要ということになる。
    - Command入力欄に*$100=200*と入力してEnter
    - OK応答が返って来ることを確認
![s100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/bde5d2f5-1dcb-17f7-49be-cf1479a909bc.png)

- 最大速度設定
    - 大きめにしておいて問題なし。*$110=5000* と入力。5000mm/minとしました。
- 最大加速度設定 
    - あまり大きくすると急激に速度変化する。50mm/s2程度で良い
    - コンソールより$120=50と入力
- ステッピングパルス関係のチューニング
    - 少し専門的になりますが、ステッピングモーターの上限スピードはコントローラーの出力するステッピングパルスの幅や追従するためのステッピングモーターのパワーで決まります。Grblはデフォルトで10μSecなのですが、A4498は最小で1μSecまでコントロールパルスを受け付けるため、もう少しチューニングしてみます。
    - コントロールパルス幅3μSec　*$0=3*
    - パルス遅延5mSec *$1=5*
![s1s5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/ed306f94-8666-79b2-9de7-af0c908fbf3d.png)

- セッティングはこんなところにしてテスト：移動量の確認
    - 上でマイクロステッピングを1/8にしているため、モーター一周には1600ステップ必要となります。1mmの移動に必要なステップ数が200のため、１回転するには制御上、8mm移動している計算になります。
    - StepXYに8と入力、制御単位がmmであることも確認
    - Feedrateは3000くらいにする
![steptest.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/28d6d913-3c2a-79af-7290-5a7b9cca9ce4.png)

- 左右ボタン（X- X+）を押してモーターが１回転することを確認
- シリアル接続を切ってUGSを終了する。設定はこれでとりあえず完了。このあたりのパラメータは動かす対象によって随時調整し直す必要あり。セッティングお疲れさま！

## TouchDesignerからの制御
ここからようやくTouchDesignerが登場。

### 使うG-Code
実は先ほどUGSでモーターを回したとき、コンソールにはこんなG-Codeが出力されていました。
![gcode_rotate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/fe167943-8d5b-13e0-8454-c46ee62bf6f0.png)
*G21G91G1X8F3000*は以下のコマンドで成り立っています。
> G21: mm単位系
> G91: 相対座標
> G1X8F3000: モーションコマンド、X軸に+8単位、フィードレート（スピード）3000で移動

同じく*G90G21*は、G90が絶対座標系なので、mm単位系で絶対座標系に戻す、という命令ですね。
今回使うのはこれと、あと現在位置を返してくれるコマンド（後述）だけです。これだけの命令でとりあえず制御できるので結構らくちんですね。

### TouchDesignerから動かしてみる
- SerialDATを作って、UGSで設定したのと同じシリアルポート番号を設定、通信速度は115200bps
- エラーが出ずに、SerialDATにGrblからのメッセージが出てくれば接続成功
![TD_openSerial1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/613e711d-e9df-c95e-698b-bbbd8e011e8e.png)

- TextDATを作り上記の１回転するコマンド、G1X8F3000を入力します。
- 次にもう一つTextDATを作り、G-Codeの入っているテキストを参照してSerialDATに書き込むようにします。
> gcode = op('text1').text
> op('serial1').send(gcode, terminator = '\r\n')

![TD_testrun.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/06c1ca0d-dfd5-3a03-d844-bfe9b4445689.png)

- コードを書き込んだTextDATを右クリックから実行(Ctrl + r)します。一回転しましたか？
- というわけで簡単に制御できるのがわかったところでCHOPから制御してみましょう。
- Slider COMPからMathCHOPで出力レンジを-4 ～ 4にしてChopexecDatに渡します。
- ChopexecDatはonValueChangeをオンにしたうえで以下のコードをonValueChange内に書いておきます。speedはここでは1500にしておきました。

> speed = 1500
> nextPosition = val
> code = 'G1X{0}F{1}'.format(nextPosition, speed)
> op('serial1').send(code, terminator = '\r\n')

![TD_simpleSlider.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/22dcaba9-a67f-b582-158a-736c8d52155d.png)

- スライダーをぐりぐりやっていただくとモーターが追随してきましたか？ただし操作に対して結構遅延するのに気づかれたと思います。また動かしすぎるとGrblがこのようなエラーを吐いてきたり、場合によってはG-Code用バッファがオーバーフローしてクラッシュします。
![TD_invalid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/d783a7cf-699d-7a63-54f9-e8080315a420.png)
- エラーコード24はG-Codeの公式のエラーではなくGrbl独自のエラーで以下のようにXYZ軸の指定を必要とする命令がブロック上に二つ以上あったと[説明](https://github.com/gnea/grbl/wiki/Grbl-v1.1-Interface)があります。ただしモーションコマンドG1はXYZ座標で毎回指定しなくてもよく、以下のエラーはバッファオーバーフローにより引き起こされたものと思われます。

> **24** Two G-code commands that both require the use of the XYZ axis words were detected in the block. 

- 今送っているコマンドをTextDatに出力してみるとFloatの有効数字があまりに大きいため適当な値で切り捨ててやります。Grblの公式ページにはmm単位の場合小数点3桁まで送るとよいとあるので、そこまでをキャストしてあげます。
![TD_simpleSlider_command.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/de0b4dd8-164c-a22b-05d1-0581b6ce9d28.png)
![TD_simpleSlider_command_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/d2e323ab-98ff-541a-d419-e2a4dbaefd27.png)

> Before -> code = 'G1X{0}F{1}'.format(nextPosition, speed)
> After -> code = 'G1X{0:.3f}F{1}'.format(nextPosition, speed)

- また、制御位置を60FPSで送る必要は全くないため、ResampleDATでSampleRateを10程度に落とします。
![TD_simpleSlider_improved.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/99db83ec-7cff-a4c8-eda5-cbf3e1b68c80.png)
- これでだいぶエラーは改善したかと思います。CNC制御ソフトなので制御点をすべて通過する制御となるため、遅延はある程度仕方ありません。

### 位置情報を取得する
とりあえず動かせるようにはなったのですが、もう少し改良してみましょう。モーターの追随速度が問題になりそうなため、現在のモーター位置をまず取得してみましょう。

- LfoCHOPで10Hzのパルスを作り、ChopexecDatでOnになったときに位置リクエストコマンド*?*を送るようにします。SerialDatに位置情報が帰ってくると思います。

> op('serial1').send('?', terminator = '\r\n')

![TD_checkPosition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/801d7506-13ed-8966-8dcf-60ad549a24de.png)
![TD_positionalresponce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/d0812c46-7f99-6d0c-5ee5-9ed4623a06c0.png)

- 上のメッセージではMpos、マシンポジションがx軸-0.77であるとわかります。WPosはWorking Positionで、CNC加工時にマシン原点からのオフセットを入れられるものなのでここでは無視します。
- メッセージから現在のポジションを常時読み出すようにしましょう。ConvertDATをつないで、メッセージ中のセパレータ、< > , : \t　をSplit Cells atに入れます。 
- DATexecuteで、DATデータに変更があった場合にConstantCHOPの値を上書きするようにします。
![TD_parse_message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/685b5a69-9de2-e4e4-87ea-eb1cd1df9493.png)

- この後は制御する対象によって違うのですが、位置の指示（resample1）と現在位置の差分を取って、差分が一定以上になるとLogicCHOPが入るロジックを作ってみました。最後のNullは制御位置を送っているchopexec1を入り切りしています。（うーん。でも現在位置を制御に取り入れても遅延要素が強すぎて有効じゃないな。デモだしまあいっか！）
![TD_generateDiff.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/312a6534-8665-1aa3-4e8d-93bd3223c122.png)

### 制御値にフィルタをかけて追随性能を良くする＆バッファオーバーフロー対策
目標位置を順次追っていくGrblをここで使ってしまう時の問題は、例えばノイズ的に目標値に1点だけ離れた点が入ってきた場合、モーターが律儀にその点まで移動して、また戻ってくるような挙動をすることです。（CNCだったら当たり前ですよね。）この時のモーターの移動時間は制御遅れにつながり、また、その間にも次の目標位置がたまり続けてしまうため上記のバッファオーバーフローも引き起こしかねません。よくあるモーターのサーボ制御の場合は移動する目標値を逐次追っていけるのよう[PID制御](https://ja.wikipedia.org/wiki/PID%E5%88%B6%E5%BE%A1#:~:text=PID%E5%88%B6%E5%BE%A1%EF%BC%88%E3%83%94%E3%83%BC%E3%82%A2%E3%82%A4%E3%83%87%E3%82%A3%E3%83%BC%E3%81%9B%E3%81%84,%E6%96%B9%E6%B3%95%E3%81%AE%E3%81%93%E3%81%A8%E3%81%A7%E3%81%82%E3%82%8B%E3%80%82)を組んでいるのですが、これは信号処理的に見ればフィルタを入れていることと違いはありません。なので今回は入力信号に対してFilterCHOPを通してあげることで、急峻な目標値の変化があってもモーターが追随できる速度で信号を渡してあげられるようにしました。要はローパスを入れたわけです。
入力信号をNoiseCHOPにし、モーターが追いつけない程度の早い周期のノイズを入れてあげてもモーターが、バッファも溜めずについてきてくれるようになります。なお、バッファが溜まってしまっているか確認するには入力のNoiseCHOPを止めてみます。入力を止めてもモーターがしばらく動き続けているようであれば、バッファが溜まってしまっていると判断できます。（そしてそのまま動かしておくと多分Grblがクラッシュします）
![TD_inputFilter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/882321/c8b26b23-5b52-81ed-fa88-082378a34085.png)

[サンプルファイル](https://drive.google.com/file/d/1HnM90uhyDEL0cnV6rP7jdwegBDU5SrDl/view?usp=sharing)もご覧ください。

## 結論
- 最初に挙げたステッピングモータ制御ボード、STEP400とは圧倒的に機能が劣りますが、少数のモーターを、3000円程度で簡易的な制御ができるのは魅力です。
- また、制御のためのG-Codeはとても単純なうえマイコンプログラミングも不要です。
- 複数のモーターを制御することも可能ですが、フィードレートの指定とは、XY座標での移動距離の指定となるため、X, Yで２個のモーターを、1モーターあたり3000で動かしたい場合、フィードレートの指定は sqrt(3000^2 + 3000^2) = 4243となりますのでご注意ください。
- このようなシステムをもし常設で使うような場合は、シリアルポートの番号が何かの拍子に変わって動かなくなってしまうリスクがあります。（実際何回か遭遇しています）
- 複数Grblを制御することも出来なくはないのですが、制御の性質上Grbl同士が同期してくれません。通信および制御上の遅延が気になるほど差が出てしまうことがあります。
- これで制御が満足できない場合は自分で制御コードを書くか、[STEP400](https://www.crowdsupply.com/ponoor-experiments/step400)を買いましょう！
- G-Codeではロボットアームとかも制御できます。こんどは3DプリンタにG-Codeをライブでぶち込んで悪いことしてみたいなぁ。

---
動かねーぞ、不明点等ありましたら hi@yuskegoto.netまたはTwitter: [@donneidecker](https://twitter.com/donneidecker)まで。