目次 [ Contents ]
2つ用意して電源をつなげば、すぐに無線でやりとりできるTWE-LITE。その手軽さは電子工作初心者にも優しい作りになっています。
買った時点でインストールされている標準アプリが、それを可能にしていますが、デジタルピン、アナログピンの入出力以外にI2C、UART(シリアル)通信にも対応しています。シリアル通信ができるなら、2台Arduinoを用意してデータのやり取りも可能なハズ。普段PCのシリアルモニタで数値を確認できるように、他のArduinoと無線でやりとりできるわけです。僕も最初これ目当てで手に入れました。
しかし、標準アプリに搭載されているUART通信機能は制約、ルールがあったりして、初心者が手を出すには少し難しいところがあります。販売元のTOCOSも、
と勧めています。
結論から言うと、標準アプリでもシリアル通信は可能です。しかし、いくつかの制限を踏まえたシステムの構築には結構工夫がいるので、ちゃんとしたUART通信を望むのであれば、素直に書き込み機を手に入れてアプリを書き換える方がいいかもしれません。
ということで、TWE-LITE標準アプリを使って、Arduinoからシリアル送信する方法について書いていこうと思います。
データ送信のルール
TOCOSサイトではUARTによる任意データの送受信についてこのように解説してます。
- UARTコマンドにより、無線端末間で任意データの送受信が可能です
- 外部のマイコン等から論理デバイスIDを指定して他の無線端末に対してデータ列を送信できます
- 1パケットで送信できるデータサイズは最大で80バイト
- いずれかの端末を親機に設定して下さい
- 電文の形式は先頭が : (コロン)で続いて 0-9 A-F の文字列が連続し <CR> <LF> で終端する形式です
- 1バイトを2文字で表現する入力形式
- 必ず終端は CRLF(0x0d 0x0a)となります
- チェックサムが誤っている時は送信されません
以上、抜粋ですが、まとめると、実際にシリアル送信するデータはこの形式に倣う必要があります。
ヘッダ | 宛先ID | コマンド | データ | チェックサム | 終端1 | 終端2 |
: | 任意 | 0x01 | 任意 | X(又は演算) | 0x0d(\r) | 0x0a(\n) |
データ種の説明
ヘッダ
TWE-LITEではデータ送信の頭に必ず「:」(0x3a)をつける必要があります。
宛先ID
送りたい機器のID番号です。親機、子機の設定で以下のように変わります。また、インタラクティブモードで個別のID番号をつけることも出来るようです。
ID番号 | 意味 |
0x00 | 親機 |
0x01~0x64 | インタラクティブモードで設定したID |
0x78 | 子機(連続モード) |
以前書いたTWE-LITEステータス受信のデータを見ると、0x00のID、つまり親機から送られたデータということが分かります(①)。
コマンド
UART(シリアル通信)送信をするには0x01にします。
データ
任意の情報(HEX)を送ることが出来ます。ただし、データ量が増えると時間がかかったり、ロスが出るようです。
チェック・サム
情報を送る場合、必ず全データが受信できるとは限りません。そういった不具合の対策としてチェック・サムというのがあります。これは送信したデータのお尻にデータ数値をまとめた数などを入れておき、受信側が終了時にこれと比較計算して欠損がないか確認するというものです。ここにやり方が書いてあります。
ただ、チェック・サムに関してはアプリのバージョンアップによって、「X」(0x58)で省略できるようになったみたいです。
終端
データ送信の終わりを意味する情報で最後に入れます。0x0d(\r) 、0x0a(\n)です。
というフォーマットに即して送信しないと、TWE送信側の方で「何だこれ」と拒否します。結果送信されず、受信もされずという状態になります。ここが難しいところで、僕も当時1ヶ月ほど躓き続けました…。
とにかく、2台のArduinoと2台のTWE-LITEで簡単な送信、受信をやってみます。
配線
今回は、親機のArudinoから子機のArduinoへシリアルデータを送信します。なので、PCでシリアルモニタするのは子機の方です。
また、TWE-LITEに表記されているUARTのTX、RXは混乱すると思うのでお気をつけください。
Promini(TX) → TWE-LITE親機(RX) → TWE-LITE子機(TX) → Promini(RX) → シリアルモニタ
こんな流れです。
Arduino親機pro miniなのはTWE-LITEの3V駆動に合わせるためです。レベル変換や電圧が同等で扱えるものなら代替品でも可能だと思います。
UART送信
データ送信の注意点
自分がつまづいていたのは以下が原因でした。
- 送信できる数値は基本16進数、つまり(0~F)×2
- しかし、実際はHEXをChar型に変換した文字
- HEXベースなので2文字単位。つまり、送るChar型数値は偶数個必要
- チェックサムの計算はヘッダの「:」を含まない(現行機は「X」で解決)
HEXて何?という方はこちらを読んでください。
受信用スケッチ
#include <SoftwareSerial.h> SoftwareSerial TWE(5, 6); // RX, TX #define LED 13 void setup() { TWE.begin(38400); Serial.begin(38400); pinMode(LED, OUTPUT); } void loop() { byte recv [60] = {}; byte count = 0; //receive data while (TWE.available()) { digitalWrite(LED, HIGH); recv [count] = TWE.read(); count++; } if (count > 0) { for (byte i = 0 ; i < count ; i++) Serial.print((char)(recv[i])); } digitalWrite(LED, LOW); }
以前の記事で書いた受信のスケッチをシリアルモニタ上で確認するため簡単にしたものです。
そして、送信側。ここでは単純に「35」という数値を送ってみたいと思います。
送信用スケッチ
#include <SoftwareSerial.h> SoftwareSerial TWE(5, 6); // RX, TX #define LED 13 void setup() { TWE.begin(38400); pinMode(13, OUTPUT); } void loop() { #define DATA_SIZE 10 byte DATA[DATA_SIZE] = {':', '7', '8', '0', '1', '3', '5', 'X', '\r', '\n'}; digitalWrite(LED, HIGH); for (byte i = 0 ; i < DATA_SIZE ; i++) TWE.write(DATA[i]); delay(300); digitalWrite(LED, LOW); delay(300); }
600msごとに「35」という数値を送るスケッチです。配列DATA[]に送りたいデータが全て入っていますが、数値ではなく、’’でくくった文字、つまり、文字コードが入っているということに注意してください。また、「78」は「7」と「8」、「01」は「0」と「1」のように本来HEXなら1つである数値を2つのCharとしていることも重要です。
送信は一部の文字を除いて(:、Xなど)、0~Fじゃないとダメです。でも、逆に言えば、0~9の数値でもChara型に変換すればOKということになります。いちいちHEXに変換するのが面倒であれば、そのまま10進数でやりとりしてしまう手もあります。要は受信側でどう戻すかの話なので。
試しに可変抵抗器を使って変化する値を送れるようスケッチを修正してみてください。ここまで理解できれば、もう難しい話ではないと思います。このサイトで以前書いた他の記事を参照して頂ければ。