M5StickC Plusで簡単Bluetooth相互通信、遠隔操作する方法

Arduinoコマンド:Bluetooth相互通信、遠隔操作方法

「M5StickC Plus」と「M5StickCまたはPlus2」(両方M5StickC Plusやパソコンとの組み合わせでも可)を使用して、Bluetoothで相互通信、遠隔操作する方法をサンプルプログラム(コピペ)を使用して詳しく紹介します。

2025/2/22 「M5StickC Plus2」でも動作確認できるようにサンプルプログラムを追加しました。

ここで紹介するBluetooth通信を使用したラジコンの作り方や、パソコンと接続して遠隔操作やデータ記録する方法も以下のリンクで詳しく紹介しています。

LEGOで作るBluetooth遠隔操作ラジコン(Arduinoコマンド、ESP32系マイコンATOM使用)
M5StickC PlusとATOMを使用してBluetooth通信とジョイスティックで操作するラジコンカーをLEGOブロックで作ります。LEGOなので組み合わせは自由!自分好みのラジコンを作りましょう♪
Bluetooth通信でパソコンへcsvデータ保存、遠隔操作する方法
BluetoothでM5StickC Plusとパソコン間でデータ送受信やcsv保存、遠隔操作する方法をpython自作アプリのシリアルモニタを使って詳しく紹介
スポンサーリンク

1.M5StickC Plusとは

「M5StickC Plus」とは「M5Stackテクノロジー社」のマイコンボードで「M5StickC」のバージョンアップ品です。

大きさは 縦48.2 × 横25.5 × 高さ13.7と小さいながら 1.14インチTFT液晶画面や入出力端子、2個のボタン、LED、赤外線送信、ブザー、3軸ジャイロ+3軸加速度センサ、マイク、RTC(リアルタイムクロック)、バッテリーが内蔵されています。

他にもシリアル通信はもちろんWiFiや今回紹介するBluetooth通信にも対応しています。


「M5StickC Plus」については、以下のリンクで詳しく紹介しています。

M5StickC Plusの使い方、初期設定、サンプルプログラム、M5StickCとの違い等を詳しく紹介
M5StickC PlusをArduino IDEやPlatformIOで使うための初期設定やサンプルプログラムでの動作確認の方法です。ビジュアルプログラミングのUiFlowの初期設定についても紹介します。

「M5StickC Plus2」についても以下のリンクで詳しく紹介しています。

M5StickC Plus2の使い方、初期設定、旧モデルとの違い等サンプルプログラムで詳しく紹介
M5StickCの最新版M5StickC Plus2について、旧モデルとの違いを確認しながら、初期設定や端子配列、機能、使い方をサンプルプログラムで詳しく紹介します。
スポンサーリンク

2.Bluetoothとは

「Bluetooth」とは、無線通信規格の一つです。無線通信規格としてはスマホやパソコンのインターネット接続で日常的に使用している「Wi-Fi」がありますが、「Wi-Fi」と比べると通信速度は遅く、通信距離も短いです。

しかし、消費電力が低いというメリットがあり、マウスやキーボード、イヤホン等、通信データ量の少ない近距離通信を行うスマホやパソコンの周辺機器に最適です。

「Bluetooth」の規格は「Bluetooth Classic」と「Bluetooth Low Energy(以下BLE)」の 2種類あり、それぞれは別物ですが、使用する側からすればどちらかを意識しなくても使用できるため、一般的には区別されることなく「Bluetooth」として呼ばれることが多いです。

「Bluetooth Classic」の通信速度はバージョンによって1Mbps〜3Mbpsで「BLE」は1Mbpsでしたがバージョン5の登場で最大2Mbpsとなり、今後は「BLE」の活躍の場が増えそうです。

通信距離については「Class」で区別されており、2.4GHz帯を使用しているため、障害物の影響を受けることを考慮しておく必要がありますが、一般的には「Class1は100m」「Class2は10m」「Class3は1m」のように言われています。

これについては、送信のみで良いのか双方向通信するのかによっても変わると思いますし、通信相手の性能によっても変わると思うのでここでは明確にするのはやめておきます。

実際にどれくらいの距離で通信できるか、最後に今回使用した「M5StickC Plus」で確認しています。

通信はマスター側とスレーブ側にそれぞれ設定した機器間で行われます。
接続先の選択や通信の開始、中断はマスター側から行いますが、接続が完了すると双方向にデータのやり取りが可能です。
スポンサーリンク

3.動作紹介

今回は「M5StickC Plus」をスレーブ側、「M5StickC/M5StickC Plus2」をマスター側として「Bluetooth Classic」で接続し相互データ通信、遠隔操作を行います。

両方「M5StickC Plus」でもいいですが、見た目が同じだとマスター/スレーブの区別がつきにくいので片方は「M5StickC/M5StickC Plus2」を使用しました。

両方「M5StickC Plus」や両方「M5StickC/M5StickC Plus2」にする場合は、ヘッダーファイルの変更と表示文字サイズだけ調整すれば同じように使用できます。

また、「M5StickC Plus」だけ1個しかない場合でも、パソコンをマスター側として動作確認することもできます。

Bluetooth通信するためにペアリングした後は、通常のシリアル入出力と同じように、文字列を送受信することができます。この文字列を本体に表示し、文字列の内容によってLEDのON/OFFを行います。


・「M5StickC Plus」と「M5StickC」での相互データ通信

動作についての詳細は下画像のようになります。
本体の色が「赤っぽい」方がスレーブ側の「M5StickC Plus」で「オレンジ」の方がマスター側の「M5StickC」です。

「M5StickC Plus2」を使用する場合は「M5StickC」の動作を参考にしてください。
M5StickC PlusでBluetooth相互通信

まず先にスレーブ側の「M5StickC Plus」の電源を入れると上画像のような表示になります。
「BT_Slave」は「M5StickC Plus」の接続名でその下に表示されている文字列は「M5StickC Plus」の「MACアドレス」です。
このどちらかを使用してマスター側から接続します。

M5StickC PlusでBluetooth相互通信

次にマスター側の「M5StickC」の電源を入れると上画像左のようにスレーブ側との接続が開始されます。
「Connected!」が表示され、上画像中央のように「BT_Master」と表示されたら接続完了です。
上画像右のように「Failed!」と表示された場合は接続失敗です。
本体左側面の電源ボタンを1秒ちょっと押して離すと再起動できるようにしてあります。


M5StickC PlusでBluetooth相互通信

マスター側「M5StickC」正面のボタンAを押すと、スレーブ側に文字列「A ON!」が送信され、上画像のように「M5StickC Plus」の液晶に「BT: A ON!」が表示されて本体左上のLED赤が点灯します。

M5StickC PlusでBluetooth相互通信

マスター側「M5StickC」右側面のボタンBを押すと、スレーブ側に文字列「B ON!」が送信され、上画像のように「M5StickC Plus」の液晶に「BT: B ON!」が表示されて本体LED赤が消灯します。


M5StickC PlusでBluetooth相互通信

スレーブ側「M5StickC Plus」正面のボタンAを押すと文字列「A ON!」がマスター側に送信され、上画像のように「M5StickC」の液晶に「A ON!」が表示され本体LED赤が点灯します。

M5StickC PlusでBluetooth相互通信

スレーブ側「M5StickC Plus」右側面のボタンBを押すと文字列「B ON!」がマスター側に送信され、上画像のように「M5StickC」の液晶に「B ON!」が表示され本体LED赤が消灯します。


・「M5StickC Plus」とパソコンでの相互データ通信

スレーブ側の「M5StickC Plus」だけでもパソコンをマスター側に使用して下画像のように動作確認できます。

動作確認に使用したパソコンのOSは「Windows10」です。

まずは、「M5StickC Plus」と「M5StickC/M5StickC Plus2」両方の電源をOFFにして「M5StickC Plus」だけ再度電源をONにします。

M5StickC PlusでBluetooth相互通信

次にパソコンと「M5StickC Plus」でBluetooth通信するためのペアリングを行います。

Bluetoothペアリング方法

パソコン画面左下の「ウインドウズアイコン」を右クリックして「デバイスマネージャ」をクリックします。

Bluetoothペアリング方法

「デバイスマネージャ」が起動したら「ポート(COMとLPT)」をクリックします。


Bluetoothペアリング方法

現在使用しているポートの一覧が表示されます。
ペアリング後はポートが増えるので現時点のポートをメモしておきましょう。
「M5StickC Plus」のUSBに接続しているポートもここで確認しておきましょう。(私の環境ではCOM9です。)

Bluetoothペアリング方法

パソコン画面左下の「ウインドウズアイコン」を今度は左クリックして「設定」をクリックします。


Bluetoothペアリング方法

設定ウインドウが表示されるので「デバイス」をクリックします。

Bluetoothペアリング方法

画面が切り替わったら上画像のように、Bluetoothが「ON」になっていることを確認してから「Bluetoothまたはその他のデバイスを追加する」をクリックします。


Bluetoothペアリング方法

上画像のように表示されたら「Bluetooth」をクリックします。

Bluetoothペアリング方法

「M5StickC Plus」の接続名「BT_Slave」が表示されたらクリックします。

Bluetoothペアリング方法

上画像のように表示されたらペアリング完了です。
「完了」をクリックしましょう。


ArduinoIDEでBluetoothシリアル通信テスト

ペアリング終了後「デバイスマネージャ」を確認するとポートが増えています。
今回は「COM7」と「COM8」でした。Windowsの場合は 2個表示されますが数字の大きい方(今回は「COM8」)が使用するポートなのでこれをBluetooth通信ポートとしてメモしておきましょう。


次にシリアルモニタで動作確認を行なっていきます。
シリアル通信で文字の入出力ができるものなら何でもいいです。

今回は「ArduinoIDE」を使用した動作確認の方法を紹介します。
「ArduinoIDE」と「シリアル出力モニタ」については以下のリンクで詳しく紹介しています。

M5StackシリーズのためのArduino IDEのインストール方法と初期設定、使い方紹介
ArduinoIDEバージョン2のインストール方法から初期設定、スケッチ例の書き込み、コピペでの使い方まで詳しく紹介します。インストールはArduinoでも同じです。
シリアル(UART)出力で内部データの表示(Arduinoプログラミング)
シリアル出力モニタとはプログラム内の値やデータをパソコンのモニタ上に表示させることができる機能で、ほとんどの開発環境にこの機能があります。表示だけではなく出力したデータを記録して保存したり、機器間でデータをやり取りする時にも使用されます。

ArduinoIDEでBluetoothシリアル通信テスト

まずはシリアルポートの設定を行います。
上画像のようにBluetoothの通信ポートを選択します。(ここではCOM8)

ArduinoIDEでBluetoothシリアル通信テスト

ポートを設定したらウインドウ右上のシリアルモニタの虫眼鏡アイコンをクリックします。


ArduinoIDEでBluetoothシリアル通信テスト

上画像のようにシリアルモニタが表示されます。
表示されなかったり「ArduinoIDE」にエラーメッセージ」が表示された場合は、COMポートが間違っているか、ペアリングがうまく言いていません。上の手順に戻ってやり直しましょう。


ArduinoIDEでBluetoothシリアル通信テスト

シリアルモニタの設定を行います。
送信データの区切り文字として使用するために「CR」を選択します。

ArduinoIDEでBluetoothシリアル通信テスト

通信速度はサンプルプログラムでは「9600」としてますので「9600bps」に設定します。


シリアルモニタに以下のように文字を入力してエンターを押すとBluetooth通信でデータが送信されます。

「M5StickC Plus」がBluetooth通信で受信したデータは液晶画面で「BT:」に続けて表示されます。
※USBのシリアル通信で受信したデータの場合は「SR:」付きで表示されます。
ArduinoIDEでBluetoothシリアル通信テスト

「test」と入力して送信すると「BT: test」と表示されデータが送信されたことが確認できます。

ArduinoIDEでBluetoothシリアル通信テスト

「A ON!」と入力して送信すると「BT: A ON!」と表示され本体左上の「LED」が点灯します。

ArduinoIDEでBluetoothシリアル通信テスト

「B ON!」と入力して送信すると「BT: B ON!」と表示され「LED」が消灯します。

「M5StickC Plus」のボタンA、ボタンBを押すとシリアルモニタに「A ON!」「B ON!」が表示されるのでこちらも確認してみましょう。
今回のBluetooth通信は「PIN」による認証を行なっていないので誰でも接続することができます。
このため、送信するデータは人に見られても問題のないデータにしましょう。
また、LEDランプを点灯する等、本体で何かを処理するために送るデータは「0」や「1」等単純なものだと、誤って誰かが送ってしまうかもしれないので「文字列」等を使用するようにしましょう。

USBからのシリアルデータをBluetooth通信経由で相互データ通信

最後に、またマスター側とスレーブ側の 2台を使用して「M5StickC Plus」で受信したUSBからのシリアルデータをそのままBluetooth通信で「M5StickC/M5StickC Plus2」に送信する動作を確認します。

Bluetooth通信で受信したデータは「M5StickC/M5StickC Plus2」のシリアルデータとして出力されます。
パソコンが 2台あればそれぞれのシリアルモニタ同士でデータのやり取りが確認できます。

これができると、シリアル通信はあるけど無線機能が無い測定器等のデータをBluetooth通信でパソコンに送信できるため、何かと便利に使用できると思います。

ArduinoIDEでBluetoothシリアル通信テスト

まず上画像のように通信ポートの設定を「M5StickC Plus」と接続しているUSBシリアル通信ポート(ここではCOM9)に変更します。

「M5StickC Plus2」を使用する場合は「M5StickC」の動作を参考にしてください。

M5StickC PlusでBluetooth相互通信

マスター側の「M5StickC」の電源を入れて上画像のようにペアリングが完了し「BT_Master」が表示されるまで待ちます。

M5StickC PlusでBluetooth相互通信

「ArduinoIDE」のシリアルモニタで「test」と入力して送信すると「M5StickC Plus」に「SR: test」と表示され、そのまま「M5StickC」に送信され「BT: test」と表示されます。
「M5StickC」側もパソコンに接続している場合はシリアルモニタで「test」が受信されるのが確認できます。

M5StickC PlusでBluetooth相互通信

シリアルモニタで「A ON!」と入力して送信すると「M5StickC Plus」に「SR: A ON!」と表示されLEDが点灯、そのまま「M5StickC」に送信され「BT: A ON!」と表示されてLEDも点灯します。

M5StickC PlusでBluetooth相互通信

シリアルモニタで「B ON!」と入力して送信すると「M5StickC Plus」に「SR: B ON!」と表示されLEDが消灯、そのまま「M5StickC」送信され「BT: B ON!」と表示されLEDが消灯します。

私の環境ではペアリングしたパソコンのBluetooth通信ポートの設定はそのままで、USBのシリアルポートに切り替えるだけで、マスター側に設定した「M5StickC」の電源を入れると接続して動作できました。
もし、うまくいかない場合はパソコンのBluetoothをOFFにしたり、ペアリング設定を削除した後に両方の「M5StickC」を再起動して動作確認してみてください。

4.サンプルプログラム(スレーブ側、M5StickC Plus)

スレーブ側のサンプルプログラムは以下になります。「コピペ」して書き込んでください。

※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

// Bluetooth接続スレーブ側プログラム
#include <M5StickCPlus.h>
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;

// 変数宣言
String name = "BT_Slave"; // 接続名を設定
int btn_pw = 0;           // 電源ボタン状態取得用
String data = "";         // 受信データ格納用

// 初期設定 -----------------------------------------------
void setup() {
  M5.begin();             // 本体初期化
  Serial.begin(9600);     // シリアル通信初期化
  // 出力設定
  pinMode(10, OUTPUT);    //本体LED赤
  digitalWrite(10, HIGH); //本体LED初期値OFF(HIGH)
  // LCD表示設定
  M5.Lcd.setTextFont(2);
  M5.Lcd.println(name); // 接続名表示

  // Bluetooth接続開始
  SerialBT.begin(name); // 接続名を指定して初期化。第2引数にtrueを書くとマスター、省略かfalseでスレーブ
  // MACアドレスの取得と表示
  uint8_t macBT[6];
  esp_read_mac(macBT, ESP_MAC_BT);  // MACアドレス取得
  M5.Lcd.printf("%02X:%02X:%02X:%02X:%02X:%02X\r\n", macBT[0], macBT[1], macBT[2], macBT[3], macBT[4], macBT[5]);
  Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X\r\n", macBT[0], macBT[1], macBT[2], macBT[3], macBT[4], macBT[5]);
  // 電源ON時のシリアルデータが無くなるまで待つ
  while (Serial.available()) {data = Serial.read();}
  M5.Lcd.setTextFont(4);  // テキストサイズ変更
}
// メイン -------------------------------------------------
void loop() {
  M5.update();  // 本体のボタン状態更新
  // ボタン操作処理(マスター側へデータ送信)
  if (M5.BtnA.wasPressed()) {   // ボタンAが押されていれば
    SerialBT.print("A ON!\r");  // 「A ON!」送信(「CR」区切り文字)
  }
  if (M5.BtnB.wasPressed()) {   // ボタンBが押されていれば
    SerialBT.print("B ON!\r");  // 「B ON!」送信(「CR」区切り文字)
  }
  // データ受信時処理
  // スレーブからの受信データをLCDに表示
  if (SerialBT.available()) {               // Bluetoothデータ受信で
    data = SerialBT.readStringUntil('\r');  // 区切り文字「CR」の手前までデータ取得
    M5.Lcd.print("BT: ");                   // 受信データ液晶表示
    M5.Lcd.println(data);                   // 液晶表示は改行あり
    Serial.print(data);                     // シリアル出力は改行なし
  }
  // シリアル入力データ(「CR」付きで入力)をスレーブ側へ送信
  if (Serial.available()) {               // シリアルデータ受信で
    data = Serial.readStringUntil('\r');  // 「CR」の手前までデータ取得
    M5.Lcd.print("SR: ");                 // シリアルデータ液晶表示
    M5.Lcd.println(data);                 // 液晶表示は改行あり
    Serial.print(data);                   // シリアル出力は改行なし
    // Bluetoothデータ送信
    SerialBT.print(data + "\r"); // 区切り文字「CR」をつけてマスター側へ送信
  }
  // LED点灯処理
  if (data == "A ON!") {      // 受信データが「A ON!」なら
    digitalWrite(10, LOW);    // 本体LED点灯
  }
  if (data == "B ON!") {      // 受信データが「B ON!」なら
    digitalWrite(10, HIGH);   // 本体LED消灯
  }
  // 再起動(リスタート)処理
  if (btn_pw == 2) {          // 電源ボタン短押し(1秒以下)なら
    ESP.restart();
  }
  // 電源ボタン状態取得(1秒以下のONで「2」1秒以上で「1」すぐに「0」に戻る)
  btn_pw = M5.Axp.GetBtnPress();
  delay(20);  // 20ms遅延時間
}

5.サンプルプログラム(マスター側、M5StickC)

マスター側のサンプルプログラムは以下になります。「コピペ」して書き込んでください。
(「M5StickC Plus」でもヘッダーファイルの変更と文字の大きさを調整すれば使用できます。)

「M5StickC Plus2」のプログラムはこの次に公開しています。

※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

// Bluetooth接続マスター側プログラム
#include <M5StickC.h>
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;

// 変数宣言
String slave_name = "BT_Slave";   // スレーブ側の接続名
String master_name = "BT_master"; // マスターの接続名
// uint8_t address[6]  = {0x94, 0xB9, 0x7E, 0x8B, 0x4F, 0xAA};  // MACアドレスで接続の場合、スレーブ側のMACアドレスを設定
bool connected = 0;       // 接続状態格納用
int connect_count = 3;    // 再接続実行回数
String data = "";         // 受信データ格納用
int btn_pw = 0;           // 電源ボタン状態取得用

// 再起動(リスタート)処理
void restart() {
  // 電源ボタン状態取得(1秒以下のONで「2」1秒以上で「1」すぐに「0」に戻る)
  btn_pw = M5.Axp.GetBtnPress();
  if (btn_pw == 2) {  // 電源ボタン短押し(1秒以下)なら
    ESP.restart();    // 再起動
  }
}
// // スレーブ側への送信のみの場合はデータ送信後に接続を切って消費電力を抑える(コメントアウトする、メイン処理のも)
// void disconnect() {
//   // 接続を切る(disconnect()は最大10秒かかる)
//   if (SerialBT.disconnect()) {
//     M5.Lcd.setTextColor(ORANGE, BLACK);
//     M5.Lcd.println("Disconnect");
//     Serial.println("Disconnect");
//   }
// }
// 初期設定 -----------------------------------------------
void setup() {
  M5.begin();             // 本体初期化
  Serial.begin(9600);     // シリアル通信初期化
  // 出力設定
  pinMode(10, OUTPUT);    //本体LED赤
  digitalWrite(10, HIGH); //本体LED初期値OFF(HIGH)
  // LCD表示設定
  M5.Lcd.setTextFont(2);

  // Bluetooth接続開始
  SerialBT.begin(master_name, true);  // マスターとして初期化。trueを書くとマスター、省略かfalseを指定でスレーブ
  M5.Lcd.print("BT Try!\n.");
  Serial.print("BT Try!\n.");
  // connect(address)は高速(最大10秒)、connect(slave_name)は低速(最大30秒)
  // slave_nameでの接続はMACアドレスを調べなくても良いが接続は遅い
  while (connected == 0) {    // connectedが0(未接続)なら接続実行を繰り返す
    if (connect_count != 0) { // 再接続実行回数カウントが0でなければ
      connected = SerialBT.connect(slave_name); // 接続実行(接続名で接続する場合)
      // connected = SerialBT.connect(address);   // 接続実行(MACアドレスで接続する場合)
      M5.Lcd.print(".");
      connect_count--;        // 再接続実行回数カウント -1
    } else {                  // 再接続実行回数カウントが0なら接続失敗
      M5.Lcd.setTextColor(RED, BLACK);
      M5.Lcd.print("\nFailed!");
      Serial.print("\nFailed!");
      while (1) {restart();}  // 無限ループ(再起動待機)
    }
  }
  // 接続確認
  M5.Lcd.setTextColor(WHITE, BLACK);
  if (connected) {                    // 接続成功なら
    M5.Lcd.setTextColor(CYAN, BLACK);
    M5.Lcd.println("\nConnected!");   // 「Connected!」表示
    Serial.println("\nConnected!");
  } else {                            // 接続失敗なら
    M5.Lcd.setTextColor(RED, BLACK);
    M5.Lcd.println("\nFailed!!");     // 「Failed!!」表示
    Serial.println("\nFailed!!");
    while (1) {restart();}            // 無限ループ(再起動待機)
  }
  delay(1000);                        // 接続結果確認画面表示時間
  // 電源ON時のシリアルデータが無くなるまで待つ
  while (Serial.available()) {data = Serial.read();}
  // LCD表示リセット
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.println(master_name);        // 接続名表示
}
// メイン -------------------------------------------------
void loop() {
  M5.update();  // 本体ボタン状態更新
  // ボタン操作処理(スレーブ側へデータ送信)※送信のみでよければコメント部を有効にして省エネ
  if (M5.BtnA.wasPressed()) {     // ボタンAが押されていれば
    // SerialBT.connect();        // 再接続 connect(name)で名前解決されたアドレス、または、connect(address)のMACアドレスで再接続
    if (connected == 1) {
      SerialBT.print("A ON!\r");  // 「A ON!」送信(「CR」区切り文字)
      // disconnect();            // 省エネのため接続を遮断
    }
  }
  if (M5.BtnB.wasPressed()) {     // ボタンBが押されていれば
    // SerialBT.connect();           // 再接続 connect(name)で名前解決されたアドレス、または、connect(address)のMACアドレスで再接続
    if (connected == 1) {
      SerialBT.print("B ON!\r");  // 「B ON!」送信(「CR」区切り文字)
      // disconnect();               // 省エネのため接続を遮断
    }
  }
  // スレーブ側からの受信データをLCDに表示
  if (SerialBT.available()) {               // Bluetoothデータ受信で
    data = SerialBT.readStringUntil('\r');  // 区切り文字「CR」までデータ取得
    M5.Lcd.print("BT: ");                   // 受信データ液晶表示
    M5.Lcd.println(data);                   // 液晶表示は改行あり
    Serial.print(data);                     // シリアル出力は改行なし
  }
  // シリアル入力データ(「CR」付きで入力)をスレーブ側へ送信
  if (Serial.available()) {               // シリアルデータ受信で
    data = Serial.readStringUntil('\r');  // 「CR」の手前までデータ取得
    M5.Lcd.print("SR: ");                 // シリアルデータ液晶表示
    M5.Lcd.println(data);                 // 液晶表示は改行あり
    Serial.print(data);                   // シリアル出力は改行なし
    // Bluetoothデータ送信
    SerialBT.print(data + "\r"); // 区切り文字「CR」をつけてスレーブ側へ送信
  }
  // LED点灯処理
  if (data == "A ON!") {      // 受信データが「A ON!」なら
    digitalWrite(10, LOW);    // 本体LED点灯
  }
  if (data == "B ON!") {      // 受信データが「B ON!」なら
    digitalWrite(10, HIGH);   // 本体LED消灯
  }
  restart();  // 再起動(リスタート)処理
  delay(20);  // 20ms遅延時間
}

・M5StickC Plus2バージョン(追記)

M5StickC Plus2」で動作確認できるようにサンプルプログラムを追加しました。
動作は上の「M5StickC」と同じです。

※下コード(黒枠)内の右上角にある小さなアイコンのクリックでコピーできます。

// Bluetooth接続マスター側プログラム
#include <M5StickCPlus2.h>    // M5StickC Plus2制御用
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;

#define LED 19  // 本体LED

// 変数宣言
String slave_name = "BT_Slave";   // スレーブ側の接続名
String master_name = "BT_master"; // マスターの接続名
// uint8_t address[6]  = {0x94, 0xB9, 0x7E, 0x8B, 0x4F, 0xAA};  // MACアドレスで接続の場合、スレーブ側のMACアドレスを設定
bool connected = 0;       // 接続状態格納用
int connect_count = 3;    // 再接続実行回数
String data = "";         // 受信データ格納用
int btn_pw = 0;           // 電源ボタン状態取得用

// 初期設定 -----------------------------------------------
void setup() {
  auto cfg = M5.config(); // 本体初期設定
  StickCP2.begin(cfg);
  Serial.begin(9600);     // シリアル通信初期化
  // 出力設定
  pinMode(LED, OUTPUT);   //本体LED赤
  digitalWrite(LED, LOW); //本体LED初期値OFF(HIGH)
  // LCD表示設定
  M5.Lcd.setTextFont(2);

  // Bluetooth接続開始
  SerialBT.begin(master_name, true);  // マスターとして初期化。trueを書くとマスター、省略かfalseを指定でスレーブ
  M5.Lcd.print(" BT Try!\n.");
  Serial.print("BT Try!\n.");
  // connect(address)は高速(最大10秒)、connect(slave_name)は低速(最大30秒)
  // slave_nameでの接続はMACアドレスを調べなくても良いが接続は遅い
  while (connected == 0) {    // connectedが0(未接続)なら接続実行を繰り返す
    if (connect_count != 0) { // 再接続実行回数カウントが0でなければ
      connected = SerialBT.connect(slave_name); // 接続実行(接続名で接続する場合)
      // connected = SerialBT.connect(address);   // 接続実行(MACアドレスで接続する場合)
      M5.Lcd.print(".");
      connect_count--;        // 再接続実行回数カウント -1
    } else {                  // 再接続実行回数カウントが0なら接続失敗
      M5.Lcd.setTextColor(RED, BLACK);
      M5.Lcd.print("\nFailed!");
      Serial.print("\nFailed!");
      ESP.restart();    // 再起動
    }
  }
  // 接続確認
  M5.Lcd.setTextColor(WHITE, BLACK);
  if (connected) {                    // 接続成功なら
    M5.Lcd.setTextColor(CYAN, BLACK);
    M5.Lcd.println("\nConnected!");   // 「Connected!」表示
    Serial.println("\nConnected!");
  } else {                            // 接続失敗なら
    M5.Lcd.setTextColor(RED, BLACK);
    M5.Lcd.println("\nFailed!!");     // 「Failed!!」表示
    Serial.println("\nFailed!!");
    ESP.restart();    // 再起動
  }
  delay(1000);                        // 接続結果確認画面表示時間
  // 電源ON時のシリアルデータが無くなるまで待つ
  while (Serial.available()) {data = Serial.read();}
  // LCD表示リセット
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.println(master_name);        // 接続名表示
}
// メイン -------------------------------------------------
void loop() {
  M5.Lcd.setTextFont(4);
  M5.update();  // 本体ボタン状態更新
  // ボタン操作処理(スレーブ側へデータ送信)※送信のみでよければコメント部を有効にして省エネ
  if (M5.BtnA.wasPressed()) {     // ボタンAが押されていれば
    // SerialBT.connect();        // 再接続 connect(name)で名前解決されたアドレス、または、connect(address)のMACアドレスで再接続
    if (connected == 1) {
      SerialBT.print("A ON!\r");  // 「A ON!」送信(「CR」区切り文字)
    }
  }
  if (M5.BtnB.wasPressed()) {     // ボタンBが押されていれば
    // SerialBT.connect();           // 再接続 connect(name)で名前解決されたアドレス、または、connect(address)のMACアドレスで再接続
    if (connected == 1) {
      SerialBT.print("B ON!\r");  // 「B ON!」送信(「CR」区切り文字)
    }
  }

  // ボタンC(電源ボタン)USB未接続時に即時電源OFF
  if (digitalRead(35) == (LOW)) {  // 電源が押されていれば
    ESP.restart();    // 再起動
  }

  // スレーブ側からの受信データをLCDに表示
  if (SerialBT.available()) {               // Bluetoothデータ受信で
    data = SerialBT.readStringUntil('\r');  // 区切り文字「CR」までデータ取得
    M5.Lcd.print("BT: ");                   // 受信データ液晶表示
    M5.Lcd.println(data);                   // 液晶表示は改行あり
    Serial.print(data);                     // シリアル出力は改行なし
  }
  // シリアル入力データ(「CR」付きで入力)をスレーブ側へ送信
  if (Serial.available()) {               // シリアルデータ受信で
    data = Serial.readStringUntil('\r');  // 「CR」の手前までデータ取得
    M5.Lcd.print("SR: ");                 // シリアルデータ液晶表示
    M5.Lcd.println(data);                 // 液晶表示は改行あり
    Serial.print(data);                   // シリアル出力は改行なし
    // Bluetoothデータ送信
    SerialBT.print(data + "\r"); // 区切り文字「CR」をつけてスレーブ側へ送信
  }
  // LED点灯処理
  if (data == "A ON!") {      // 受信データが「A ON!」なら
    digitalWrite(LED, HIGH);    // 本体LED点灯
  }
  if (data == "B ON!") {      // 受信データが「B ON!」なら
    digitalWrite(LED, LOW);   // 本体LED消灯
  }
  delay(20);  // 20ms遅延時間
}

6.Bluetooth通信プログラムの詳細

サンプルプログラムは長々と書いてますが、Bluetooth通信の部分だけ抜き出すと以下のようにシンプルです。

・MACアドレスの確認方法

「MACアドレス」とは機器固有の識別番号で、同じ番号を持った機器は存在しません。
このため「MACアドレス」を確認することで対象の機器を特定することができます。

「MACアドレス」を確認するには以下のようにプログラム内に書き込みます。
これでシリアルモニタに「MACアドレス」が表示されて確認できます。

// MACアドレスの取得と表示
uint8_t macBT[6];                 // MACアドレス格納用配列を準備
esp_read_mac(macBT, ESP_MAC_BT);  // MACアドレス取得

Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X\r\n", macBT[0], macBT[1], macBT[2], macBT[3], macBT[4], macBT[5]);

・マスター側、スレーブ側共通

Bluetooth通信を開始するコマンドは、マスター側とスレーブ側で共通で以下のようになります。

#include <M5StickCPlus.h>     // 使用するマイコンボードのヘッダファイル
#include "BluetoothSerial.h"  // Bluetooth通信用のヘッダファイル
BluetoothSerial SerialBT;     // インスタンスを準備

String data = "";       // 受信データ格納用

// 初期設定 -----------------------------------------------
void setup() {
  M5.begin();           // 本体初期化
  Serial.begin(9600);   // シリアル通信初期化

  // Bluetooth接続開始
  SerialBT.begin("BT_slave"); // 接続名を指定して初期化。trueを書くとマスター、省略かfalseを指定でスレーブ
}
// メイン -------------------------------------------------
void loop() {
  SerialBT.print("data\r");  // データ送信

  // データ受信時処理
  if (SerialBT.available()) {              // Bluetoothデータ受信で
    data = SerialBT.readStringUntil('\r'); // 「CR」の手前までデータ取得
    Serial.print(data);
  }
  delay(1000);  // 1秒ごとに実行
}

2, 3行目のようにヘッダファイル等を準備して、13行目のように指定するだけでBluetooth通信が開始されます。

・Bluetooth通信を開始するプログラム
 SerialBT.begin ( “接続名”第2引数 ) ;
SerialBT.begin:指定した接続名でBluetooth通信を開始します。
接続名:本体の接続名を設定します。他の機器から見たときにこの名前で接続先が特定できます。
第2引数:「true」でマスター側に設定、「false」または省略でスレーブ側に設定

データの送受信はシリアル通信と同じように扱えます。
シリアルデータの送受信には「Serial」コマンドを使用しますが、Bluetooth通信データの送受信には「SerialBT」コマンドで指定します。

主なコマンドは以下のようになります。(他にもたくさんあります。)

SerialBT. print ( “データ”) ;  // “データ(文字列)”を送信
SerialBT.available( ) ;         // 受信データのバイト数(文字数)を取得
SerialBT.read( ) ;                // 受信データを1文字取得
SerialBT.readStringUntil( ‘\r’) ;  // 受信データを指定した文字の手前まで文字列で取得

今回は受信データの取得には 21行目のように「SerialBT.readStringUntil(‘\r’)」を使用しました。
これで、受信したデータを区切り文字「‘\r’」の手前まで変数(文字列)に格納することができます。

特殊文字(エスケープシーケンス)の「‘\r’」は「キャリッジリターン(CR)」と呼ばれます。

「キャリッジリターン(CR)」とは、機械式の印字装置、タイプライターの動作に由来するものです。
タイプライターでは印字装置が固定で、紙の方が移動することで文字送りや行送りが行われ、紙を固定している部分をキャリッジと言います。
キャリッジを左端に戻す(リターン)ことを「キャリッジリターン(CR)」と言います。
また、行(ライン)を送る(フィード)ことを「ラインフィード(LF)」と言い、タイプライターでは「キャリッジリターン」して「ラインフィード」することで「改行」を行なっていました。
この名残からプログラミングの文字出力の表現として使用されています。
開発環境にもよりますが「ラインフィード(LF)」は特殊文字(エスケープシーケンス)で「’\n’」と書かれ、これだけで改行を表すものも多いです。

区切り文字としては「 ; 」等なんでも良いですが、この場合は毎回「 ; 」を入力する必要があります。
「CR」なら、出力する文字の表示には影響が無く、シリアルモニタで自動で付けて送信できるので便利です。


・マスター側専用

マスター側はスレーブ側と接続するためのコマンドが追加で必要です。
以下ハイライト部がマスター側専用のプログラムです。

※メインループ処理はスレーブ側と同じなので省略してます。

#include <M5StickCPlus.h>     // 使用するマイコンボードのヘッダファイル
#include "BluetoothSerial.h"  // Bluetooth通信用のヘッダファイル
BluetoothSerial SerialBT;     // インスタンスを準備

String data = "";    // 受信データ格納用
uint8_t address[6]  = {0x94, 0xB9, 0x7E, 0x8B, 0x4F, 0xAA};  // MACアドレスで接続の場合、スレーブ側のMACアドレスを設定
bool connected = 0;  // 接続状態格納用

// 初期設定 -----------------------------------------------
void setup() {
  M5.begin();             // 本体初期化
  Serial.begin(9600);     // シリアル通信初期化

  // Bluetooth接続開始
  SerialBT.begin("BT_master", true);  // マスターとして初期化。trueを書くとマスター、省略かfalseを指定でスレーブ

  // connect(address)は高速(最大10秒)、connect(slave_name)は低速(最大30秒)
  // slave_nameでの接続はMACアドレスを調べなくても良いが接続は遅い
  connected = SerialBT.connect("BT_slave"); // 接続実行(スレーブ側の接続名で接続する場合)
  // connected = SerialBT.connect(address);   // 接続実行(スレーブ側のMACアドレスで接続する場合)

  // 接続確認
  if (connected) {                    // 接続成功なら
    Serial.println("\nConnected!");
  } else {                            // 接続失敗なら
    Serial.println("\nFailed!!");
    while (1) {}            // 無限ループ
  }
}

マスター側では19, 20行目のようにスレーブ側と接続するためのプログラムを実行します。
一度接続してしまえばマスター/スレーブ特に区別なく相互通信できます。

スレーブ側と接続する方法は以下のように、「接続名」で指定する場合と「MACアドレス」で指定する場合の2種類あります。

・スレーブ側と接続する方法(2種類)
 SerialBT.connect ( “接続名” ) ;  // スレーブ側の接続名で接続する場合
 SerialBT.connect ( “MACアドレス” ) ; // スレーブ側のMACアドレスで接続する場合

接続名」で指定するよりも「MACアドレス」で指定した方が早く接続できましたが、スレーブ側の管理がしやすいのと、他のマイコンボーへの変更がしやすいのでサンプルプログラムでは「接続名」の方を採用しました。

SerialBT.connect()」を実行して接続が完了すると「1」を返してくるので、22〜28行目のように接続結果を確認して接続が完了した場合のみメイン処理を実行するようにします。


・通信の一時遮断と再接続による消費電力の削減(マスター側のみ)

常に通信し続ける必要がなく、マスター側からデータを送信するだけの場合には、待機中に接続を遮断して消費電力を抑えることができます。(マスター側のサンプルプログラムではコメントアウトしてあります。)

接続の遮断と再接続は以下のように簡単に指定できるので用途に応じて使用しましょう。

SerialBT.disconnect(); // 接続を一時的に遮断する。
SerialBT.connect();    // 再接続する。再接続時は接続名やMACアドレスの指定は不要

7.通信距離の確認

実際に通信距離の確認を行いました。
間に障害物や壁のない環境で、マスター側から送ったデータをスレーブ側からそのままマスター側へ送り返すようにサンプルプログラムを改良して確認しました。

結果は28mまで問題なく送受信できました。
屋内環境でこれ以上距離を取ることができなかったため、ここまでで断念しました・・・。

自宅で確認したところ、1階のリビングの端から、 2階の寝室の端(直線距離10m程度)では通信不可で、寝室の入り口付近では通信可能でした。

見通しの良い直線では予想以上に通信が届きましたが、壁のある環境ではかなり距離が短くなるようです。

ということで、できるだけ障害物のない環境で10m程度の通信には安定して使えそうです。

8.まとめ

「M5StackC Plus」を使用したBluetooth相互通信の方法を紹介しました。

ヘッダファイルを準備してシリアル通信のように「SerialBT.begin()」するだけでBluetooth通信を開始することができます。

接続はマスター側からスレーブ側の「接続名」または「MACアドレス」を指定して行います。
一度接続してしまえばマスター/スレーブ特に区別なく相互通信できます。

通信距離は壁等があると極端に短くなりますが、できるだけ障害物を避けるようにすれば10m程度の距離であれば問題なく通信できると思います。

コメント

タイトルとURLをコピーしました