Arduinoを使ってPCからDCモーター制御(Node.js編)

# Arduinoを使ってPCからDCモーター制御(Node.js編)

　[Arduinoを使ってDCモーター制御](https://qiita.com/fumimix/items/bf3d644d3fa3d4075c80)の続きです。モーターを回すことに成功したので、次はモーターを外部からの操作で制御することにチャレンジしてみます。

　外部記事[^NJW]を参考に、Node.jsを使ってArduinoをコントロール→モーターの制御までやってみました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ArduinoというAVRマイコン、入出力ポートを備えた基板が面白いので、モーター制御するところまで遊んでみた。<br>このモーターの先を巻取りカーテンに挿して、Wifi経由で遠隔操作してリモートからカーテンの開け閉めとかできそう。<a href="https://t.co/G0rZRlrfS8">https://t.co/G0rZRlrfS8</a></p>&mdash; いわもと　よしふみ (@yosi_iwa) <a href="https://twitter.com/yosi_iwa/status/977910236638883840?ref_src=twsrc%5Etfw">March 25, 2018</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

　モータの回転をWeb経由で制御する仕組みは以下のようになっています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/151198/7ac42732-bcc6-b013-394d-058a892f9a4d.png)


## 環境
　以下のとおりです。
- PC:Windows 10 Fall Creators Update
- Arduino-UNO
- Arduinoビギナーのためのモーター・リレー・ブザー制御入門

　[前回の続き](https://qiita.com/fumimix/items/bf3d644d3fa3d4075c80)から、引き続きこの基盤を使ってモーターの外部操作を試みます。



## 下準備

### Node.jsのインストール
　[Node\.js](https://nodejs.org/en/)からダウンロード→インストールでOKです。今回は9.10.1をインストールしました。


### Johnny-five のインストール
　コマンドプロンプトより、C:\から"npm install johnny-five"します。
　インストール前に、"npm init"しておき、package.jsonを作成しておくと良いです。
　他のディレクトリからインストールしようとすると、そのディレクトリからの相対パスでnode_modules以下ができてしまうので注意。
　間違った場所にnode_modulesができても、node_modulesごと消して再インストールで良さそうです。



```cmd:インストール例
C:\Users>cd c:\
c:\>npm install johnny-five

> serialport@6.0.5 install c:\node_modules\firmata\node_modules\serialport
> prebuild-install || node-gyp rebuild

（中略）

c:\node_modules\serialport\build\Release\serialport.node successfully
prebuild-install info install Successfully installed prebuilt binary!
npm WARN saveError ENOENT: no such file or directory, open 'c:\package.json'
npm WARN saveError EPERM: operation not permitted, open 'c:\package-lock.json.769635733'
npm WARN enoent ENOENT: no such file or directory, open 'c:\package.json'
npm WARN !invalid#1 No description
npm WARN !invalid#1 No repository field.
npm WARN !invalid#1 No README data
npm WARN !invalid#1 No license field.

+ johnny-five@0.14.2
added 197 packages in 10.887s
```

　以下のようなWARNINGが出てしまった場合、package.jsonが生成されていないことが原因なのですが、インストール自体が成功している場合は次の手順に進んでも構いません。

```cmd:packagel.jsonに関するWARNING
npm WARN saveError ENOENT: no such file or directory, open 'c:\package.json'
```

### Arduinoライブラリ設定
　[GitHub \- firmata/arduino: Firmata firmware for Arduino](https://github.com/firmata/arduino)の右上Clone or downloadよりDownload ZIPを選択、ZIPモジュールをダウンロードします。
　Arduino IDEを起動し、スケッチ→ライブラリをインクルード→.ZIP形式のライブラリをインストールのあと、ダウンロードしたZIPモジュールを指定してインストールすれば使えるようになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/151198/0a5a6c5e-3a45-e261-033c-27481ea832b5.png)

　その後、スケッチ例→Firmata→StandardFirmataと選択し、StandardFirmataのコードを表示させ、マイコンボードに書き込み準備完了です。
　書き込み完了後、Arduino側でNode.jsからの命令を受け付けるようになります。一度書き込みが済んでしまえば、Arduino側に新しいコードを書き込まなくても色々なことを実行できるのは便利ですね。

### Hello wordを試す
　準備ができたら、[Johnny\-Five Hello World](http://johnny-five.io/#hello-world)を試してみます。
　Windowsの場合ポート指定が必要なため、サイトのソースをそのまま実行できないため注意が必要です。
　サイトの図のように基盤にLEDを指していなくても、基板上のオレンジLEDの点滅を確認できます。

```javascript:基板上のLED点滅
var five = require("johnny-five");
var board = new five.Board({port:'COM5'});			// Windowsの場合、必ずポートを指定する

board.on("ready", function() {
  console.log("Ready!");
  var led = new five.Led(13);

  led.blink(500);

});
```


## Node.jsでモーター制御
　Johnny\-FiveのDCモーターのサンプルコード[JavaScript Robotics: Motor \- Directional](http://johnny-five.io/examples/motor-directional/)を例に、モーターを回してみるコードを書いてみます。
　ソースコードはこのような感じになります。モーターを5秒間正回転させ、その後5秒間逆回転し、停止させます。
　環境によってはモーターの制御がうまくいかない場合があるかもしれません。その場合は、pins:の設定を見直してみてください。
　また、この環境だけの可能性がありますが、motor.forward()した後、モーターの回転を止める際にmotor.reverse()→motor.stop()の順で命令を送らないとモーターが止まらないため、ソースコードがそのような記載になっています。

- [MotorControlTest/motor\_test\.js](https://github.com/yoshiiwa/MotorControlTest/blob/master/motor_test.js)

　ちなみに、プログラムによりモーターが一通り動いた後、```>>```プロンプトに続けてモーター制御のコマンドを入力すると、モーターの正回転・逆回転・停止を直接制御可能です。

```cmd:コマンドを入力することでモーターの動きを制御
>> motor.reverse(80)
>> motor.stop()
```


## Web経由でモーターの制御をするための準備
　PCからモーターの制御をするところまでできたので、次はWeb経由でモーターの制御をしてみます。
　Webから以下のようにフラグ情報を送ってあげて、Arduino側で受け取ったらフラグに応じた処理をさせてみます。

- 1:正回転
- 0:停止
- -1:逆回転

　Web経由での情報の受け渡しにはGoogle Spreadsheetを使う方法を採用しました。[^GSW]
　ソースコードは[MotorControlTest/MotorControlApp\.gs](https://github.com/yoshiiwa/MotorControlTest/blob/fa7877a07878cf17aeea95bbbadd16cfc06b41a0/MotorControlApp.gs)に記載しました。各関数の動きは以下のとおりです。
　コードが一通りできたら「ウェブアプリケーションとして導入」します。

- doGet(e) : A1セルの値を取得
- setFlag(e) : A1セルを1⇔-1に切り替える
- setStopFlag(e) : A1セルに0をセット

　次に以下図のように、図形にスクリプトを割り当てます。図形を押すと、1・0・-1の切替ができるようにしてみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/151198/ac1b2b87-4b59-5f2e-0d7e-99eb89b5cb83.png)

　Node.js側では[指定したURLのBodyを取得するコード](https://qiita.com/fumimix/items/36d0b7f179a9d6d62e76#%E7%89%B9%E5%AE%9A%E3%81%AE%E5%87%A6%E7%90%86%E3%82%92%E4%B8%80%E5%AE%9A%E9%96%93%E9%9A%94%E3%81%A7%E3%82%84%E3%82%8A%E3%81%9F%E3%81%84)を実行します。
　上記の公開したアプリのURLを変数として実行させると、A1セルの値が返ってきます。図形をクリックしてA1の値を更新してみます。A1セルの変更がNode.js側でも拾ってこれたので、いよいよWeb経由での制御に進みます。


## Web経由でのモータの制御

　ここまで来たら「Node.jsでモーター制御」と「Web経由でモーターの制御をするための準備」を組み合わせて、[MotorControlTest/motor\_control\.js](https://github.com/yoshiiwa/MotorControlTest/blob/master/motor_control.js)
というコードを書いてモーターの制御をスマホ経由で実施してみました。
　Goole SpreadSheetの図形はアプリからクリックができないようなので、FirefoxのPCモードから対象のスプレッドシートを開いてボタンを押しています。
　スプレッドシートの値の変更と、モーターの回転が連動していることが確認できました！

```cmd:動かしたときのログ
>node motor_control.js
1522641390473 Connected COM5
1522641392494 Repl Initialized
>>
2018/04/02 12:56:32     Motor Cotroll Start!!
2018/04/02 12:56:32     Motor Stop!!
2018/04/02 12:56:32     Motor Stop!!
2018/04/02 12:56:32     Motor Reverse!!
2018/04/02 12:56:32     Motor Stop!!
2018/04/02 12:56:37Flag:0
2018/04/02 12:56:37     Motor Stop!!
2018/04/02 12:56:37     Motor Reverse!!
2018/04/02 12:56:38     Motor Stop!!

（中略）

2018/04/02 12:57:25Flag:-1
2018/04/02 12:57:25     Motor Stop!!
2018/04/02 12:57:25     Motor Reverse!!
2018/04/02 12:57:25     Motor Start!!

（中略）

2018/04/02 12:58:07Flag:0
2018/04/02 12:58:07     Motor Stop!!
2018/04/02 12:58:07     Motor Reverse!!
2018/04/02 12:58:08     Motor Stop!!

(To exit, press ^C again or type .exit)
>>
1522641489593 Board Closing.
```



## 参考文献

[^NJW]: [Node\.js \+ Johnny\-Five \+ windows で Arduino を動かす \- JH1LHVの雑記帳](http://jh1lhv.hatenablog.jp/entry/2016/01/26/213606)
[^GSW]: [Google Spreadsheet を簡易 Webサーバーとして動かして、手軽にWebHookを受け取る方法 \- Qiita](https://qiita.com/kunichiko/items/7f64c7c80b44b15371a3)



- [Firmataを使ってNode\.jsからArduinoを制御してみよう \- Qiita](https://qiita.com/dll7/items/922265e34766938f1a72)
- [Windows Remote Arduinoを試す \- Qiita](https://qiita.com/matsujirushi/items/54f079a41baeeb70adf7)
- [javascriptで日付フォーマッタ \- Qiita](https://qiita.com/egnr-in-6matroom/items/37e65bb642d2e158804c) 
- [スプレッドシートに図形でボタンを作成しGASを実行＆トリガーを使ったメニューの追加：Excel VBAプログラマーのためのGoogle Apps Script入門（9） \- ＠IT](http://www.atmarkit.co.jp/ait/articles/1708/14/news011.html)
- [Node\.jsで定期的に実行 \- Qiita](https://qiita.com/tq_jappy/items/c5ebfdb30dc90617414f)