無線デジタル差圧計/bluetooth接続

いやあ、完全に舐めていました。bluetooth接続。wifi接続と同じくらいに考えていたので、測定データを表示するだけで思った以上に時間を費やしてしまいました。Serial通信だと測定データはそのまま10進数で表示されますが、Bluetoothだとちゃんと選ばないといけないんですね。

SerialBT

Bluetoothで接続しても、シリアル通信と同様にデータ取得ができる優れもの(多分)ですね。(多分)なのは、うまく機能しなかったので便利さが実感できなかった為です。

SerialBTを使うには、esp32のボードをインストールすると付いてくるserialbluetooth.hをインクルードします。esp32なら全部使えるのかと思っていましたが、なにやら様子がおかしい。。。サンプルスケッチそのままコンパイルしようとしても、エラーが出ます。

ちょっと小さくなっていますが、

”Compilation error : exit status 1”

というエラーが出て、コンパイルすることが出来ません。文法が間違っている時は、間違っている個所をハイライトしてくれますが、今回はどこにもハイライトが付いていません。少し調べてみると、arduino-esp32のバージョンを落としてみたり、再インストールで直ることがあるようですが、こちらの環境では効果がありませんでした。

ファイル名にスペースがあることでエラーが出るとの情報もありましたが、どうやって探せばよいのか。。。

SerialBTを組み込んだスケッチも作りましたが、動作確認まで辿り着かなかったので、貼り付けるのはやめておきます。

BLE

勉強が全然追いついていませんが、Bluetoothには二種類あるんですね。通常のBluetooothとBluetooth Low Energy(BLE)です。次はBLEでの接続を試してみます。

Xiao ESP32C3のメーカーサイト(Seeed Studio)にBluetooth Serverのサンプルスケッチがあるので、そっくりそのまま使ってみます。

Bluetooth Usage | Seeed Studio Wiki

上のサンプルスケッチのすぐ下にTIPとして修正点が記載されていますので、忘れず反映させます。修正点は、下の通りですね。

std::string value = pCharacteristic->getValue(); change to String value = pCharacteristic->getValue();

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"


class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      //std::string value = pCharacteristic->getValue();
      String value = pCharacteristic->getValue(); //←修正箇所

      if (value.length() > 0) {
        Serial.println("*********");
        Serial.print("New value: ");
        for (int i = 0; i < value.length(); i++)
          Serial.print(value[i]);

        Serial.println();
        Serial.println("*********");
      }
    }
};

void setup() {
  Serial.begin(115200);

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();

  BLEService *pService = pServer->createService(SERVICE_UUID);

  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());

  pCharacteristic->setValue("Hello World");
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
}

Xiao ESP32C3にbluetooth接続してデータをやり取りするクライアントとして、メーカーサイトでも例として挙げられているLightBlueをスマホにインストールします。

接続自体はスゴク簡単ですね。サンプルスケッチをコンパイルして書き込んだESP32(名前はMyESP32)をLightBlueで探してみると、直ぐに見つかります。

Connectを開くともう繋がっています。

サンプルスケッチでは”Hello world”を発信しているので、設定されているUUIDのキャラクタリスティックを開いてReadしてみると、

16進数で書かれた情報が読み出せました。画面右上に”HEX”とあるので、ここをタップして開くと、文字コードを選ぶことが出来ます。HEXからUTF-8stringに変えてセーブすると、

おお!読めた!

LightBlue側から文字を入力してみます。

キャラクタリスティックでWrite New Valueからアルファベットと日本語を入力すると、

おお!!arduinoIDEのシリアルモニタで文字が表示出来た!その上日本語もいけた!

それはそうと、平仮名とか漢字とか表示できるんですね。英数記号以外は全く受け付けないのかと思っていました。

Xiao ESP32C3とLightBlueのbluetooth接続自体は簡単に行きました。問題はここからですね。

(単独)デジタル気圧計に組み込み

参考にしたのは、作りながら学ぶArduino+=電子工作入門さんの記事です。

Seeed Studio XIAO ESP32C3でBLE ③ I2CでセンサBMP280をつなぐ – Arduinoクックブック

参考にしたというかなんというか、そっくりそのままです。違う点は、こちらではLCDでの表示を残しているくらいでしょうか。BLE部分はそのままなのでスケッチを貼るのは憚られますが、一応こんな感じになりました。

#include <Wire.h>

#define SDA D4
#define SCL D5

#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp; // I2C

#include <ST7032.h>
ST7032 lcd(0x3E);

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

float temp = 0;
float press = 0;

#define SERVICE_UUID "ec55ef5e-****-****-****-************"
#define CHARA_T_UUID "f0254e0e-****-****-****-************"
#define CHARA_P_UUID "cce39fae-****-****-****-************"

BLECharacteristic *tCharacteristic;
BLECharacteristic *pCharacteristic;


void setup() {
  Wire.begin();

  pinMode(SDA, INPUT_PULLUP); //D4 --SDA pin, pullup
  pinMode(SCL, INPUT_PULLUP); //D5 --SCL pin, pullup

  lcd.begin(16,2);
  lcd.setContrast(10);

  lcd.setCursor(0,0);
  lcd.print("1P");
  lcd.setCursor(13,0);
  lcd.print("Pa");
  lcd.setCursor(0,1);
  lcd.print("TEMP");
  lcd.setCursor(12,1);
  lcd.print("C");

  byte degree[] = {
    0b00111,
    0b00101,
    0b00111,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
    0b00000,
  };
  lcd.createChar(0, degree);
  lcd.setCursor(11,1);
  lcd.write(byte(0));

  unsigned status;
  status = bmp.begin(0x76); // I2C address

  /* Default settings from datasheet. */
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

  BLEDevice::init("PI-001");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  tCharacteristic = pService->createCharacteristic(
      CHARA_T_UUID,
      BLECharacteristic::PROPERTY_READ |
      BLECharacteristic::PROPERTY_NOTIFY
  );
  pCharacteristic = pService->createCharacteristic(
      CHARA_P_UUID,
      BLECharacteristic::PROPERTY_READ |
      BLECharacteristic::PROPERTY_NOTIFY
  );

  pService->start();
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  BLEDevice::startAdvertising();
}

void loop() {
    temp = bmp.readTemperature();
    press = bmp.readPressure();

    lcd.setCursor(3,0);
    lcd.print(press);
    lcd.setCursor(5,1);
    lcd.print(temp);

    tCharacteristic->setValue(temp);
    tCharacteristic->notify();
    pCharacteristic->setValue(press);
    pCharacteristic->notify();

    delay(2000);
}

LightBlueで見てみると、ちゃんと接続は出来ていますね。UUIDがf0254e0e-で始まるほうが温度計、cce39fae-で始まるほうが圧力計です。


温度計のキャラクタリステックを開いてReadしてみると、16進数でなにやらデータを読み込めています。サンプルスケッチの時と同様に、文字コードを変えてみると、


んんん?
どの文字コードでもまともに読めない。LCDで表示している温度計の数字は21℃近辺なので、温度計がおかしいわけではないですね。

ここからしばらく16進数の文字列を変換する旅に出ますが、まともな数字になりません。まあ、全く勉強せずに手当たり次第に試すので、なかなか答えは出ませんね。2週間くらい悩んでしまいました。

何度かLightBlueを触っていると、整数や浮動小数点のところには、Endiannessという項目があって、BigとLittleが選択できることに気が付きました。ここをBigからLittleに変えると、


おお!室温が表示出来た!!
いや、これレベル高いですね。勉強していないので当然ですが、さっぱり意味が分かりません。Endiannessがどういうものか知らない上に、bigの反対はsmallじゃなかろうかとか、littleの反対はlargeじゃなかったっけとか、どうでもいいことが頭を巡って、解説を読んでもさっぱり頭に入ってきません。

まあ、目的はbluetoothで圧力データをやり取りすることなので、詳しいことは後日勉強することにしましょう。

同様に、圧力の方のキャラクタリスティックも、floatのEndiannessでLittleを選ぶことで表示が出来ました。

単位はPaなので桁数が多いですが、作ろうとしているのは微小な差圧計なのでこれくらでちょうどいいです。

いやー、bluetoothはserialとは単語が全然違うのと、スケッチの文法も何か違いますよね。::とかー>とか、これまであまり見かけなかった気がします。まあ、なんとかbluetoothで接続することが出来て、圧力計データを読み出すところまで来ることが出来ました。

bluetoothの詳しいところは、また後日勉強することにして、差圧計の作成を進めます。次は対となる二個目の気圧計と、Xiao ESP32C3同士のBLE接続かな。

コメントを残す

しろすけ技術研究所
主任研究員

こんにちは。市民農園で野菜作りをしているしろすけです。極小規模の栽培管理システム開発をいつかやってみたいと思っていました。2024年から育苗ケース給排気温調や、水耕栽培管理システムの試作を電子工作で始めました。想像以上に検討することがあったので、記録を残すことにします。バイク(SR400)と耕運機(FV200)の整備記録もついでに記録に残しておきます。


しろすけ技術研究所をもっと見る

今すぐ購読し、続きを読んで、すべてのアーカイブにアクセスしましょう。

続きを読む