PC上のNode-REDではSerial inノードとSerial outノードを使って有線接続のSerial通信を行うことができますが、現時点のNode-RED MCUではSerial通信を行うノードは用意されていません。将来的には本家から公式にサポートされたノードが提供される可能性もありますが、それまでの間に機能は限定されていても臨時で使えるようなものがFunctionノードを使って簡単にできないかな?と試した内容がこの記事になります。
できたこと
Function ノードを使って「mcu serial in」と「mcu serial out」を作成し、mcuデバイスとPCの間でStringのコマンドを送受信して、PCからmcuデバイスに取り付けたLEDのON/OFFをコントロールすることができました。
ポート設定もFunctionノード内で行う、など簡易型で制限もいろいろありますが、ノードの使いかたとしては割とPC上のNode-REDに用意されているSerial in/outノードに似た使いかたができるかと思います。
これに使用した、Node-RED MCU Editionについてはこちらをご覧ください。
接続図と使用した部品
Node-RED MCUプラグインを使っている場合、ESP32のUSB端子に割り当てられているデフォルトのPort 0はプログラムの書き込み、およびデバッガxsbugとの連動のために占有されていますので、他にESP32で使用できる空いているシリアルポートを使用します。
今回の例ではPort 2として使用できる16,17ピンを使用し、シリアルUSB変換モジュールを使ってPCに接続するようにしています。
このモジュール自体はここに接続するUSBケーブルからの給電で動作しますので5V端子はオープンにしておきます。また、FT234Xを使用したモジュールなので給電は5VですがTxDとRxDは3.3Vで動作します。これらの信号線は3.3Vで動作するESP32に直接接続できます。GNDラインも一緒に配線しておきます。
PCからみた場合、例えばこちらの例では以下のように2つのポートに接続しています:
COM5: プログラムの書き込みとxsbug(デバッガ)
COM7: シリアル通信用
また、GPIOポート制御の確認用としてピン18にLEDを接続しています。
mcuデバイス用フロー
今回設定するシリアルポートを使用して、「mcu serial in」ノードでPCからのGPIO制御コマンドを受信し、switchノードでon/offを分離して「Digital out」ノードでLEDをON/OFFすると同時に、「mcu serial out」ノードを使用してLEDの状態をPCに返すようにしています。
今回のチャレンジはNode-REDのFunctionノードを使ってNode-RED MCUでビルドした後にESP32側でModdable SDKの機能を使う事です。フローはPC側では正しく動作しませんが、ESP32に入ると正常に動作します。
このポート設定の中で、mcu側だけで利用できるmoddable SDKのdevice.io.Serialを参照しているのでPC上のNode-REDフローエディタのノードには設定がおかしなときに表示される赤い▲マークがつきますが、node-red-mcuでmcu用にビルドすればmcuデバイス上では動作するのでそのままにしておきます。
mcu serial in
このノードを使用して、シリアルポートの設定と受信を行います。
通常「Function」ノードで使用する「コード」タブは空で、ここの処理には「初期化処理」タブを使用しています。
シリアル通信の通信速度やポートはここで設定しています。
データを受信したときの処理もここで、区切り文字(\n)を削除して送出しています。
// Code added here will be run once
// whenever the node is started.
let serial = new device.io.Serial({
...device.Serial.default,
baud: 115200,
port: 2,
receive: 16,
transmit: 17,
format: "buffer",
onReadable: function (count) {
let msg = {};
msg.payload = String.fromArrayBuffer(this.read());
msg.payload = msg.payload.trimEnd();
node.send(msg);
},
});
flow.set('serial', serial); // provide 'serial' for 'mcu serial out' node.
mcu serial out
こちらのノードでは、msgを受け取ったら「mcu serial in」ノードで初期設定したポートを使用して送信を行います。
let serial = flow.get('serial'); // get 'serial' from 'mcu serial in'
if (msg.payload != null){
serial.write(ArrayBuffer.fromString(msg.payload + "\n"));
}
PC用フロー
PC側にはmcuデバイスのLEDをon/offするフローと、LEDの状態のフィードバックを受信するフローを組んでいます。
動作確認
・テストしたフローはGithubで公開しています。「こちら」からダウンロードできます。
これで「18 ON」のインジェクトノードのボタンを押すと、mcuデバイスのLEDが点灯し、デバッグウインドウに「18 turned on」が表示されるようになりました。
同様に、「18 OFF」のインジェクトノードのボタンを押すと、mcuデバイスのLEDが消灯し、デバッグウインドウに「18 turned off」が表示されます。
さいごに
このノードは、node-red-mcuですぐにシリアルポートを使いたいという話を聞いて簡易的に試してみたもので、そのうちに本家の方から正式なserial in/outノードが提供されるのではないかと思います。それでも、今回は私自身がModdable SDKやNode-REDの仕組みを理解するのに役立ちました。
Node-REDはビジュアルプログラミングができるノーコード/ローコードツールとして素晴らしいもので、私もノーコードで「Functionノードを使わずに」いろいろな処理を組み立てるのを楽しんでいます。そういった一面もありながら、Functionノードを使うことで便利になる面もあると思います。
Functionノードがある事でJavascriptのコードを書きたい「コーディング派」の人も、ノーコードでいろいろ作りたい「ノーコード派」の人も、どちらも同じNode-RED環境で仲良くコラボレーションができる素晴らしい環境だなと思う今日この頃です。