Hobby Science&Experiment

愛と工作の日々

趣味でやっている工作や勉強したことのメモ書きです。

ESP-WROOM-32D開発ボードでSwitchbotを動作させる

ESP-WROOM-32D開発ボードとSwitchbotを動かしてみたいと思います。
前回のコードからM5StickC関係の部分を削除するだけで動作しました。
並列処理はまだ使い方が分からないので、スライドスイッチを利用してPIN 25がONであればスイッチボットが10秒に一回動作するように設定します。

配線

ESP-WROOM-32D開発ボードの25番ピンとGNDを接続すると、PIN25=ONと判断されスイッチボットが動作するようにします。なのでこの間にスライドスイッチを差し込んでおきます。
スライドスイッチがONである間は、10秒に一回スイッチボットへ動作指令が飛ぶようなプログラムになってます。

コード

static String MAC_SWITCHBOT = "xx:xx:xx:xx:xx:xx";のxxの部分にスイッチボットのMACアドレスを入力してください。

//#include <M5StickC.h>
#include <driver/i2s.h>
#include "BLEDevice.h"

//追加
#define BTN_A_PIN 34
#define BTN_B_PIN 18
#define LED_PIN   10

// このLEDは、GPIO10の電位を下げることで発光するタイプ
#define LED_ON  LOW
#define LED_OFF HIGH

// INPUT_PULLUPが有効かは不明だが、有効という前提で定義
#define BTN_ON  LOW
#define BTN_OFF HIGH

uint8_t prev_btn_a = BTN_OFF;
uint8_t btn_a      = BTN_OFF;

// このLEDは、GPIO10の電位を下げることで発光するタイプ
#define LED_ON  LOW
#define LED_OFF HIGH

// INPUT_PULLUPが有効かは不明だが、有効という前提で定義
#define BTN_ON  LOW
#define BTN_OFF HIGH

// 手元のSwitchBotのMACアドレス
static String MAC_SWITCHBOT = "C3:8D:26:47:8A:55";

// SwitchBotのBLE情報
static BLEUUID SERV_SWITCHBOT("cba20d00-224d-11e6-9fb8-0002a5d5c51b");
static BLEUUID CHAR_SWITCHBOT("cba20002-224d-11e6-9fb8-0002a5d5c51b");
// SwitchBot へ送信するコマンド
// アームを倒し、引く動作の場合 {0x57, 0x01, 0x00}
// 以下2つはスマートフォンアプリでモードを変える必要あり
// アームを倒す動作の場合 {0x57, 0x01, 0x01}
// アームを引く動作の場合 {0x57, 0x01, 0x02}
static uint8_t cmdPress[3] = {0x57, 0x01, 0x01};

#define PIN_CLK  0
#define PIN_DATA 34
#define READ_LEN (2 * 1024)
#define SAMPLING_FREQUENCY 44100

uint8_t BUFFER[READ_LEN] = {0};
uint16_t *adcBuffer = NULL;
//const uint16_t FFTsamples = 256;  // サンプル数は2のべき乗//消去
//double vReal[FFTsamples];  // vReal[]にサンプリングしたデーターを入れる//消去
//double vImag[FFTsamples];//消去
//arduinoFFT FFT = arduinoFFT(vReal, vImag, FFTsamples, SAMPLING_FREQUENCY);  // FFTオブジェクトを作る//消去

bool doScan = true;
BLEScan* pBLEScan;
static BLEAddress *pGattServerAddress;
static BLEAdvertisedDevice* myDevice;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEClient*  pClient = NULL;

unsigned int sampling_period_us;
float dmax = 10000.0;

bool doDetection = false;
bool sendFlg = false;
bool cas = false;


//int printCount = 0;

void log(String s) {
  Serial.println(s);
}


// BLEへの接続 コールバック
class MyClientCallback : public BLEClientCallbacks {
    void onConnect(BLEClient* pclient) {
      Serial.println("onConnect");
      //    log("cc conn");
    }
    void onDisconnect(BLEClient* pclient) {
      Serial.println("onDisconnect");
      //    log("dis");
      //    doScan = true;
      //    doDetection = false;
      if (cas) {
        esp_restart();
      }
    }
};

// アドバタイズ検出時のコールバック
class advdCallback: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
      if (advertisedDevice.haveServiceUUID()) {
        String addr = advertisedDevice.getAddress().toString().c_str();
        Serial.printf("It have service addr: %s \n", advertisedDevice.getAddress().toString().c_str());
        if (addr.equalsIgnoreCase(MAC_SWITCHBOT)) {
          // SwitchBot を発見
          //        if (advertisedDevice.getServiceUUID().equals(SERV_SWITCHBOT)) {
          log("found");

          advertisedDevice.getScan()->stop();
          pGattServerAddress = new BLEAddress(advertisedDevice.getAddress());
          myDevice = new BLEAdvertisedDevice(advertisedDevice);

          doScan = false;
          doDetection = true;
//          m5LED(500, 2);
        }
      }
    }
};


void setup() {
  Serial.begin(115200);
  pinMode(BTN_A_PIN, INPUT_PULLUP);//追加

  log("Start");

  // BLE 初期化
  BLEDevice::init("");
  // デバイスからのアドバタイズをスキャン
  pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new advdCallback());
  pBLEScan->setActiveScan(true);
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
}

void loop() {
  btn_a = digitalRead(BTN_A_PIN);//追加
  if((btn_a == BTN_ON)){//追加   

    if (doScan) {
      log("Scan");
      pBLEScan->start(5, false);
    }

    if(doScan == false){
      digitalWrite(LED_PIN, LED_ON);
     //digitalWrite(LED_PIN, LED_OFF);
      
      if (connectAndSendCommand(*pGattServerAddress)) {
        log("Done!");
        sendFlg = false;
        doScan = false;
        delay(10000);
      } else {
        log("Failed.");
        doScan = true;
        delay(3000);
      }
    }
  }
  vTaskDelay(500 / portTICK_RATE_MS);
}

// SwitchBot の GATT サーバへ接続 ~ Press コマンド送信
static bool connectAndSendCommand(BLEAddress pAddress) {
  cas = true;
  try {
    pClient = BLEDevice::createClient();

    pClient->setClientCallbacks(new MyClientCallback());

    log("Connecting");
    while (!pClient->connect(myDevice)) {
      log("reconnect");
      delay(1000);
    }

    // 対象サービスを得る
    BLERemoteService* pRemoteService = pClient->getService(SERV_SWITCHBOT);
    if (pRemoteService == nullptr) {
      log("e:service not found");
      return false;
    }

    // 対象キャラクタリスティックを得る
    pRemoteCharacteristic = pRemoteService->getCharacteristic(CHAR_SWITCHBOT);
    if (pRemoteCharacteristic == nullptr) {
      log("e:characteristic not found");
      return false;
    }

    // キャラクタリスティックに Press コマンドを書き込む
    pRemoteCharacteristic->writeValue(cmdPress, sizeof(cmdPress), false);
    //    pRemoteCharacteristic->writeValue("test", true);
    log("Send");

    cas = false;

    delay(3000);
    pClient->disconnect();
    pClient = NULL;
    delay(1000);
  }
  catch (...) {
    log("error");
    if (pClient) {
      pClient->disconnect();
      pClient = NULL;
    }
    return false;
  }

  return true;
}

動作