M5atomで取得した情報をbluetoothを経由してM5stackのディスプレイに表示させてみた。

# 初めに
M5atomで取得した土壌センサーの値をM5stackのディスプレイに表示させてみました。
![IMG_4951.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176158/4ae01e41-f91b-a854-9520-baaf6753d105.jpeg)
![IMG_4956.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176158/385cd9e0-07a5-ee41-491a-6851a09f8600.jpeg)

# 環境
OS: windows 10.0
Arduino IDE：2.0.0
デバイス:M5stackcore2,M5atom,[M5Stack用土壌水分センサユニット](https://www.switch-science.com/products/4049)

## bluetooth接続
M5 atomのbleutooth接続は、Masterと、M5stack core2はSlaveとしました。
M5 atomでは、M5stack core2の接続先を指定して、Set upのときに接続、切断のテストを行っています。M5atomのボタンを押すと土壌センサから値を取得し、bluetoothに転送させています。その後、M5stack core2側では、ディスプレイへ転送結果を表示させるようにしました。
![スクリーンショット 2023-02-26 18.59.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176158/af0d29c2-0f43-7da5-112a-c08e255cf074.png)

### bluetooth接続先の取得
最初にslaveのbluetoothのMACアドレスを取得します。下記プログラムを実行すると、シリアルモニタに出力されます。

```test.cc

#include <M5Core2.h>

void setup(void) {
  Serial.begin(115200);
  Serial.println("-----------------");
  uint8_t macBT[6];
  esp_read_mac(macBT, ESP_MAC_BT);
  Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X\r\n", macBT[0], macBT[1], macBT[2], macBT[3], macBT[4], macBT[5]);
}

void loop() {
  delay(1000);
}

```

## プログラム
### M5 atom側
最初にM5 atom側のスケッチです。先ほど取得したMACアドレスを```MACadd、address```へ入力します。プログラムは、bluetoothの接続、切断をテストし、再度接続、その後、ボタンを押すと、bluetoothを経由してデータを転送することができます。

```test.cc
#include "M5Atom.h"
#include "BLEDevice.h"
#include "BLEUtils.h"
#include "BLEBeacon.h"
#include "esp_sleep.h"
#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

String MACadd = "XA:XB:XC:XD:XE:XF";
uint8_t macBT[6];
uint8_t address[6]  = {0xXA, 0xXB, 0xXC, 0xXD, 0xXE, 0xXF};
bool connected;

int bluetooth_address =0;
uint16_t analogRead_value = 0;
uint16_t digitalRead_value = 0;
uint16_t device_id = 0x0101;        // your any sensor device id

BLEAdvertising *pAdvertising;

void readEarthSensor() {
  analogRead_value = analogRead(32);
  digitalRead_value = digitalRead(26);
  Serial.printf("0x%04x, %d, %d\n", device_id, digitalRead_value, analogRead_value);
}

void print_readEarthSensor() {
  analogRead_value = analogRead(32);
  digitalRead_value = digitalRead(26);
  //SerialBT.printf("%d,%d\r", digitalRead_value, analogRead_value);
  SerialBT.printf("%d\r", analogRead_value);
}

void setAdvData() {
  BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();

  oAdvertisementData.setFlags(0x06); // BR_EDR_NOT_SUPPORTED | LE General Discoverable Mode
  std::string strServiceData = "";
  strServiceData += (char)0x08;   // length
  strServiceData += (char)0xff;   // AD Type 0xFF: Manufacturer specific data
  strServiceData += (char)0xff;   // Test manufacture ID
  strServiceData += (char)0xff;   // Test manufacture ID
  strServiceData += (char)((device_id >> 8) & 0xff);
  strServiceData += (char)(device_id & 0xff);
  strServiceData += (char)((analogRead_value >> 8) & 0xff);
  strServiceData += (char)(analogRead_value & 0xff);
  strServiceData += (char)(digitalRead_value & 0xff);

  oAdvertisementData.addData(strServiceData);
  pAdvertising->setAdvertisementData(oAdvertisementData);
}

void setup() {
  M5.begin(true, false, true);
  delay(10);
  Serial.begin(115200);
  M5.dis.clear();
  pinMode(26, INPUT);
  Serial.println("\nEarth Test");
  // Read earth sensor value
  readEarthSensor();
  
  // Create the BLE Device
  BLEDevice::init("Earth_Beacon");
  pAdvertising = BLEDevice::getAdvertising();

  // set advertizing packet data
  setAdvData();
  delay(3000);
  
  // Check my bluethooth address. for debug.
  if (bluetooth_address == 1){
  Serial.println("-----------------");
  esp_read_mac(macBT, ESP_MAC_BT);
  Serial.printf("%02X:%02X:%02X:%02X:%02X:%02X\r\n", macBT[0], macBT[1], macBT[2], macBT[3], macBT[4], macBT[5]);
  }
  // Start advertising
  pAdvertising->start();
  Serial.println("Advertizing started...");
  delay(1200);
  pAdvertising->stop();
  
  // Set bluethooth master.
  SerialBT.begin("ESP32test", true);  //Bluetooth device name
  Serial.println("The device started in master mode, make sure remote BT device is on!");
  
  connected = SerialBT.connect(address);  
  if(connected) {
    Serial.println("Connected Succesfully!");
  } else {
    while(!SerialBT.connected(10000)) {
      Serial.println("Failed to connect. Make sure remote device is available and in range, then restart app."); 
    }
  }
  // disconnect() may take upto 10 secs max
  if (SerialBT.disconnect()) {
    Serial.println("Disconnected Succesfully!");
  }
  // this would reconnect to the name(will use address, if resolved) or address used with connect(name/address).
  SerialBT.connect();

}

void loop() {

  if (M5.Btn.wasPressed()) {
  // Read earth sensor value
  readEarthSensor();
  print_readEarthSensor();
  }
  M5.update();
  delay(1*1000);

}
```

### M5stack core2側
M5stack core2側のスケッチです。M5stackからbluetoothへ転送された情報を一旦ポインタに入れてから、出力するようにしています。何度も転送したときに文字化けしたので、メモリの確保と解放させるために入れてます。

```test.cc
#include <M5Core2.h>
#include "BluetoothSerial.h"
#include <stdio.h>
#include <stdlib.h>

// 構造体の宣言
typedef struct {
	char *str;
} strct;

//Bluetooth
BluetoothSerial SerialBT;

// sprite 
TFT_eSprite sprite = TFT_eSprite(&M5.Lcd);

int   earth_analog = 0; 

void setup() {
  M5.begin();
  M5.Lcd.setBrightness(10);
  M5.Lcd.setRotation(1); 
  M5.Lcd.setTextSize(2);
  M5.Lcd.fillScreen(BLACK);

  SerialBT.begin("M5Stack2",false);
  Serial.println("M5 Slave mode. you can pair it with bluetooth!");

  Wire.begin();               //  // Wire init, adding the I2C bus.
  qmp6988.init();
  sprite.setColorDepth(8);
  sprite.setTextSize(2);
  sprite.fillScreen(BLACK);
  sprite.createSprite(M5.lcd.width(), M5.lcd.height());

}

void loop() {

  sprite.pushSprite( 0, 0);
  M5.update();// update button state

    sprite.fillScreen(BLACK);
    // print for earth
    sprite.setTextColor(WHITE);
    sprite.setCursor(10, 10, 1); 
    sprite.printf("DEVICE NAME");
    sprite.setTextColor(ORANGE); 
      sprite.setCursor(60, 30, 4);
    sprite.printf("EARTH");
    // print for blue tooth 
    sprite.setTextColor(WHITE);
    sprite.setCursor(10, 80, 1); 
    sprite.printf("Bluetooth connect");
    sprite.setTextColor(BLUE);
    sprite.setCursor(60, 110, 4);
    SerialBT.available() ? sprite.printf("On") : sprite.printf("Off");
    // print for blue tooth
    sprite.setTextColor(WHITE);
    sprite.setCursor(10, 160, 1);
    sprite.printf("Analog value");
    sprite.setTextColor(TFT_MAROON);       
    sprite.setCursor(60, 190, 4);     
    sprite.printf("%04d\n", earth_analog);

    if (SerialBT.available()) {
      // Set up ant allocating dynamic memory
      strct *receive_dataStr;
	    receive_dataStr = (strct*)malloc(sizeof(strct));
	    receive_dataStr->str = (char*)malloc(sizeof(char) * 64); //initalize
      sprintf(receive_dataStr->str, "%s", SerialBT.readStringUntil('\r'));
      Serial.print(receive_dataStr->str); // for debug
      earth_analog = atoi(receive_dataStr->str);
      free(receive_dataStr->str);
      free(receive_dataStr);
    delay(1 * 1000); 
    }
}


```

### 参考リンク
今回のプログラムを作成するにあたって、下記リンクを参考にさせていただきました。ありがとうございました。
https://karakuri-musha.com/inside-technology/arduino-m5stickc-plus-10-bluetooth-serialimu-01/
[ESP32同士をBluetoothシリアルでつないでみる](http://robooptions.blog.fc2.com/blog-entry-9.html)