Windows Node-RED で Keigan Motor と JavaScript でシリアル通信するとき DataView クラスが便利だったメモです。
Keigan Motor へデータを送るときに Buffer データをつくる試行錯誤をしていた
Keigan Motor の動作撮影するに Node-RED を操作する手が足りないので Power Automate Desktop に操作をまかせるメモ
こちらの記事で動かしたときに、Keigan Motor へデータを送るときに Buffer データをつくるために試行錯誤した時の知見です。
Keigan モーター のローレベル API
まず、Windows で Keigan Motor を動かす場合、serial ノードを使ってシリアル通信をしてデータを送っています。
その時に、ローレベル API というコマンド(バイト列)を送信して直接制御することができます。
ローレベルAPIの概要 – 株式会社Keigan-KeiganMotor ドキュメント
このようにドキュメントも分かりやすく、取っつきやすい感じです。
ローレベル API で LED を操作する( DataView 使わない版)
コマンド(LED) の KeiganMotor ドキュメントはこのようになっています
フローはこんな感じです。こちらの「LED 命令 + payload からのカラー指示を反映」と書いてある function ノードの中で、さきほどのコマンドをつくれば操作することができます。
ごくごくシンプルに書くとこのような感じです。
let commands = [0xE0,0,0,3,0,0,0,0,0]; const rgb = msg.payload; commands[4] = rgb[0]; commands[5] = rgb[1]; commands[6] = rgb[2]; msg.payload = Buffer.from(commands); return msg;
配列を Buffer.from で変換して扱う形です。
commands で
- LED コマンドの指示である
0xE0
- タスク管理用ID をとりあえず 2 桁のゼロで埋める
0,0
- LED の光り方を決める
3
- 巡回冗長検査の値を最後の2桁のゼロで埋める
0,0
- 4~6 番目で LED のカラーの RGB を設定
を作っています。
これでも出来なくはないのですが、より複雑なバッファの操作もこれでやるとなると結構大変だなという印象で困っていました。
本家のライブラリを読んでいたら DataView クラスが便利そう
こういうときは、本家の JavaScript ライブラリ kmconnector-js で、どうしているかを追ってみました。
KMComWebBLE.js を見てみると、ローレベル API の仕様に合わせて、各命令のバッファを良い感じに DataView クラスでさばいていることが分かりました。
DataView クラスはざっくりいうと、バイト列の並びを配列で自前でがんばるよりも、気を利かせて、データを加えたり並べてくれるクラスのようです。
DataView クラスを使ってローレベル API で LED を操作する
まだ、使い方ははっきりわからないですが、先ほどの KMComWebBLE.js あたりを読めば、今回の Keigan Motor に関しての DataView の使い方は分かるので、LED 操作のコードを書き換えてみました。
const commandNum = 0xE0; let buffer = new ArrayBuffer(9); // LED コマンド new DataView(buffer).setUint8(0,commandNum); // タスク管理用ID const cid = 0; new DataView(buffer).setUint16(1,cid); // LED 点灯方法 // LED_STATE_OFF = 0, // LED消灯 // LED_STATE_ON_SOLID = 1, // LED点灯(点灯しっぱなし) // LED_STATE_ON_FLASH = 2, // LED点滅(一定間隔で点滅) // LED_STATE_ON_DIM = 3 // LEDがゆっくり明滅する new DataView(buffer).setUint8(3,3); // payload からカラー設定 new DataView(buffer).setUint8(4,msg.payload[0]); new DataView(buffer).setUint8(5,msg.payload[1]); new DataView(buffer).setUint8(6,msg.payload[2]); // 巡回冗長検査 new DataView(buffer).setUint16(7,0); msg.payload = Buffer.from(buffer); return msg;
はい、めっちゃ分かりやすくなりましたね。気を利かせて、データを加えたり並べてくれてます。
- 最初に ArrayBuffer で DataView が編集する元のバイト列をつくってあげる
- 以後は new DataView(buffer).setUint8 のような書き方で、DataView を通して buffer が操作する
- LED コマンド、LED 点灯方法、payload からカラー設定のような、1 桁のデータ挿入であれば setUint8 で、入れる場所と数値として値を入れれば、計算して buffer に挿入してくれる
- タスク管理用ID、巡回冗長検査のような、2 桁のデータ挿入も setUint16 を使ってドキュメントにあるように値を入れれば、計算して buffer に挿入してくれる
という流れで、こちら側からは、普段使っている Number 型でデータを作って、データ順に合わせて値を入れれば計算して buffer に挿入してくれるところがとてもありがたいです。
とくに感動したのが、2 桁のデータ挿入。
素で配列をいじっているときは、いつも uint16_t と言った値で普段扱っている数値をどういう風にバイト列に入れてあげるかの試行錯誤で時間を使ってしまうのが、DataView 側で計算して buffer に挿入してくれるというのが素敵。
Keigan Motor のドキュメントはとても分かりやすいですが、どうしても、そのあたりの読み解き&実装が必要だったところが、DataView だとシンプルにドキュメントに書いてある uint16_t , uint8_t に合わせて setUint8 , setUint16 と書き換えていけばいいので、ミスも減るし、直感的にコードが書けるようになりました。
ということで、DataView クラスが便利でした
動いたのがこちらの動画です。LED 操作ができました。
ちょっと要望あって #KeiganMoter にWindowsからUSBシリアル経由でローレベルAPIやるので、ひとまずLED命令してみたけど、ちゃんと Node-RED からデータ送れた! 仕様に合わせた素のBuffer データの並べ方うまくできたー。 #nodered #noderedjp pic.twitter.com/gQcbKM3trP
— Tanaka Seigo (@1ft_seabass) February 11, 2022
おかげさまで、モーター操作の許可であったりモーターの絶対角度の指定のような、より複雑なバイト列を組む他の ローレベル API についても、なんとかやっていけそうな勇気が出てくる DataView クラスの知見を得ることができました。