ATOM Liteを2台使用して、bluetoothの双方向通信を行います。
開発環境 VSCODE + PlatformIO
使用したライブラリ
FastLED by Daniel Garcia
M5Atom by M5Stack
LovyanGFX by lovyan03
Macアドレス探索で参考にさせてもらったブログ
今回は、bluetoothのMacアドレスを指定して1対1の通信を行います。
※bluetooth Classicモードでは、マスターは複数接続できるはずです。
マスター(Host)サイドで、ペアリング先のbluetoothデバイスを、bluetoothMacアドレスで指定します。
前もって、スレーブ(Client)サイドのmacアドレスをUSBシリアルに出力して、メモしておきます。
uint8_t bt_mac[6];
//bluetoothクライアントアドレスの表示
esp_read_mac(bt_mac, ESP_MAC_BT);
Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
bt_mac[0], bt_mac[1], bt_mac[2], bt_mac[3], bt_mac[4], bt_mac[5]);
マスターサイドの接続関数で、相手先のmacアドレスを指定します。
uint8_t ClientAtomlite_address[6]={0xA1,0xB1,0x09,0xC1,0x76,0xB8};
//bluetoothデバイスサーチと接続
//advertisingパケット受信。
//Client 側のアドバタイズは停止していないはず。
int times=0;
bool connected;
int btConnectCounter;
//相手先探索
do
{
connected = SerialBT.connect(ClientAtomlite_address);//10秒でタイムアウト
Serial.printf("%d connected=%d ",times,connected);
times++;
if(times==30)
{
Serial.println("error:connect timeout");
break;
}
}while(!connected);
相手先とのペアリングシーケンスが成功すれば、接続完了です。
Master(Host)サイドのコード
platformIOの設定と使用ライブラリ
[env:m5stack-atom]
platform = espressif32
board = m5stack-atom
framework = arduino
lib_deps =
m5stack/M5Atom@^0.1.2
fastled/FastLED@^3.7.0
lovyan03/LovyanGFX@^1.1.16
upload_port = COM7
/*
**********************************************************************************
M5 ATOM Lite
SK6812 LED グラデーション表示
※using libratries=> M5ATOM, FastLED
**********************************************************************************
*/
#include <M5Atom.h>
#include "mySerialBT.hpp"
#include "myTask.hpp"
/// @brief セットアップ
void setup()
{
int i;
// 本体初期化(UART有効, I2C無効, LED有効)
M5.begin(true,false,true);
delay(50);
Serial.println("Start");
uint8_t bt_mac[6];
//自身のbluetooth macアドレス表示
esp_read_mac(bt_mac, ESP_MAC_BT);
Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
bt_mac[0], bt_mac[1], bt_mac[2], bt_mac[3], bt_mac[4], bt_mac[5]);
//起動を示すLED点滅
for(i=0; i<=1; i++)
{
M5.dis.drawpix(0, 0x0F0000);
delay(500);
M5.dis.drawpix(0, 0x000000);
delay(500);
}
//bluetooth開始 Master MODE-----------------
bluetoothMasterBegin(ClientAtomlite_address);
//タスク開始---------------------
setupRxTask();
}
int counter;
/// @brief メインループ
void loop()
{
M5.dis.drawpix(0, 0x00000F);
SerialBT.printf("cnt=%d\n",counter++);
delay(500);
M5.dis.drawpix(0, 0x0F0F00);
SerialBT.printf("cnt=%d\n",counter++);
delay(500);
}
#ifndef MYSERIALBT_HPP
#define MYSERIALBT_HPP
#include <BluetoothSerial.h>
extern uint8_t ClientAtomlite_address[6];
extern BluetoothSerial SerialBT;
extern void bluetoothMasterBegin(uint8_t *address);
#endif
#include "mySerialBT.hpp"
BluetoothSerial SerialBT;
//相手先bluetooth MACアドレス
uint8_t ClientAtomlite_address[6]={0x??,0x??,0x??,0xA1,0xC6,0x13};
/// @brief bluetoothマスターシリアル通信初期化
/// @param address
void bluetoothMasterBegin(uint8_t *address)
{
//bluetoothモジュールの起動
SerialBT.begin("M5 ATOM master", true);
Serial.println("begin connect");
//bluetoothデバイスサーチと接続
//advertisingパケット受信。
//ATOMLite側のアドバタイズは停止していない。
int times=0;
bool connected;
int btConnectCounter;
//相手先探索
do
{
connected = SerialBT.connect(address);//10秒でタイムアウト
Serial.printf("%d connected=%d ",times,connected);
times++;
if(times==30)
{
Serial.println("error:connect timeout");
break;
}
}while(!connected);
Serial.println("");
delay(30);
if (connected)
{//接続成功
btConnectCounter++;
Serial.printf("Connected Succesfully! %d\n\r",btConnectCounter);
} else
{//接続失敗
while (!SerialBT.connected(10000))
{
Serial.println("Failed to connect.");
}
}
}
#ifndef MYTASK_HPP
#define MYTASK_HPP
#include <stdint.h>
#include <M5ATOM.h>
#define INTERVAL_TASK 33
extern void setupRxTask(void);
extern void bluetoothRXtask(void *arg);
#endif
#include "myTask.hpp"
#include "mySerialBT.hpp"
void setupRxTask()
{
xTaskCreate(bluetoothRXtask, "bluetoothRXtask", 2048, NULL, 1, NULL);
}
void bluetoothRXtask(void *arg)
{
while (1)
{
if(SerialBT.available()>1)
{
String str = SerialBT.readStringUntil('\n');
uint length = str.length();
Serial.print("echo=> ");
Serial.print(str);
Serial.printf("length=%d\r",length);
}
vTaskDelay(INTERVAL_TASK / portTICK_RATE_MS);
}
}
Slave(Client)サイドのコード
PlatformIOの環境と、使用ライブラリ
[env:m5stack-atom]
platform = espressif32
board = m5stack-atom
framework = arduino
lib_deps =
fastled/FastLED@^3.7.0
m5stack/M5Atom@^0.1.2
lovyan03/LovyanGFX@^1.1.16
upload_port = COM19
#include <M5Atom.h>
#include "mySerialBT.hpp"
#include "myGraphics.hpp"
#include "myTask.hpp"
CRGB color[3]={0x000F00,0x00000F,0x000000};
void setup(void)
{
uint8_t bt_mac[6];
M5.begin(true,false,true);
pinMode(22,OUTPUT); //Lチカ用
//bluetoothクライアントアドレスの表示
esp_read_mac(bt_mac, ESP_MAC_BT);
Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X\n",
bt_mac[0], bt_mac[1], bt_mac[2], bt_mac[3], bt_mac[4], bt_mac[5]);
//bluetooth クライアントとして初期化開始
bluetoothClientBegin();
//SSD1306初期化-----------------
lcd.init();
canvas.createSprite(lcd.width(), lcd.height());
canvas.setTextWrap(true); //自動折返し:無し
canvas.fillScreen(TFT_BLACK); //背景塗りつぶし
canvas.setTextColor(TFT_WHITE); //文字色
SerialBT.println("Start\n");
//シリアル通信受信タスクスタート
setUPserialRxTask();
}
void loop(void)
{
//GP22のLEDと、本体LEDの点滅
digitalWrite(22,HIGH);
M5.dis.drawpix(0,color[0]);
delay(500);
digitalWrite(22,LOW);
M5.dis.drawpix(0,color[1]);
delay(500);
}
#ifndef MYSERIALBT_HPP
#define MYSERIALBT_HPP
#include <BluetoothSerial.h>
extern BluetoothSerial SerialBT; //bluetoothインスタンス
extern void bluetoothClientBegin(void);
#endif
#include "mySerialBT.hpp"
/// @brief bluetoothインスタンス
BluetoothSerial SerialBT;
/// @brief bluetooth初期化関数
/// @param address
void bluetoothClientBegin(void)
{
SerialBT.begin("M5 ATOM01",false);
Serial.println("begin connect");
}
#ifndef MYTASK_HPP
#define MYTASK_HPP
#include <stdint.h>
#include <M5ATOM.h>
#define INTERVAL_TASK 33
extern void setUPserialRxTask(void);
extern void serialRxTask(void *arg);
#endif
#include "myTask.hpp"
#include "mySerialBT.hpp"
#include "myGraphics.hpp"
/// @brief シリアル通信受信タスク初期化
void setUPserialRxTask()
{
xTaskCreate(serialRxTask, "serialRxTask", 2048, NULL, 1, NULL);
}
/// @brief Bluetoothシリアル通信受信タスク
/// @param arg
void serialRxTask(void *arg)
{
while (1)
{
if(SerialBT.available()>1)
{
String str = SerialBT.readStringUntil('\n');
uint length = str.length();
SerialBT.print("echo=> ");
SerialBT.print(str);
SerialBT.printf("length=%d\n",length);
Serial.printf("%s\n",str);
//SSD1306 表示------------------------------------
canvas.startWrite();//通信を開始する。(ペリフェラルを占有する)
canvas.fillScreen(TFT_BLACK); // 背景塗り潰し
canvas.setTextSize(1);
canvas.setCursor(0,0, &Font4);
canvas.println("BT Client");
canvas.setCursor(0,20, &Font4);
canvas.printf("%s\n",str);
canvas.pushSprite(0,0);
canvas.endWrite();//通信を終了する。(ペリフェラルの占有を終了する)
}
vTaskDelay(INTERVAL_TASK / portTICK_RATE_MS);
}
}
#ifndef __MYGRAPHICS_HPP__
#define __MYGRAPHICS_HPP__
#define LGFX_USE_V1
#include <LovyanGFX.hpp>
#include <Wire.h>
class LGFX_SSD1306 : public lgfx::LGFX_Device
{
lgfx::Panel_SSD1306 _panel_instance; // SSD1306
lgfx::Bus_I2C _bus_instance; // バス設定用構造体
//コンストラクタ
public:
LGFX_SSD1306()
{
//I2Cバスクラス構造体
{
auto cfg = _bus_instance.config(); //I2Cバス構造体インスタンスの取得
cfg.i2c_port = 1; //Wire1を選択
cfg.freq_write = 400000; // 送信時のクロック クロック周波数
cfg.freq_read = 400000; // 受信時のクロック クロック周波数
cfg.pin_sda = 25; // SDAを接続しているピン番号 SDAピン
cfg.pin_scl = 21; // SCLを接続しているピン番号 SCLピン
cfg.i2c_addr = 0x3C; // I2Cデバイスのアドレス スレーブアドレス
_bus_instance.config(cfg);
_panel_instance.setBus(&_bus_instance);
}
{
auto cfg = _panel_instance.config();
cfg.offset_rotation = 2;
_panel_instance.config(cfg);
}
setPanel(&_panel_instance);
}
};
#include "myGraphics.hpp"
//LovyanGFXインスタンス***********************************************
LGFX_SSD1306 lcd;
LGFX_Sprite canvas(&lcd);