読者です 読者をやめる 読者になる 読者になる

ぱんだのびぼーろく

わたしの備忘録、生物学とプログラミングが多いかも

esp32で心拍を測る

esp-idfのexampleに、GATT profile tableを使ったheart rate計測デモがある.
こやつを解析する.

GATT “Heart Rate”

Heart Rate serviceを利用.
16bit uuid: 0x180D
Viewer | Bluetooth Technology Website

gatts_table_create_demo.c

uuid変数

static uint8_t heart_rate_service_uuid[16] = {
    /* LSB <--------------------------------------------------------------------------------> MSB */
    //first uuid, 16bit, [12],[13] is the value
    0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x18, 0x0D, 0x00, 0x00,
                                                                          //  here    //
};

Bluetooth LEを各種OS, マイコンで使う

Windows

UWP(Universal Windows Platform)がBLEに対応、さすがU!W!P!

また、Bluetooth GATT APIBluetooth LEバイスと連携することによって、次のことが可能となります。
* サービス/特性/記述子の探索 * 特性/記述子の値の読み取りと書き込み * 特性の ValueChanged イベントで呼び出されるコールバックの登録

docs.microsoft.com

Mac (iOS, macOS)

Core Bluetoothフレームワーク

Core Bluetoothフレームワークには、iOS/Macアプリケーションが、Bluetooth Low Energy(BLE)という省電力無線通信技術を実装したデバイスと通信するために必要なクラス群があります。

Core Bluetoothフレームワークは、BLEプロトコルスタックを抽象化しています。
https://developer.apple.com/jp/documentation/CoreBluetoothPG.pdf

ひゅー、なんて簡潔で的確なドキュメントなんだ、素晴らしい.

Linux

gatttool?
Linuxよくわからんでごわす

マイコン

ESP32

esp-idfはBluedroidを基にしたBLEプロトコルスタックを実装している.
esp-idfのAPIを利用してBLEセントラル/ペリフェラルとして機能できる.

Arduino

bluetoothとESP32

#

Bluetooth Low Energy (BLE)を利用したESP32の開発.

ESP32のBLE対応状況

2017-04-04: API群とexampleが存在する. しかし、documentが無い. そして色々不備が指摘されてる.
www.esp32.com
esp-idf2.0で大改修なのかな?

掘り出しもんを見つけた

esp-idf内にHID Over GATT Profile関係…?
命名からして、hid_le_prf = HID Low Energy Profileぽいよね.
esp-idf/hid_le_prf.c at release/v2.0 · espressif/esp-idf · GitHub

Bluetooth のプロファイルについて調べたことのまとめ - Over&Out その後

GATT SERVER API

application callbacksの登録.
esp_ble_gatts_register_callback()

This function is called to register application callbacks with BTA GATTS module.

esp_ble_gap_register_callback()

This function is called to occur gap event, such as scan result.

serviceへのcharacteristic追加.
esp_ble_gatts_add_char()
GATT SERVER API
実体: https://github.com/espressif/esp-idf/blob/47b8f78cb0e15fa43647788a808dac353167a485/components/bt/bluedroid/api/esp_gatts_api.c

This function is called to add a characteristic into a service.

struct esp_attr_value_t
  {
    uint16_t attr_max_len,  
    uint16_t attr_len,  
    uint8_t *attr_value
  }
esp_err_t esp_ble_gatts_add_char(uint16_t service_handle,  esp_bt_uuid_t  *char_uuid,
                                 esp_gatt_perm_t perm, esp_gatt_char_prop_t property, esp_attr_value_t *char_val,
                                 esp_attr_control_t *control){
...
    // set memory block. <string.h> (?)
    memset(&arg, 0, sizeof(btc_ble_gatts_args_t));

    // add to btc_msg struct.
    msg.sig = BTC_SIG_API_CALL;
    msg.pid = BTC_PID_GATTS;
    msg.act = BTC_GATTS_ACT_ADD_CHAR;

    // add functionArguments to "arg" variable.
    arg.add_char.service_handle = service_handle; // argument 0
    arg.add_char.perm = perm; // argument 2
    arg.add_char.property = property; // argument 3
    if (char_val != NULL) { // argument 4
        arg.add_char.char_val.attr_max_len = char_val->attr_max_len;
        arg.add_char.char_val.attr_len = char_val->attr_len;
        arg.add_char.char_val.attr_value = char_val->attr_value;
    }

    if (control != NULL) { .. argument 5
        arg.add_char.attr_control.auto_rsp = control->auto_rsp; 
    }

    // arg.add_char_uuid <- char_uuid
    memcpy(&arg.add_char.char_uuid, char_uuid, sizeof(esp_bt_uuid_t));

    // execute "btc_transfer_context" and return success/failure.
    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gatts_args_t), btc_gatts_arg_deep_copy) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}

[https://github.com/espressif/esp-idf/blob/fbe89a083322c7903fd7baae966441546052354e/components/bt/bluedroid/api/esp_gatts_api.c#L134:title]
typedef struct btc_msg {
    uint8_t sig;    //event signal
    uint8_t aid;    //application id
    uint8_t pid;    //profile id
    uint8_t act;    //profile action, defined in seprerate header files
    void   *arg;    //param for btc function or function param
} btc_msg_t;

[https://github.com/espressif/esp-idf/blob/65f57e5da7287576d98f657ea45163411bc3a564/components/bt/bluedroid/btc/include/btc_task.h:title]  
bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg_deep_copy_t copy_func)
{
    btc_msg_t lmsg;
    //lmsg {
    //    uint8_t sig;    //event signal
    //    uint8_t aid;    //application id
    //    uint8_t pid;    //profile id
    //    uint8_t act;    //profile action, defined in seprerate header files
    //    void   *arg;    //param for btc function or function param
    //}

    if (msg == NULL) {
        return BT_STATUS_PARM_INVALID;
    }

    LOG_DEBUG("%s msg %u %u %u %p\n", __func__, msg->sig, msg->pid, msg->act, arg);

    // copy "msg -> lmsg"
    memcpy(&lmsg, msg, sizeof(btc_msg_t));
    //lmsg {
    //    uint8_t sig: BTC_SIG_API_CALL,    //event signal
    //    uint8_t aid,    //application id
    //    uint8_t pid: BTC_PID_GATTS,    //profile id
    //    uint8_t act: BTC_GATTS_ACT_ADD_CHAR,    //profile action, defined in seprerate header files
    //    void   *arg: many information about "Characteristic"    //param for btc function or function param
    //}

    if (arg) {
        lmsg.arg = (void *)GKI_getbuf(arg_len);
        
        // lmsg.arg : 0x00, 0x00, 0x00, ... (No. arg_len) 0x00.
        memset(lmsg.arg, 0x00, arg_len);    //important, avoid arg which have no length
        if (lmsg.arg == NULL) {
            return BT_STATUS_NOMEM;
        }
        // copy arg -> lmsg.arg(0x00, 0x00, ...)
        memcpy(lmsg.arg, arg, arg_len);

        // copy_finc == btc_gatts_arg_deep_copy
        if (copy_func) {
            copy_func(&lmsg, lmsg.arg, arg);
        }
    } else {
        lmsg.arg = NULL;
    }

    return btc_task_post(&lmsg);
}

[https://github.com/espressif/esp-idf/blob/65f57e5da7287576d98f657ea45163411bc3a564/components/bt/bluedroid/btc/core/btc_task.c:title]  
void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
{
    btc_ble_gatts_args_t *dst = (btc_ble_gatts_args_t *) p_dest;
    btc_ble_gatts_args_t *src = (btc_ble_gatts_args_t *)p_src;

    switch (msg->act) {
...  
        case BTC_GATTS_ACT_ADD_CHAR:{
            if (src->add_char.char_val.attr_value != NULL){
                dst->add_char.char_val.attr_value = (uint8_t *)GKI_getbuf(src->add_char.char_val.attr_len);
                if(dst->add_char.char_val.attr_value != NULL){
                    memcpy(dst->add_char.char_val.attr_value, src->add_char.char_val.attr_value, 
                        src->add_char.char_val.attr_len);
                }else{
                    LOG_ERROR("%s %d no mem\n", __func__, msg->act);
                }
            }
            break;
        }
    ...
    }
...
}

[https://github.com/espressif/esp-idf/blob/c06cc31d85cc700e1dbddbe527d4282c4bc5845a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c#L69:title]  

IoT開発用ハードウェア

あらゆるものをネットワークに繋ぐ、Internet of Things.
この言葉はバズワードを超え、実社会で利用される段階にあります.
本稿は、IoT開発を始めたい、私含めた初学者向けの、ハードウェア(IoTデバイス)紹介記事です.

IoT開発用ハードウェアの要件

  • センサー情報の取得とネットワークへの送信
  • Thingsへの動作命令とネットワークからの受信
    • 命令の送信
      • 赤外線/IR
      • 有線
      • Thingsへの直結

        IoT開発用ハードウェアsとそれらの特徴

  • Raspberry Piシリーズ
  • Arduinoシリーズ
  • ESPシリーズ
    • ESP32

Raspberry Pi Zero W

ワイヤレス対応ラズパイZero.
¥1,300 Raspberry Pi Zero W - スイッチサイエンス
LinuxベースOSを搭載.
GPIO * 27,
GPIOの制御: Linuxの仕組みを使う(LinuxがGPIOデバドラAPIを仮想ファイルでラップ)
tool-lab.com

Arduino

ワンボードマイコン(と開発環境).
マイコン部はAtmel AVR.
OSは無い.
ArduinoIDEという言語・環境で開発.

ESP32

ワイヤレス対応マイコン.
ワイヤレスモージュールを名乗るが、もはや立派なペリフェラル付きマイコンである.
DevKit: ¥1,500 SoC: ¥500~
ArduinoIDEを使うならOS無し、esp-idf使うならfreeRTOS搭載.
GPIO * x, ADC, DAC, I2C, I2S, 静電容量センサ etcetc ペリフェラル満載のSoC
GPIOの制御:
esp-idf: デバドラAPI叩く

  1. どんなOSを搭載するか
  2. Windows/Mac/Linuxのようなハイエンド向けOS?
  3. マイコン向け軽量OS?

    • freeRTOS

ESP32の静電容量式touch sensor with esp-idf

ヘッダーファイル
github.com

実体(.c)
github.com

例1.
github.com

例2.
github.com

ESP32datasheet appendix
https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf#page44

自分でドライバー書いちゃいなYo!

ドライバーが未実装なら実装すればいいじゃない
github.com

ESP32のD/Aコンバータを調査・検証

ESP32のデジタル→アナログ コンバーターを調査・検証してみる。予定

  • スペック
    • 口数: 2口
    • 分解能: 8bit
    • 動作周波数:
    • 変換原理: 抵抗ストリング型
  • How to use
    • 対応GPIO: 25番 & 26番
    • 他のD/A変換法:
    • ESP-IDF
      • DAC-GPIOはなんと関数は1つ、シンプルぅ
      • I2C-GPIOをDACへルーティング可能。サイン波とか簡単に入力可能?
  • 検証結果

スペック

口数と分解能

2つの8bit DACを搭載.

Two 8-bit DAC channels can be used…
https://espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf#page31

変換原理

DACは integrated resistor strings and a bufferから構成される.
つまり、バッファを持つ抵抗ストリング型と予想される.
The design structure is composed of integrated resistor strings and a buffer.

How to use

対応GPIO

25番(channel 1) & 26番(channel 2)

connected to GPIO25 (Channel 1) and GPIO26 (Channel 2).
Digital To Analog Converter — ESP-IDF Programming Guide v2.0-rc1-343-g65baf50 documentation

他のD/A変換法

For other analog output options, see the Sigma-delta Modulation module and the LED Control module. Both these modules produce high frequency PWM output, which can be hardware low-pass filtered in order to generate a lower frequency analog output.
Digital To Analog Converter — ESP-IDF Programming Guide v2.0-rc1-343-g65baf50 documentation

ESP-IDF

DAC直叩き

Header Files
components/driver/include/driver/dac.h

 esp_err_t dac_out_voltage(dac_channel_t channel, uint8_t dac_value)

I2Sルーティング

ESP32にはI2S対応ペリフェラルが2つ。

ESP32 contains two I2S peripherals.
I2S — ESP-IDF Programming Guide v2.0-rc1-343-g65baf50 documentation

DMA(ダイレクト メモリ アクセス)に対応、CPUを介さずにメモリ上のデータをDAC-GPIOへ送れる模様.

The I2S peripheral supports DMA meaning it can stream sample data without requiring each sample to be read or written by the CPU.

I2S output can also be routed directly to the Digital/Analog Converter output channels (GPIO 25 & GPIO 26) to produce analog output directly, rather than via an external I2S codec.
I2S — ESP-IDF Programming Guide v2.0-rc1-343-g65baf50 documentation

検証

ブートストラップ

ブートストラップ:
ブートストラップとは、ブーツの後ろにある輪っかのこと。ブーツを履く際に引っ張って使う.

NOUN.
A loop at the back of a boot, used to pull it on.
en.oxforddictionaries.com