📡

Raspberry Pi Pico+ArduinoとTWELITE UARTを使って無線通信する

2023/01/25に公開

Raspberry Pi Pico (RP2040) と Arduino フレームワークで TWELITE UART を使った無線通信を行う方法のメモです。

Arduino フレームワークは arduino-pico (いわゆる earlephilhower 版)の 2.7.1 で動作を確認しています。

用意するもの

部品名 入手先
TWELITE UART
BLUE または RED、アンテナ内蔵または同軸コネクタタイプ
内蔵: BLUE RED
同軸: BLUE RED
アンテナ
同軸コネクタタイプでは必須
平面 ダイポール 薄型
TWELITE R
R2 または R3
R2 R3
MONOSTICK
BLUE または RED
BLUE RED
Raspberry Pi Pico 秋月

他にブレッドボード、ピンヘッダ、配線材などが必要です。

ソフトウェア

  • VSCode + PlatformIO
    Arduino IDE での開発でも可能ですが、こちらがオススメです。
  • TWELITE STAGE APP
    インストール方法 に従って導入してください。
  • CoolTerm
    PlatformIO 付属のターミナルでは使いづらいので、こちらを使っています。

準備

MONOSTICK(親機)の準備

  1. MONOSTICK を PC に接続する
  2. TWELITE STAGE APP(TWELITE_Stage.exe)を起動し、MONOSTICK を選択します
  3. インタラクティブモードを選択します。その旨を確認する画面になりますので、ENTER を押して続行します
  4. CONFIG/TWE UART APP から始まる設定画面が表示され、各項目が以下のようになっていることを確認する
 a: set Application ID (0x67720103) 
 i: set Device ID (120=0x78) 
 c: set Channels (18) 
 x: set RF Conf (3) 
 r: set Role (0x0) 
 l: set Layer (0x1) 
 b: set UART baud (38400) 
 B: set UART option (8N1) 
 m: set UART mode (E) 
 k: set Tx Trigger (sep=0x0d0a, min_bytes=0 dly=0[ms])
 h: set header format [;U;%t;%i;0x%A;%q;%s;<*;%X;\n] 
 C: set crypt mode (0) 
 o: set option bits (0x00000100) 
TWE UART APP と表示されていない場合
  1. ESC を押してメニューに戻る
  2. アプリ書換を選択する
  3. BIN から選択を選択する
  4. App_Uart_*** もしくは App_Uart_TWELITEUART_*** のどちらかのバイナリを選択する
  5. 書き込みが始まり、完了したら Enter を押してインタラクティブモードに入る
設定項目が異なる場合
  1. 設定項目と同じキーを押して個別に変更するか、もしくはリセットのためにRキー(Shift+R)を押す
  2. すると変更される項目に * が表示されるので、Sキー(Shift+S)を押す
  3. 書き込みが終わると自動でメニューに戻されます
  1. TWELITE STAGE APPを閉じる

TWELITE UART(子機)の準備

親機と異なり、設定の変更が必要です。

  1. TWELITE UART と TWELITE R を写真のように接続する(方向注意
  2. TWELITE STAGE APP(TWELITE_Stage.exe)を起動し、TWELITE R を選択する
  3. インタラクティブモードを選択し、その旨を確認する画面になりますので、ENTERを押して続行します
  4. CONFIG/TWE UART APP から始まる設定画面が表示され、以下の項目を変更します
(該当箇所のみ記載)
 h: set header format [;%A;%q;*;\n] 
 o: set option bits (0x00010100) 
変更したオプションの意味
  • ヘッダフォーマットは TWELITE UART から返される応答の出力書式になります。%A がメッセージの送り主のアドレス(シリアルナンバー)、%q が電波強度(自ら発信した場合は 000)、* がメッセージ本文です。

  • オプションビットは 0x000100000x00000100 の組み合わせです。

    • 0x00010000 は BPS ピンの設定と関係なく、設定画面に表示されている UART baud(ボーレート) を使うようになります。TWELITE UART には BPS ピンがないため、このビットを設定しないとボーレートは 115200 で固定されます
    • 0x00000100 は Tx Trigger の sep で設定された文字列をUARTで受け取ったときに送信を開始するよう設定されます。デフォルトでは sep には 0x0d0a\r\n) が設定されています。
    • その他のオプションビットの意味は公式のドキュメントを参照してください。
TWE UART APP と表示されていない場合

MONOSTICK(親機)と同様に ESC を押してメニューに戻り、アプリの書き換えを行ってください。バイナリは
App_Uart_*** もしくは App_Uart_TWELITEUART_*** のどちらかになります。

  1. 変更項目に * がついていることを確認したら、S(Shift+S)を押して設定を保存する
  2. 保存後は自動でメニューに戻されます

ボーレートを変更したあとのインタラクティブモードの入り方

上記の設定を行うと TWELITE UART のボーレートが 115200 から 38400 に変更されます。TWELITE STAGE APP では 115200 がデフォルト設定で接続を行います。必要であれば以下の方法で設定を変えます。

ボーレートの変更方法
  1. メニューの TWELITE STAGE の設定を選択する
  2. 設定メニューの 0 を押して共通設定に入る
  3. B(Shift+B)を押す
  4. 38400 を押して Enter を押す
  5. ボーレートの項目に正しいレートと * が表示されていることを確認してS(Shift+S)を押す

結線

TWELITE R を PC から外し、TWELITE UART も外します。Raspberry Pi Pico と TWELITE UART を以下のように接続します。


Raspberry Pi Pico と TWELITE UART を接続した様子

Raspberry Pi Pico TWELITE UART
GND GND
GP12(UART0 TX) RXD
GP13(UART0 RX) TXD
3V3(OUT) VCC

プログラム

公式ドキュメントにて掲載されているサンプルスケッチを Raspberry Pi Pico 用に書き換えたものになります。主な動作に変更はないため、解説は公式ドキュメントを参照してください。

#include <Arduino.h>
#include <SoftwareSerial.h>

SoftwareSerial MWSerial(13, 12);  // RX, TX

#define BLOCK_MAX 10

// データ列を区切り文字で分割してString型の配列に入れる。
int split(char* source, char delimiter, String* result) {
  char* p = source;
  char tmp[81];
  memset(tmp, 0, sizeof(tmp));
  int n     = 0;
  int block = 0;

  // ヌル文字が来るか分けたブロック数がBLOCK_MAXになったらやめる。
  while (*p != 0 && block < BLOCK_MAX) {
    // 区切り文字が来たら、String型に変換する。
    if (*p == delimiter) {
      // 分割したデータが0バイトの時は何もしない。
      if (n > 0) {
        // 念のためヌル文字を末尾に代入。
        tmp[n]        = 0;
        result[block] = String(tmp);
        block++;

        n = 0;
        memset(tmp, 0, sizeof(tmp));
      }
    } else {
      tmp[n] = *p;
      n++;
    }
    p++;
  }

  return block;
}

void setup() {
  Serial.begin(38400);
  MWSerial.begin(38400);
}

void loop() {
  while (MWSerial.available()) {
    static char buf[256] = { 0 };
    static char* p = buf;
    char before = *p;
    *p          = MWSerial.read();

    if (before == '\r' && *p == '\n') {
      *p = 0;                            // 末尾をNull文字にする
      String str[BLOCK_MAX];             // 区切り文字で分割した文字列を入れる
      int block = split(buf, ';', str);  // データの分割

      if (block == 3) {
        Serial.print("Message: ");
        Serial.println(buf);
        Serial.print("Serial No.: ");
        Serial.println(str[0]);
        Serial.print("LQI: ");
        Serial.println(str[1]);
        Serial.print("Data: ");
        Serial.println(str[2]);
        Serial.println();
      }

      p = buf;
      memset(buf, 0, sizeof(buf));
    } else {
      if (*p >= 0x20) {
        p++;
      }
    }
  }

  while (Serial.available()) { MWSerial.write(Serial.read()); }
}

動作確認

以下は CoolTerm を使った方法になります。Options から設定が以下のようになっているか確認してください。

  • Serial Port Options ページ
    • Data Bits: 8
    • Parity: None
    • Stop Bits: 1
  • Terminal Options ページ
    • Terminal Mode: Line Mode
    • Enter Key Emulation: CR+LF

設定が正しければ CoolTerm を2つ開き、親機の MONOSTICK と子機の Raspberry Pi Pico に接続します。

接続先 ボーレート
MONOSTICK
親機
115200
Raspberry Pi Pico
子機
38400


左: MONOSTICK、右: Raspberry Pi Pico

親機から子機へ通信

親機の MONOSTICK 側に適当な文字列を送信します。hello raspi と入力します。


親機から hello raspi を送信

すると親機のターミナルには送信ログが表示されます。

;U;05666;219;0x8201BFFB;000;001;1,1,hel...;74;

送信側では受信強度は 000 となり、メッセージ本文は省略されます。一方、受信側では以下のような表示になります。

Message: ;8201BFFB;168;hello raspi;
Serial No.: 8201BFFB
LQI: 168
Data: hello raspi

メッセージ本文が省略されずに表示されます。LQIは受信強度です。

子機から親機へ送信

逆に子機から送信を行います。hi monostick と入力します。


子機から hi monostick を送信

すると子機のターミナルには送信ログが表示されます。

Message: ;810A5A33;000;20,1,hi ...;
Serial No.: 810A5A33
LQI: 000
Data: 20,1,hi ...

親機には子機から受信したメッセージ本番が省略されずに表示されます。

;U;05715;120;0x810A5A33;135;020;hi monostick;7F;

うまくいかない場合

ターミナルが文字化けする

ボーレートが合致していないと文字化けやデータが正しく表示されません。この記事で設定したボーレートは複数ありますので、今一度まとめておきます。

接続先 ボーレート
MONOSTICK 115200
Raspberry Pi Pico の Serial 38400
Raspberry Pi Pico の SoftwareSerial 38400
TWELITE UART 38400

ターミナルで文字を送っても何も起きない

改行文字が \n のままになっているかもしれません。MONOSTICK、TWELITE UART ともに \r\n を送らないと送信をしない設定になっているため、ターミナル側で改行文字を正しく設定してください。

通信の最初にNULLが入る

TWELITE UART から通信をすると、最初の通信にこのように NULL 文字(00)が入ってしまうことがあります。これは Raspberry Pi Pico のハードウェアリセットがかかっても TWELITE UART はリセットされず、バッファの一部が漏れてしまうためです。スケッチの書き換え直後に頻発します。

TWELITE UART には RST ピンがあります。アクティブローですので GND にショートするとリセットされます。配線を以下のように1本追加します。

Raspberry Pi Pico TWELITE UART
GND GND
GP12(UART0 TX) RXD
GP13(UART0 RX) TXD
GP16 RST
3V3(OUT) VCC

スケッチの setup 関数に以下のようにリセット処理を追加します。MWSerial.begin よりも後にリセット処理をかけることがポイントです。delay はそれぞれ100ミリ秒、500ミリ秒と TWELITE UART の初期化に十分な時間を見越して指定しています。

void setup() {
  Serial.begin(38400);
  MWSerial.begin(38400);

  pinMode(16, OUTPUT);
  digitalWrite(16, HIGH);
  digitalWrite(16, LOW);
  delay(100);
  digitalWrite(16, HIGH);
  delay(500);
}

参考文献

Discussion