SSブログ

Arduino IDE2.0 Release Candidate を少し試してみた [Arduino]

Arduino IDE 2.0 Release Candidate のアナウンスがあったので早速ダウンロードして試してみました。全体的にかっこよくなっていて、Visual Studio Code を意識した設計となっています。


ArduinoIDE2.png


基本的な使い方は従来のArduino IDEと変わりません。SpresenseのArduino Libraryもインストールできましたので、ESP8266含めて外部ライブラリは従来どおり使えるようです。


ArduinoIDE2_initial.png


一番の驚きなのはデバッガーをサポートしたことです。Spresenseの場合SWD対応のJTAGデバッガーをつなげればデバッグできるようになります。これは朗報ですね。


ArduinoIDE2Debug.png


【参考】SONY Spresense をLPC-Link2(CMSIS-DAP)でデバックしよう
https://qiita.com/usashirou/items/525eeaa9c43acf860f64


簡易版 Visual Studio Code という感じで気軽に使える開発環境となりそうです。しばらく 2.0 RC を使ってみて気づいた点があったらここで紹介したいと思います!







SONY SPRESENSE メインボード CXD5602PWBMAIN1

SONY SPRESENSE メインボード CXD5602PWBMAIN1

  • 出版社/メーカー: スプレッセンス(Spresense)
  • メディア: Tools & Hardware



SONY SPRESENSE 拡張ボード CXD5602PWBEXT1

SONY SPRESENSE 拡張ボード CXD5602PWBEXT1

  • 出版社/メーカー: スプレッセンス(Spresense)
  • メディア: Tools & Hardware




タグ:Arduino
nice!(20)  コメント(0) 
共通テーマ:趣味・カルチャー

Arduino Uno Mini 爆誕 [exclamation] [Arduino]

ArduinoさんがUNOの新作を発表しました。今までのUNOの1/4サイズくらいの大きさの小ぶりのボードで登場してきました。


UNO-vs-UNO-mini.jpg


気になるスペックはこちら。


MICROCONTROLLER ATmega328P
USB CONNECTOR USB-C
BUILT-IN LED PIN 13
DIGITAL I/O PINS 14
ANALOG INPUT PINS 6
PWM PINS 6
UART yes
I2C yes
SPI yes
CIRCUIT OPERATING VOLTAGE 5V
INPUT VOLTAGE (LIMIT) 6-12V
BATTERY CONNECTOR None.
DC CURRENT PER I/O PIN 20 mA
DC CURRENT FOR 3.3V PIN 50 mA
MAIN PROCESSOR ATmega328P 16 MHz
USB-SERIAL PROCESSOR ATmega16U2 16 MHz
MEMORYATMEGA328P 2KB SRAM, 32KB FLASH, 1KB EEPROM
WEIGHT 8.05 g
WIDTH 26.70 mm
LENGTH 34.20 mm



CPUは、なんとATmega328Pそのまま。ライブラリの互換性を重視したのかも知れません。ボードの色は黒。SPRESENSEが出てから黒いボードが流行になってきましたね。ただ、つや消し黒じゃないので、SPRESENSEやPortenta H7よりもちょっと安っぽいかも。


ArduinoUnoMini.jpg


それ以上に目を引くのが、このパッケージ。やはりイタリアの会社はオシャレですね。物欲をそそるパッケージです。内容もすごいオシャレ。化粧品でも入っているのか思うような箱の作りです。外装にお金かけるんだったら、基板もつや消し黒にしてほしかったなぁ。


ArduinoUnoMiniBox.jpg


色々と開発ボードは出てきていますが、老舗のArduinoからもまだまだ目が離せませんね。
(^^)/~



The Arduino Starter Kit(日本語版)

The Arduino Starter Kit(日本語版)

  • 出版社/メーカー: スイッチサイエンス
  • メディア: エレクトロニクス



タグ:Arduino
nice!(17)  コメント(0) 
共通テーマ:趣味・カルチャー

"Arduino Portenta H7" に "Vison Shield" が登場!! [Arduino]

SPRESENSE のコピー品かと思われるようなデザインの Arduino Portenta H7。25mm x 66mm で SPRESENSE よりも一回り大きいくらいのボードです。


ArduinoPortentaH7.png


今一度、仕様をおさらいしてみたいと思います。

Microcontroller STM32H747XI dual Cortex®-M7+M4 32bit low power ARM MCU (datasheet)
Radio module Murata 1DX dual WiFi 802.11b/g/n 65 Mbps and Bluetooth 5.1 BR/EDR/LE (datasheet)
Secure Element (default) NXP SE0502 (datasheet)
Board Power Supply (USB/VIN) 5V
Supported Battery Li-Po Single Cell, 3.7V, 700mAh Minimum (integrated charger)
Circuit Operating Voltage 3.3V
Current Consumption 2.95 μA in Standby mode (Backup SRAM OFF, RTC/LSE ON)
Display Connector MIPI DSI host & MIPI D-PHY to interface with low-pin count large display
GPU Chrom-ART graphical hardware Accelerator[トレードマーク]
Timers 22x timers and watchdogs
UART 4x ports (2 with flow control)
Ethernet PHY 10 / 100 Mbps (through expansion port only)
SD Card Interface for SD Card connector (through expansion port only)
Operational Temperature -40 °C to +85 °C
MKR Headers Use any of the existing industrial MKR shields on it
High-density Connectors Two 80 pin connectors will expose all of the board's peripherals to other devices
Camera Interface 8-bit, up to 80 MHz
ADC 3× ADCs with 16-bit max. resolution (up to 36 channels, up to 3.6 MSPS)
DAC 2× 12-bit DAC (1 MHz)
USB-C Host / Device, DisplayPort out, High / Full Speed, Power delivery



CPUは"STM32H747XI"で Cortex M7 と Cortex M4 のデュアルコアです。STマイクロのホームページで仕様を確認してみると、両方あわせて1,327 DMIPS なのでSPRESENSEにはやや及ばないレベル。(SPRESENSEはM4@300DMIPS x 6 = 1,800DMIS)

RAMとROMの情報がないので、こちらのサイトで確認しました。





SDRAM:64MB / Flash128M-bit で、かなりリッチです。ただSDRAMを使っているので低消費電力はあまり期待できないですね。残念ながら。

おさらいはここまでで、そのシールドが初登場しました。その名も "ARDUINO PORTENTA VISION SHIELD"。名前がかっこいいですね。カメラとEther、ステレオマイクが搭載されています。


pritenta-vision-shield.jpg

CameraHimax HM-01B0 camera module (manufacturer site)
Resolution324 x 324 active pixel resolution with support for QVGA
Image sensorHigh sensitivity 3.6μ BrightSense[トレードマーク] pixel technology
Microphone2 x MP34DT05 (datasheet)
Length66 mm
Width25 mm
Weight11 gr



イメージセンサーの解像度が想像以上に小さい。データシートを確認すると、QVGA 30FPS で 2mW 以下なのでかなり省電力ですが、本体の消費電力がイマイチなのでここで頑張ってもなぁという感じはします。





ひょっとして Global Shutter? とも思ったのですが、残念ながら Rolling Shutter。HDRというわけでもないし。うーん、なんのために使うのかよくわからない。


マイクのほうも確認をしてみました。データシートを確認すると、これはデジタルMEMSマイクですね。となると他のアナログセンサーや指向性マイクの接続は無理そうです。


mems.png


マイクは設置する場所が大事なので嵌め殺しにせずに、コネクタで接続できるようにしてほしかったなぁ。かなり残念。


価格は"Portenta H7"と"Vision Shield"両方あわせて、約 $150 (15,750円:105円/ドル)、SPRESENSEのメインボード、カメラ、LTEボードをあわせると 16,980 円。これぐらいのクラスになるとこれくらいの値段が妥当なのかな。

Arduino Portenta H7は Ether, WiFi/BLE を使えるけど消費電力がもう致命的。一方、SPRESENSEは5百万画素カメラ、アナログマイク4チャンネル、GPS付きで超低消費電力だけど、LTEボードにSIMがいるってことを考えると、どっこいどっこいかな。

プロ向けにとっては、最後は消費電力が決め手になりそう。SPRESENSEのWiFI/BLEやEtherは必要に応じて追加できるし。

ということで和洋のソックリさん対決は、ホビー向けにはArduino Portenta に軍配。低消費電力を追い求めるIoT向けにはSPRESENSEに軍配。という痛み分けの結果となりました。
(○ ̄ ー  ̄○ )





Arduinoをはじめよう 第3版 (Make:PROJECTS)

Arduinoをはじめよう 第3版 (Make:PROJECTS)

  • 出版社/メーカー: オライリージャパン
  • 発売日: 2015/11/28
  • メディア: 単行本(ソフトカバー)



Arduinoをはじめようキット

Arduinoをはじめようキット

  • 出版社/メーカー: スイッチサイエンス
  • メディア: おもちゃ&ホビー



SONY SPRESENSE メインボード CXD5602PWBMAIN1

SONY SPRESENSE メインボード CXD5602PWBMAIN1

  • 出版社/メーカー: スプレッセンス(Spresense)
  • メディア: Tools & Hardware




nice!(25)  コメント(0) 
共通テーマ:趣味・カルチャー

久しぶりにESP-WROOM-02のファームをアップデートしたらクラッシュしたでござる [Arduino]

久しぶりに"ESP-WROOM-02"を引っ張り出して、ファームウェアをアップデートしたら、なんとクラッシュをしてしまったようです。ここまでしてファームを更新できるようにしたのに。(´;ω;`)


DSC_0955.JPG


もともとは、SPRESENSE用のWi-Fi Add-onボードのファームをアップデートしようとしたのですが、ファームがアップデートできない仕様になっていました。残念。


DSC_0956.JPG


なんで、手持ちのESP-WROOM-02を引っ張り出してきてハンダを駆使して最新ファームに更新したのですが、ATコマンドを打ってもウンスン…。

書き込むファーム間違えたかなと思い、もう一度 Flash Downloader を立ち上げファームを更新しようとしたら、無情にも次のようなメッセージが出てきて必ず失敗するようになりました。Σ(゚д゚lll)


======
CONNECT BAUD: 115200
============
.Uploading stub...
Running stub...
Stub running...
[2020-04-03 00:52:07,584][ESP8266Loader_spi[1]][espDownloader.py][line:468][ERROR]: ESP8266 Chip efuse check error esp_check_mac_and_efuse.



書き込んだのは "ESP8266_NONOS_SDK-3.0.3"。リリース日はなんと"2020/03/24"。いやな予感しかしません。(;・∀・)

Google大先生に問い合わせしてみたものの、いまだ解決策はない様子…。まじかー。OTZ…
 
"efuse check error" とか出てるから書き込んではいけない領域に書き込みをしてしまったのかなぁ。ここまで苦労したのに、オレの時間を返してくれよ~!!。・゚・(ノД`)・゚・。

誰か解決策知りませんか?(°д°)









ESP-WROOM-02ピッチ変換済みモジュール《シンプル版》

ESP-WROOM-02ピッチ変換済みモジュール《シンプル版》

  • 出版社/メーカー: スイッチサイエンス(Switch Science)
  • メディア: おもちゃ&ホビー



ESP8266ではじめるIoTプログラミング

ESP8266ではじめるIoTプログラミング

  • 作者: 部員三号
  • 出版社/メーカー:
  • 発売日: 2016/06/06
  • メディア: Kindle版




タグ:ESP-WROOM-02
nice!(33)  コメント(4) 
共通テーマ:趣味・カルチャー

Arduino 新作ボードがまるで SPRESENSE?その違いとは!? [Arduino]

Arduino が新しいボードを発表しました。Arduino Portenta H7 です。インダストリー向けで価格はなんと $99.9!Arduino シリーズ向けとしては少し高い気がしますが個人向けではないので、こんな値段なんでしょうね。で、気になるのがそのフォームファクター。


https://store.arduino.cc/usa/portenta-h7
main-arduino_portenta.jpg


あれぇ?これなんてSPRESENSE??? 

そう、SPRESENSEそっくりなんですよ。でもプロセッサーのシルクがイタリア製らしくおしゃれですね。大きさは、67.64 × 25 mm で SPRESENSE よりも一回り大きな感じですね。少しスリムなRaspberry Pi Zero という感じです。

裏面を見ると、なんとB2Bコネクタが!そこまでSPRESENSEと同じなの!?


board_back.jpg


ということは拡張ボードが出るのかな?

仕様を詳しく見てみましょう。

MicrocontrollerSTM32H747XI dual Cortex-M7+M4 32bit low power ARM MCU
Radio moduleMurata 1DX dual WiFi 802.11b/g/n 65 Mbps and Bluetooth 5.1 BR/EDR/LE
Secure ElementNXP SE0502
Board Power Supply (USB/VIN)5V
Supported Battery Li-Po Single Cell, 3.7V, 700mAh Minimum (integrated charger)
Circuit Operating Voltage 3.3V
Current Consumption 2.95 μA in Standby mode (Backup SRAM OFF, RTC/LSE ON)
Display Connector MIPI DSI host & MIPI D-PHY to interface with low-pin count large display
GPU Chrom-ART graphical hardware Accelerator
Timers 22x timers and watchdogs
UART 4x ports (2 with flow control)
Ethernet PHY 10 / 100 Mbps (through expansion port only)
SD Card Interface for SD Card connector (through expansion port only)
Operational Temperature -40 °C to +85 °C (excl. Wireless module) / -10 °C to +55 °C (incl. Wireless module)
MKR Headers Use any of the existing industrial MKR shields on it
High-density Connectors Two 80 pin connectors will expose all of the board's peripherals to other devices
Camera Interface 8-bit, up to 80 MHz
ADC 3× ADCs with 16-bit max. resolution (up to 36 channels, up to 3.6 MSPS)
DAC 2× 12-bit DAC (1 MHz)
USB-C Host / Device, DisplayPort out, High / Full Speed, Power delivery



カメラをサポートしているのですが、8ビットパラレルっぽいですね。あとSDカードも裏面のB2Bコネクタ (expantion port) 経由で扱えるようです。そこらへんもSPRESENSEと同じかー。完全にベンチマークしてますね。

メモリはデフォルトでRAMが2MB、Flashが16MBといったところで、少しSPRESENSEよりも大きい。ただメモリはオプションで 64MB まで拡張できるようです。TensorFlow Liteも使えるのでメモリが拡張できるのはいいですね。(でも、PoPになると思われるので、かなりお高くなるかと)

ADCが3.6MSPSまでいけるのと、スリープモードで 3μAというのはいいですね。でも回路を見る限り、動かしているときはかなり電力食うと思います。


SPRESENSEとARDUINO PORTENTA H7の違いを簡単にまとめてみました。

SPRESENSEの良いところ
・測位(GPS)機能
・音声出力、音声入力
・LPWA(LTE-M)をサポート
・動作時も省電力


ARDUINO PORTENTA H7の良いところ
・オンボードWiFi/BT
・バッテリチャージャー内蔵
・Sleep時の消費電力が低い
・メモリ拡張可能


どっちも一長一短ですね。PORTENTA H7も拡張ボードでLPWAをサポートしてくるだろうし、一方でSPRESENSEはWiFi/BLEのボードもサポートしているし。この2つの良いところを一緒にするとちょうどいいエッジソリューションなんですけどねぇ。


でも、日本発のボードデザインが本家に参考されるなんてちょっと誇らしいですね。この分野も今まで欧米(主にArduino, Raspberry Pi, Intel ですが)が主導してきましたが、ここにきて日本勢が巻き返してきた感じです。ソニーだけでなくルネサスもがんばってほしいなぁ。
(^^)





Arduinoをはじめよう 第3版 (Make:PROJECTS)

Arduinoをはじめよう 第3版 (Make:PROJECTS)

  • 作者: Massimo Banzi
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2015/11/28
  • メディア: 単行本(ソフトカバー)



アイデア実現のための Raspberry Piデザインパターン: 電子回路からMathematicaによるArduinoコラボまで

アイデア実現のための Raspberry Piデザインパターン: 電子回路からMathematicaによるArduinoコラボまで

  • 作者: 小林 博和
  • 出版社/メーカー: オーム社
  • 発売日: 2019/10/25
  • メディア: 単行本



電子部品ごとの制御を学べる! Arduino 電子工作 実践講座

電子部品ごとの制御を学べる! Arduino 電子工作 実践講座

  • 作者: 福田 和宏
  • 出版社/メーカー: ソーテック社
  • 発売日: 2018/09/21
  • メディア: 単行本




nice!(29)  コメント(2) 
共通テーマ:趣味・カルチャー

ESP32 の機能を再確認してみた! [Arduino]

ESP32 をなんとなく使いこなす自信もついてきたので、ESP32 の機能を再確認してみることにしました。ESP32 の Datasheet から主要機能をピックアップしてみました。

ESP32 Datasheet
ESP32_datasheet.png
http://espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf


Wi-Fi は、2.4GHz帯 のみですね。まぁ値段がこれですから当然か。でも n に対応しているのはポイント高いです。

1.2 Wi-Fi Key Features
 802.11 b/g/n/e/i
 802.11 n (2.4 GHz), up to 150 Mbps
 802.11 e: QoS for wireless multimedia technology
 WMM-PS, UAPSD
 A-MPDU and A-MSDU aggregation
 Block ACK
 Fragmentation and defragmentation
 Automatic Beacon monitoring/scanning
 802.11 i security features: pre-authentication and TSN
 Wi-Fi Protected Access (WPA)/WPA2/WPA2-Enterprise/Wi-Fi Protected Setup (WPS)
 Infrastructure BSS Station mode/SoftAP mode
 Wi-Fi Direct (P2P), P2P Discovery, P2P Group Owner mode and P2P Power Management
 UMA compliant and certified
 Antenna diversity and selection


Bluetooth は、v4.2 対応です。BLEならびにGATTもサポートしています。HeartRateブロファイルで確認清みですね。A2DP/HSP/HFP もサポートしているので、ヘッドセットみたいなのもできそうですね。

1.3 BT Key Features
 Compliant with Bluetooth v4.2 BR/EDR and BLE specification
 Class-1, class-2 and class-3 transmitter without external power amplifier
 Enhanced power control
 +12 dBm transmitting power
 NZIF receiver with -97 dBm sensitivity
 Adaptive Frequency Hopping (AFH)
 Standard HCI based on SDIO/SPI/UART
 High-speed UART HCI, up to 4 Mbps
 BT 4.2 controller and host stack
 Service Discover Protocol (SDP)
 General Access Profile (GAP)
 Security Manage Protocol (SMP)
 ATT/GATT
 HID
 All GATT-based profile supported
 SPP-like GATT-based profile
 BLE Beacon
 A2DP/AVRCP/SPP, HSP/HFP, RFCOMM
 CVSD and SBC for audio codec
 Bluetooth Piconet and Scatternet


CPUはデュアルコアですね。メモリは520kB+15kB。外付けの Quad SPI Flash がつくようです。駆動電圧は 3.3V。

1.4.1 CPU and Memory
 Xtensa[レジスタードトレードマーク] single-/dual-core 32-bit LX6 microprocessor(s), up to 600 DMIPS (200 DMIPS for single-core microprocessor)
 448 kB ROM
 520 kB SRAM
 16 kB SRAM in RTC
 QSPI flash/SRAM, up to 4 x 16 MB
 Power supply: 2.3V to 3.6V


タイマーは2系統のようです。RTCは当然ありますね。Wi-Fiと相性が良いので助かります。

1.4.2 Clocks and Timers
 Internal 8 MHz oscillator with calibration
 Internal RC oscillator with calibration
 External 2 MHz to 60 MHz crystal oscillator (40 MHz only for Wi-Fi/BT functionality)
 External 32 kHz crystal oscillator for RTC with calibration
 Two timer groups, including 2 x 64-bit timers and 1 x main watchdog in each group
 RTC timer with sub-second accuracy
 RTC watchdog


12-bit ADCが18チャンネルもあるってスゴイですね。ただサンプリングレートが明記されていません。遅いのかな。CANもサポートとしているので車関連のアプリも作れますね。プリアンプも載っているんですね。DACが2系統あるし、音を出すためかな。すごいなぁ。

1.4.3 Advanced Peripheral Interfaces
 12-bit SAR ADC up to 18 channels
 2 × 8-bit DAC
 10 × touch sensors
 Temperature sensor
 4 × SPI
 2 × I2S
 2 × I2C
 3 × UART
 1 host (SD/eMMC/SDIO)
 1 slave (SDIO/SPI)
 Ethernet MAC interface with dedicated DMA and IEEE 1588 support
 CAN 2.0
 IR (TX/RX)
 Motor PWM
 LED PWM up to 16 channels
 Hall sensor
 Ultra-low-noise analog pre-amplifier


セキュアブートをサポートしていて、ハードウェアの暗号化エンジンもあります。フラッシュ暗号化もサポートしているので、セキュリティはばっちりですね。

1.4.4 Security
 IEEE 802.11 standard security features are all supported, including WFA, WPA/WPA2 and WAPI
 Secure boot
 Flash encryption
 1024-bit OTP, up to 768-bit for customers
 Cryptographic hardware acceleration:
  > AES
  > HASH (SHA-2) library
  > RSA
  > ECC
  > Random Number Generator (RNG)

スマホのSoCに比べると、計算能力やワークメモリの容量はとても及びませんが、基本機能はほぼ匹敵するといってもいいくらいです。ESP32の全機能が使いこなせるようになったら面白そうです。
(^^)/~





waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

  • 出版社/メーカー: waves(ウェイブス)
  • メディア: エレクトロニクス



waves ESP32 ESPDuino-32 (ESP-WROOM-32) 技適取得品

waves ESP32 ESPDuino-32 (ESP-WROOM-32) 技適取得品

  • 出版社/メーカー: waves(ウェイブス)
  • メディア: おもちゃ&ホビー



MicroPython for ESP32 Development Workshop (English Edition)

MicroPython for ESP32 Development Workshop (English Edition)

  • 出版社/メーカー:
  • 発売日: 2017/08/19
  • メディア: Kindle版




タグ:ESP32
nice!(33)  コメント(0) 

ESP32 で高周波クロックをPWMで生成してみた! [Arduino]

ESP32 で 1MHz の高周波クロックが生成できるか試してました。波形はオシロスコープで確認しました。

DSC04871.JPG


最初に試してみたのは、サーボモーターをコントロールした方法。スケッチを以下に示します。

#include "esp_system.h"

void setup() {
  ledcSetup(0, 1000000, 8);  // 0ch, 1MHz, 8bit
  ledcAttachPin(15, 0); // 15pin 0ch
  ledcWrite(0, 128); // 0ch, duty 50% (128/256)
}

void loop() {
}



観測した波形がこちら。


ESP32_pwm_simple.png


1MHz にはほど遠いだいたい310kHz程度の上、波形をよくよく見るとパルス幅が不揃いで、安定した波形が得られていません。

で、いろいろと調べてみたら、ESP32 の PWM で高周波クロックを出力するには、HIGH_SPEED モードに設定する必要があるようです。スケッチを以下に示します。


#include "esp_system.h"
#include "driver/ledc.h"

void setup() {
   ledc_timer_bit_t bit_num = (ledc_timer_bit_t) 3; // duty range = 2^3 = 8

   // Enable LEDC PWM peripheral
   periph_module_enable(PERIPH_LEDC_MODULE);

   // Set Duty
   int duty = pow(2, (int) bit_num) / 2;  // (2^3) /2 = 4 : 50% 

   // setup the timer
   ledc_timer_config_t clk_timer;
   clk_timer.bit_num = bit_num; // 3
   clk_timer.freq_hz = 1000000; // 1MHz
   clk_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
   clk_timer.timer_num = LEDC_TIMER_0;
   ledc_timer_config(&clk_timer);

   // setup the pwm channel
   ledc_channel_config_t pwm_channel;
   pwm_channel.channel = LEDC_CHANNEL_0;
   pwm_channel.duty = duty;
   pwm_channel.gpio_num = GPIO_NUM_15;
   pwm_channel.intr_type = LEDC_INTR_DISABLE;
   pwm_channel.speed_mode = LEDC_HIGH_SPEED_MODE;
   pwm_channel.timer_sel = LEDC_TIMER_0;
   ledc_channel_config(&pwm_channel);

   // Set the PWM to the duty specified
   ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, duty);
   ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
}

void loop() {

}



波形を確認してみます。


ESP32_pwm_complex.png


比較的安定した波形が得られました。オシロスコープが MHz の信号を観測するには性能不足なので、少し誤差が出ていますが、ほぼ 1MHz のクロックが得られたようです。

ESP32はまだ出たばかりなので、使いこなすのはちょっと面倒ですね。
σ(^_^;





waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

  • 出版社/メーカー: waves(ウェイブス)
  • メディア: エレクトロニクス



waves ESP32 ESPDuino-32 (ESP-WROOM-32) 技適取得品

waves ESP32 ESPDuino-32 (ESP-WROOM-32) 技適取得品

  • 出版社/メーカー: waves(ウェイブス)
  • メディア: おもちゃ&ホビー



SparkFun ESP32 Thing Development Workshop (English Edition)

SparkFun ESP32 Thing Development Workshop (English Edition)

  • 出版社/メーカー: PE Press
  • 発売日: 2017/04/09
  • メディア: Kindle版




nice!(31)  コメント(2) 
共通テーマ:趣味・カルチャー

ESP32 の BLEデバイス化にチャレンジ!(4)ついに完結! [Arduino]

ずっと苦労していた ESP32 のBLEデバイス化ですが、ようやくうまく行きました!(涙)
。・゚・(ノД`)・゚・。


DSC04856.JPG


まずは成功した証。スマホアプリ LAPIS Semconductor さん謹製の BLE TOOL の画面を披露します。


ESP32_Heart_Rate.png



ばっちり心拍データを受信しています。実際に心拍を測定しているわけでなく、ランダムデータなんですけどね。^^; いろんな試行錯誤をした後、完成したスケッチがこちらです。

#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-fpermissive"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "bt.h"
#include "bta_api.h"

#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"

#define HRPS_HT_MEAS_MAX_LEN  13

///Attributes State Machine
enum {
    HRS_IDX_SVC,

    HRS_IDX_HR_MEAS_CHAR,
    HRS_IDX_HR_MEAS_VAL,
    HRS_IDX_HR_MEAS_NTF_CFG,
    
    HRS_IDX_NB,
};

#define ESP_HEART_RATE_APP_ID           0x55
#define SAMPLE_DEVICE_NAME              "ESP_HEART_RATE"
#define SAMPLE_MANUFACTURER_DATA_LEN    17
#define HEART_RATE_SVC_INST_ID          0

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,
};

static esp_ble_adv_data_t heart_rate_adv_config = {
    .set_scan_rsp = false,
    .include_name = true,
    .include_txpower = true,
    .min_interval = 0x20,
    .max_interval = 0x40,
    .appearance = 0x00,
    .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
    .p_manufacturer_data =  NULL, //&test_manufacturer[0],
    .service_data_len = 0,
    .p_service_data = NULL,
    .service_uuid_len = sizeof(heart_rate_service_uuid),
    .p_service_uuid = heart_rate_service_uuid,
    .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};

static esp_ble_adv_params_t heart_rate_adv_params; 

struct gatts_profile_inst {
    esp_gatts_cb_t gatts_cb;
    uint16_t gatts_if;
    uint16_t app_id;
    uint16_t conn_id;
    uint16_t service_handle;
    esp_gatt_srvc_id_t service_id;
    uint16_t char_handle;
    esp_bt_uuid_t char_uuid;
    esp_gatt_perm_t perm;
    esp_gatt_char_prop_t property;
    uint16_t descr_handle;
    esp_bt_uuid_t descr_uuid;
};


static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);

/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
static struct gatts_profile_inst heart_rate_profile = {
    .gatts_cb = gatts_profile_event_handler,
    .gatts_if = ESP_GATT_IF_NONE, 
};

/// Heart Rate Sensor Service
static const uint16_t heart_rate_svc = ESP_GATT_UUID_HEART_RATE_SVC;

#define CHAR_DECLARATION_SIZE   (sizeof(uint8_t))
static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ;
static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ;

/// Heart Rate Sensor Service - Heart Rate Measurement Characteristic, notify
static const uint16_t heart_rate_meas_uuid = ESP_GATT_HEART_RATE_MEAS;
static const uint8_t heart_measurement_ccc[2] ={ 0x00, 0x00};

/// Full HRS Database Description - Used to add attributes into the database
static const esp_gatts_attr_db_t heart_rate_gatt_db[HRS_IDX_NB] =
{
    // Heart Rate Service Declaration
    [HRS_IDX_SVC]                       =  
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
      sizeof(uint16_t), sizeof(heart_rate_svc), (uint8_t *)&heart_rate_svc}},

    // Heart Rate Measurement Characteristic Declaration
    [HRS_IDX_HR_MEAS_CHAR]            = 
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
      CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_notify}},
      
    // Heart Rate Measurement Characteristic Value
    [HRS_IDX_HR_MEAS_VAL]               =   
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&heart_rate_meas_uuid, ESP_GATT_PERM_READ,
      HRPS_HT_MEAS_MAX_LEN, 0, NULL}},

    // Heart Rate Measurement Characteristic - Client Characteristic Configuration Descriptor
    [HRS_IDX_HR_MEAS_NTF_CFG]       =    
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
      sizeof(uint16_t),sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
};


static uint16_t heart_rate_handle_table[HRS_IDX_NB];


//////////////////////////////////////////////////////
static void ble_indicate() {
    if (heart_rate_profile.gatts_if == ESP_GATT_IF_NONE) {
        Serial.println("cannot indicate: gatts_if_for_indicate is NONE");
        return;
    }
    uint8_t hrm_value = random(30, 220);
    uint8_t hrm_value_arr[] = {0x00, hrm_value};
    Serial.println(hrm_value);
    esp_ble_gatts_send_indicate(heart_rate_profile.gatts_if, 
        heart_rate_profile.conn_id, heart_rate_handle_table[HRS_IDX_HR_MEAS_VAL], 
        sizeof(hrm_value_arr), hrm_value_arr, false);
}
//////////////////////////////////////////////////////


static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event) {
    case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
        Serial.println("gap start advertising....");
        esp_ble_gap_start_advertising(&heart_rate_adv_params);
        break;
    case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
        //advertising start complete event to indicate advertising start successfully or failed
        if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
            Serial.println("gap advertising failed");
        }
        Serial.println("gap advertising success");
        break;
    default:
        break;
    }
}

static bool bConnected = false;

static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) 
{
    switch (event) {
    case ESP_GATTS_REG_EVT:
        Serial.println("gatt server register event");
        esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
        esp_ble_gap_config_adv_data(&heart_rate_adv_config);
        esp_ble_gatts_create_attr_tab(heart_rate_gatt_db, gatts_if, HRS_IDX_NB, HEART_RATE_SVC_INST_ID);
        break;
    case ESP_GATTS_READ_EVT: 
        Serial.println("gatt server read event");
        break;
    case ESP_GATTS_WRITE_EVT: 
        Serial.println("gatt server write event");       
        break;
    case ESP_GATTS_EXEC_WRITE_EVT:
        Serial.println("gatt server exec write event");       
        break;
    case ESP_GATTS_MTU_EVT:
        Serial.println("gatt server mtu event?");       
         break;
   case ESP_GATTS_CONF_EVT:
        Serial.println("gatt server configuration event");       
        heart_rate_profile.gatts_if = gatts_if;
        heart_rate_profile.conn_id = param->connect.conn_id;
        break;
   case ESP_GATTS_UNREG_EVT:
        Serial.println("gatt server unregister event");       
        break;
   case ESP_GATTS_DELETE_EVT:
        Serial.println("gatt server delete event");       
        break;
   case ESP_GATTS_START_EVT:
        Serial.println("gatt server start event");       
        break; 
   case ESP_GATTS_STOP_EVT:
        Serial.println("gatt server stop event");       
        break;
   case ESP_GATTS_CONNECT_EVT:
        Serial.println("gatt server connect event");       
        heart_rate_profile.gatts_if = gatts_if;
        heart_rate_profile.conn_id = param->connect.conn_id;
        bConnected = true;
        break;
   case ESP_GATTS_CREATE_EVT:
        Serial.println("gatt server create event");  
        break;
   case ESP_GATTS_ADD_CHAR_EVT:
        Serial.println("gatt server add char event");  
        break;
   case ESP_GATTS_ADD_CHAR_DESCR_EVT:
        Serial.println("gatt server add char descriptor event");  
        break;
   case ESP_GATTS_DISCONNECT_EVT:
        Serial.println("gatt server disconnect event");     
        esp_ble_gap_start_advertising(&heart_rate_adv_params);
        bConnected = false;
        break;
   case ESP_GATTS_OPEN_EVT:
        Serial.println("gatt server open event");     
        break;
   case ESP_GATTS_CANCEL_OPEN_EVT:
        Serial.println("gatt server cancel open event");     
        break;
   case ESP_GATTS_CLOSE_EVT:
        Serial.println("gatt server close event");     
        break;
   case ESP_GATTS_LISTEN_EVT:
        Serial.println("gatt server listen event");     
        break;
   case ESP_GATTS_CONGEST_EVT:
        Serial.println("gatt server congest event?");     
        break;
   case ESP_GATTS_CREAT_ATTR_TAB_EVT:
        {
            if (param->add_attr_tab.status != ESP_GATT_OK){
                Serial.println("create attribute table failed");
            } else if (param->add_attr_tab.num_handle != HRS_IDX_NB){
                Serial.println("create attribute table abnormally");
            } else {
                memcpy(heart_rate_handle_table, param->add_attr_tab.handles, sizeof(heart_rate_handle_table));
                esp_ble_gatts_start_service(heart_rate_handle_table[HRS_IDX_SVC]);
                Serial.println("gatt server create attribute tab successfully");     
            }
        }
        break;
   default:
        break;
   }
}

static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,  esp_ble_gatts_cb_param_t *param)
{
    /* If event is register event, store the gatts_if for each profile */
    if (event == ESP_GATTS_REG_EVT) {
        if (param->reg.status == ESP_GATT_OK) {
            Serial.println("gatt server register accepted");
            heart_rate_profile.gatts_if = gatts_if;
        } else {
            Serial.println("gatt server register app failed");
            return;
        }
    }
  
    do {
        int idx;
        if (gatts_if == ESP_GATT_IF_NONE || gatts_if == heart_rate_profile.gatts_if) {
            if (heart_rate_profile.gatts_cb) {
                heart_rate_profile.gatts_cb(event, gatts_if, param);
            }
        }
    } while (0);
}

void setup() {

    Serial.begin(115200);

    /* initialize advertising info */
    heart_rate_adv_params.adv_int_min = 0x20;
    heart_rate_adv_params.adv_int_max = 0x40;
    heart_rate_adv_params.adv_type = ADV_TYPE_IND;
    heart_rate_adv_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
    heart_rate_adv_params.channel_map = ADV_CHNL_ALL;
    heart_rate_adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY;

    btStart();

    esp_err_t ret;

    Serial.println("Init bluetooth");
    ret = esp_bluedroid_init();
    if (ret) {
        Serial.println("esp_bluedroid_init failed");
        return;
    }
    ret = esp_bluedroid_enable();
    if (ret) {
        Serial.println("esp_bluedroid_enable failed");
        return;
    }

    esp_ble_gatts_register_callback(gatts_event_handler);
    esp_ble_gap_register_callback(gap_event_handler);
    esp_ble_gatts_app_register(ESP_HEART_RATE_APP_ID);
}

void loop() {
  if (bConnected) {
      ble_indicate();
  } 
  delay(1000);
}



ポイントは二つ。ひとつは esp_ble_gatts_send_indicate の handle を CREATE_ATTR_TAB で取得したものを使ったのと、もう一つは、心拍データを16bit で送る必要があったことの2点です。この心拍データが 16bit 必要というのが気が付かずに、かなり時間をかけてしまいました。

全般的に、ESP32 SDK の BLE は mbed の Nordic のものよりも分かり難いですねぇ。でも、使い方のコツは分かったので、これから ESP32 を BLEデバイスとして活用できそうです!
(^_^)/~





waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

  • 出版社/メーカー: waves(ウェイブス)
  • メディア: エレクトロニクス



waves ESP32 ESPDuino-32 (ESP-WROOM-32) 技適取得品

waves ESP32 ESPDuino-32 (ESP-WROOM-32) 技適取得品

  • 出版社/メーカー: waves(ウェイブス)
  • メディア: おもちゃ&ホビー



MicroPython for ESP32 Development Workshop (English Edition)

MicroPython for ESP32 Development Workshop (English Edition)

  • 出版社/メーカー:
  • 発売日: 2017/08/19
  • メディア: Kindle版



タグ:Arduino BLE ESP32
nice!(32)  コメント(3) 
共通テーマ:趣味・カルチャー

ESP32 の BLEデバイス化にチャレンジ!(3) [Arduino]

今日は久しぶりに時間ができたので、じっくりと ESP32 の BLE について調べることができました。


DSC04860.JPG


なんとなく構造が分かってきたので、少しスケッチを整理してみました。見通しをよくするために "Body Sensor Location" や "Heart Rate Control Point" など、余計な "Characteristics" は省いてしまいました。

#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-fpermissive"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "bt.h"
#include "bta_api.h"

#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_main.h"

#define HRPS_HT_MEAS_MAX_LEN            13

///Attributes State Machine
enum {
    HRS_IDX_SVC,

    HRS_IDX_HR_MEAS_CHAR,
    HRS_IDX_HR_MEAS_VAL,
    HRS_IDX_HR_MEAS_NTF_CFG,

    HRS_IDX_NB,
};

#define ESP_HEART_RATE_APP_ID           0x55
#define SAMPLE_DEVICE_NAME              "ESP_HEART_RATE"
#define SAMPLE_MANUFACTURER_DATA_LEN    17
#define HEART_RATE_SVC_INST_ID          0

uint16_t heart_rate_handle_table[HRS_IDX_NB];

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,
};

static esp_ble_adv_data_t heart_rate_adv_config = {
    .set_scan_rsp = false,
    .include_name = true,
    .include_txpower = true,
    .min_interval = 0x20,
    .max_interval = 0x40,
    .appearance = 0x00,
    .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
    .p_manufacturer_data =  NULL, //&test_manufacturer[0],
    .service_data_len = 0,
    .p_service_data = NULL,
    .service_uuid_len = sizeof(heart_rate_service_uuid),
    .p_service_uuid = heart_rate_service_uuid,
    .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};

static esp_ble_adv_params_t heart_rate_adv_params; 

struct gatts_profile_inst {
    esp_gatts_cb_t gatts_cb;
    uint16_t gatts_if;
    uint16_t app_id;
    uint16_t conn_id;
    uint16_t service_handle;
    esp_gatt_srvc_id_t service_id;
    uint16_t char_handle;
    esp_bt_uuid_t char_uuid;
    esp_gatt_perm_t perm;
    esp_gatt_char_prop_t property;
    uint16_t descr_handle;
    esp_bt_uuid_t descr_uuid;
};

static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);

/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
static struct gatts_profile_inst heart_rate_profile = {
    .gatts_cb = gatts_profile_event_handler,
    .gatts_if = ESP_GATT_IF_NONE, 
};

/// Heart Rate Sensor Service
static const uint16_t heart_rate_svc = ESP_GATT_UUID_HEART_RATE_SVC;

#define CHAR_DECLARATION_SIZE   (sizeof(uint8_t))
static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ;
static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ;

/// Heart Rate Sensor Service - Heart Rate Measurement Characteristic, notify
static const uint16_t heart_rate_meas_uuid = ESP_GATT_HEART_RATE_MEAS;
static const uint8_t heart_measurement_ccc[2] ={ 0x00, 0x00};

static uint8_t hrm_value = 0x00;

/// Full HRS Database Description - Used to add attributes into the database
static const esp_gatts_attr_db_t heart_rate_gatt_db[HRS_IDX_NB] =
{
    // Heart Rate Service Declaration
    [HRS_IDX_SVC]                       =  
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
      sizeof(uint16_t), sizeof(heart_rate_svc), (uint8_t *)&heart_rate_svc}},

    // Heart Rate Measurement Characteristic Declaration
    [HRS_IDX_HR_MEAS_CHAR]            = 
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
      CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_notify}},
      
    // Heart Rate Measurement Characteristic Value
    [HRS_IDX_HR_MEAS_VAL]               =   
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&heart_rate_meas_uuid, ESP_GATT_PERM_READ,
      HRPS_HT_MEAS_MAX_LEN, sizeof(hrm_value), (uint8_t *)&hrm_value}},

    // Heart Rate Measurement Characteristic - Client Characteristic Configuration Descriptor
    [HRS_IDX_HR_MEAS_NTF_CFG]       =    
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
      sizeof(uint16_t),sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
};

//////////////////////////////////////////////////////
static void ble_indicate() {
    if (heart_rate_profile.gatts_if == ESP_GATT_IF_NONE) {
        Serial.println("cannot indicate: gatts_if_for_indicate is NONE");
        return;
    }
    hrm_value = random(100);
    Serial.println(hrm_value);

    esp_ble_gatts_send_indicate(heart_rate_profile.gatts_if, heart_rate_profile.conn_id, heart_rate_profile.char_handle, 
        sizeof(hrm_value), (uint8_t *)&hrm_value, true);

}
//////////////////////////////////////////////////////


static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event) {
    case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
        Serial.println("gap start advertising....");
        esp_ble_gap_start_advertising(&heart_rate_adv_params);
        break;
    case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
        //advertising start complete event to indicate advertising start successfully or failed
        if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
            Serial.println("gap advertising failed");
        }
        Serial.println("gap advertising success");
        break;
    default:
        break;
    }
}

static bool bConnected = false;

static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) 
{

    switch (event) {
    case ESP_GATTS_REG_EVT:
        Serial.println("gatt server register event");
        esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
        esp_ble_gap_config_adv_data(&heart_rate_adv_config);
        esp_ble_gatts_create_attr_tab(heart_rate_gatt_db, gatts_if, HRS_IDX_NB, HEART_RATE_SVC_INST_ID);
        break;
    case ESP_GATTS_READ_EVT: 
        Serial.println("gatt server read event");
        break;
    case ESP_GATTS_WRITE_EVT: 
        Serial.println("gatt server write event");       
        break;
    case ESP_GATTS_EXEC_WRITE_EVT:
        Serial.println("gatt server exec write event");       
        break;
    case ESP_GATTS_MTU_EVT:
        Serial.println("gatt server mtu event?");       
         break;
   case ESP_GATTS_CONF_EVT:
        Serial.println("gatt server configuration event");       
        break;
   case ESP_GATTS_UNREG_EVT:
        Serial.println("gatt server unregister event");       
        break;
   case ESP_GATTS_DELETE_EVT:
        Serial.println("gatt server delete event");       
        break;
   case ESP_GATTS_START_EVT:
        Serial.println("gatt server start event");       
        break; 
   case ESP_GATTS_STOP_EVT:
        Serial.println("gatt server stop event");       
        break;
   case ESP_GATTS_CONNECT_EVT:
        heart_rate_profile.gatts_if = gatts_if;
        heart_rate_profile.conn_id = param->connect.conn_id;
        heart_rate_profile.char_handle = param->add_char.attr_handle;
        bConnected = true;
        break;
   case ESP_GATTS_DISCONNECT_EVT:
        Serial.println("gatt server disconnect event");     
        heart_rate_profile.gatts_if = ESP_GATT_IF_NONE;
        bConnected = false;
        break;
   case ESP_GATTS_OPEN_EVT:
        Serial.println("gatt server open event");     
        break;
   case ESP_GATTS_CANCEL_OPEN_EVT:
        Serial.println("gatt server cancel open event");     
        break;
   case ESP_GATTS_CLOSE_EVT:
        Serial.println("gatt server close event");     
        break;
   case ESP_GATTS_LISTEN_EVT:
        Serial.println("gatt server listen event");     
        break;
   case ESP_GATTS_CONGEST_EVT:
        Serial.println("gatt server congest event?");     
        break;
   case ESP_GATTS_CREAT_ATTR_TAB_EVT:
        {
            if (param->add_attr_tab.status != ESP_GATT_OK){
                Serial.println("create attribute table failed");
            } else if (param->add_attr_tab.num_handle != HRS_IDX_NB){
                Serial.println("create attribute table abnormally");
            } else {
                Serial.println("gatt server create attribute tab successfully");     
                memcpy(heart_rate_handle_table, param->add_attr_tab.handles, sizeof(heart_rate_handle_table));
                esp_ble_gatts_start_service(heart_rate_handle_table[HRS_IDX_SVC]);
            }
        }
        break;
   default:
        break;
   }
}

static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,  esp_ble_gatts_cb_param_t *param)
{
    /* If event is register event, store the gatts_if for each profile */
    if (event == ESP_GATTS_REG_EVT) {
        if (param->reg.status == ESP_GATT_OK) {
            Serial.println("gatt server register accepted");
            heart_rate_profile.gatts_if = gatts_if;
        } else {
            Serial.println("gatt server register app failed");
            return;
        }
    }
  
    do {
        int idx;
        if (gatts_if == ESP_GATT_IF_NONE || gatts_if == heart_rate_profile.gatts_if) {
            if (heart_rate_profile.gatts_cb) {
                heart_rate_profile.gatts_cb(event, gatts_if, param);
            }
        }
    } while (0);
}

void setup() {

    Serial.begin(115200);

    /* initialize advertising info */
    heart_rate_adv_params.adv_int_min = 0x20;
    heart_rate_adv_params.adv_int_max = 0x40;
    heart_rate_adv_params.adv_type = ADV_TYPE_IND;
    heart_rate_adv_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
    heart_rate_adv_params.channel_map = ADV_CHNL_ALL;
    heart_rate_adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY;
   
    esp_err_t ret;

    btStart();

    Serial.println("Init bluetooth");
    ret = esp_bluedroid_init();
    if (ret) {
        Serial.println("esp_bluedroid_init failed");
        return;
    }
    ret = esp_bluedroid_enable();
    if (ret) {
        Serial.println("esp_bluedroid_enable failed");
        return;
    }

    esp_ble_gatts_register_callback(gatts_event_handler);
    esp_ble_gap_register_callback(gap_event_handler);
    esp_ble_gatts_app_register(ESP_HEART_RATE_APP_ID);
}

void loop() {
  if (bConnected) {
      ble_indicate();
  } 
  delay(1000);
}



LAPIS Semicondocutor の BLE TOOL で Android スマホから接続してみたら、HRM として認識させることに成功しました!やった。


Screenshot_2017-11-19-00-14-12.png


でも、値を受け取ることはできませんでした。NOTIFY をうまく伝えることができていないようです。あと一息なんだけどなぁ。 orz...


Screenshot_2017-11-19-00-14-48.png


こちらがログになります。

Init bluetooth
gatt server register accepted
gatt server register event
gatt server create attribute tab successfully
gap start advertising....
gatt server start event
gap advertising success
90
85
71
gatt server write event
69
10
97
32
91
62
19
gatt server write event
78
47
83
gatt server disconnect event


どうも Attribute の handle 値が正しく設定されていないようなのですが、どう値を持ってくればよいのかよく分かりません。ESP32 の BLE 関連の情報がほとんどなくしばらく苦戦しそうです。うーむ。
(。-`ω´-)





waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

  • 出版社/メーカー: waves(ウェイブス)
  • メディア: エレクトロニクス



waves ESP32 ESP-WROOM-32 WiFi/Bluetoothモジュール(技適取得済み) ブレイクアウトボード付属

waves ESP32 ESP-WROOM-32 WiFi/Bluetoothモジュール(技適取得済み) ブレイクアウトボード付属

  • 出版社/メーカー: waves(ウェイブス)
  • メディア: おもちゃ&ホビー



SparkFun ESP32 Thing Development Workshop (English Edition)

SparkFun ESP32 Thing Development Workshop (English Edition)

  • 出版社/メーカー: PE Press
  • 発売日: 2017/04/09
  • メディア: Kindle版




タグ:ESP32 BLE Arduino
nice!(25)  コメント(2) 
共通テーマ:趣味・カルチャー

ESP32 の BLEデバイス化にチャレンジ!(2) [Arduino]

ESP32をGATTデバイス化しようにも、すっかりBLEの仕様も忘れてしまっているし、ESP32のESP-IDFと言われるSDKもよく分からないし、しかも調べる時間ないし…


DSC04860.JPG


なにかよい資料がないかなとあら探しをしていたら、ESP32 による Heart Rate Profile のサンプルを見つけました!


esp-idf/examples/bluetooth/gatt_server_service_table/main/gatts_table_creat_demo.c


Heart Rate Profile なら mbed HRM1017 を使った開発経験があります。


mbed HRM1017 で Heart Rate Profile をサポートしてみる
http://makers-with-myson.blog.so-net.ne.jp/archive/c2306056631-1


これをヒントに、ESP32のBLEの使い方を習熟していきたいと思います。とりあえずダメもとで ESP-IDF のコードを Arduino のスケッチに移植してしみました。


#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-fpermissive"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "bt.h"
#include "bta_api.h"

#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_main.h"

#define HRPS_HT_MEAS_MAX_LEN            (13)

#define HRPS_MANDATORY_MASK             (0x0F)
#define HRPS_BODY_SENSOR_LOC_MASK       (0x30)
#define HRPS_HR_CTNL_PT_MASK            (0xC0)


///Attributes State Machine
enum {
    HRS_IDX_SVC,

    HRS_IDX_HR_MEAS_CHAR,
    HRS_IDX_HR_MEAS_VAL,
    HRS_IDX_HR_MEAS_NTF_CFG,

    HRS_IDX_BOBY_SENSOR_LOC_CHAR,
    HRS_IDX_BOBY_SENSOR_LOC_VAL,

    HRS_IDX_HR_CTNL_PT_CHAR,
    HRS_IDX_HR_CTNL_PT_VAL,

    HRS_IDX_NB,
};


#define GATTS_TABLE_TAG "GATTS_TABLE_DEMO"

#define HEART_PROFILE_NUM  1
#define HEART_PROFILE_APP_IDX   0
#define ESP_HEART_RATE_APP_ID  0x55
#define SAMPLE_DEVICE_NAME     "ESP_HEART_RATE"
#define SAMPLE_MANUFACTURER_DATA_LEN  17
#define HEART_RATE_SVC_INST_ID   0

#define GATTS_DEMO_CHAR_VAL_LEN_MAX   0x40

uint8_t char1_str[] ={0x11,0x22,0x33};

uint16_t heart_rate_handle_table[HRS_IDX_NB];

esp_attr_value_t gatts_demo_char1_val = 
{
  .attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX,
  .attr_len   = sizeof(char1_str),
  .attr_value     = char1_str,
};


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,
};


static esp_ble_adv_data_t heart_rate_adv_config = {
    .set_scan_rsp = false,
    .include_name = true,
    .include_txpower = true,
    .min_interval = 0x20,
    .max_interval = 0x40,
    .appearance = 0x00,
    .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
    .p_manufacturer_data =  NULL, //&test_manufacturer[0],
    .service_data_len = 0,
    .p_service_data = NULL,
    .service_uuid_len = sizeof(heart_rate_service_uuid),
    .p_service_uuid = heart_rate_service_uuid,
    .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};

static esp_ble_adv_params_t heart_rate_adv_params; 

struct gatts_profile_inst {
    esp_gatts_cb_t gatts_cb;
    uint16_t gatts_if;
    uint16_t app_id;
    uint16_t conn_id;
    uint16_t service_handle;
    esp_gatt_srvc_id_t service_id;
    uint16_t char_handle;
    esp_bt_uuid_t char_uuid;
    esp_gatt_perm_t perm;
    esp_gatt_char_prop_t property;
    uint16_t descr_handle;
    esp_bt_uuid_t descr_uuid;
};

static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);

/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
static struct gatts_profile_inst heart_rate_profile_tab[HEART_PROFILE_NUM] = {
    [HEART_PROFILE_APP_IDX] = {
        .gatts_cb = gatts_profile_event_handler,
        .gatts_if = ESP_GATT_IF_NONE,       /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
    },
    
};

/*
 * HTPT PROFILE ATTRIBUTES
 ****************************************************************************************
 */


/*
 *  Heart Rate PROFILE ATTRIBUTES
 ****************************************************************************************
 */

/// Heart Rate Sensor Service
static const uint16_t heart_rate_svc = ESP_GATT_UUID_HEART_RATE_SVC;

#define CHAR_DECLARATION_SIZE   (sizeof(uint8_t))
static const uint16_t primary_service_uuid = ESP_GATT_UUID_PRI_SERVICE;
static const uint16_t character_declaration_uuid = ESP_GATT_UUID_CHAR_DECLARE;
static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
static const uint8_t char_prop_notify = ESP_GATT_CHAR_PROP_BIT_NOTIFY;
static const uint8_t char_prop_read = ESP_GATT_CHAR_PROP_BIT_READ;
static const uint8_t char_prop_read_write = ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_READ;

/// Heart Rate Sensor Service - Heart Rate Measurement Characteristic, notify
static const uint16_t heart_rate_meas_uuid = ESP_GATT_HEART_RATE_MEAS;
static const uint8_t heart_measurement_ccc[2] ={ 0x00, 0x00};


/// Heart Rate Sensor Service -Body Sensor Location characteristic, read
static const uint16_t body_sensor_location_uuid = ESP_GATT_BODY_SENSOR_LOCATION;
static const uint8_t body_sensor_loc_val[1] = {0x00};


/// Heart Rate Sensor Service - Heart Rate Control Point characteristic, write&read
static const uint16_t heart_rate_ctrl_point = ESP_GATT_HEART_RATE_CNTL_POINT;
static const uint8_t heart_ctrl_point[1] = {0x00};

/// Full HRS Database Description - Used to add attributes into the database
static const esp_gatts_attr_db_t heart_rate_gatt_db[HRS_IDX_NB] =
{
    // Heart Rate Service Declaration
    [HRS_IDX_SVC]                       =  
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
      sizeof(uint16_t), sizeof(heart_rate_svc), (uint8_t *)&heart_rate_svc}},

    // Heart Rate Measurement Characteristic Declaration
    [HRS_IDX_HR_MEAS_CHAR]            = 
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
      CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_notify}},
      
    // Heart Rate Measurement Characteristic Value
    [HRS_IDX_HR_MEAS_VAL]               =   
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&heart_rate_meas_uuid, ESP_GATT_PERM_READ,
      HRPS_HT_MEAS_MAX_LEN,0, NULL}},

    // Heart Rate Measurement Characteristic - Client Characteristic Configuration Descriptor
    [HRS_IDX_HR_MEAS_NTF_CFG]       =    
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,
      sizeof(uint16_t),sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},

    // Body Sensor Location Characteristic Declaration
    [HRS_IDX_BOBY_SENSOR_LOC_CHAR]  = 
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
      CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read}},

    // Body Sensor Location Characteristic Value
    [HRS_IDX_BOBY_SENSOR_LOC_VAL]   = 
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&body_sensor_location_uuid, ESP_GATT_PERM_READ,
      sizeof(uint8_t), sizeof(body_sensor_loc_val), (uint8_t *)body_sensor_loc_val}},

    // Heart Rate Control Point Characteristic Declaration
    [HRS_IDX_HR_CTNL_PT_CHAR]          = 
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
      CHAR_DECLARATION_SIZE,CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write}},
                                              
    // Heart Rate Control Point Characteristic Value
    [HRS_IDX_HR_CTNL_PT_VAL]             = 
    {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&heart_rate_ctrl_point, ESP_GATT_PERM_WRITE|ESP_GATT_PERM_READ,
      sizeof(uint8_t), sizeof(heart_ctrl_point), (uint8_t *)heart_ctrl_point}},  
};



static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    Serial.println("gap_event_handler");

    switch (event) {
    case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
        Serial.println(" ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT");
        esp_ble_gap_start_advertising(&heart_rate_adv_params);
        break;
    case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
        //advertising start complete event to indicate advertising start successfully or failed
        Serial.println(" ESP_GAP_BLE_ADV_START_COMPLETE_EVT");
        if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
            Serial.println("Advertising start failed");
        }
        break;
    default:
        break;
    }
}

static void gatts_profile_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) 
{
    Serial.println("gatts_profile_event_handler:");
    switch (event) {
    case ESP_GATTS_REG_EVT:
        Serial.println(" ESP_GATTS_REG_EVT");
        esp_ble_gap_set_device_name(SAMPLE_DEVICE_NAME);
        esp_ble_gap_config_adv_data(&heart_rate_adv_config);
        esp_ble_gatts_create_attr_tab(heart_rate_gatt_db, gatts_if, HRS_IDX_NB, HEART_RATE_SVC_INST_ID);
        break;
    case ESP_GATTS_READ_EVT: 
        Serial.println(" ESP_GATTS_READ_EVT");
        char hrp1 = 0x1E; // dummy data
        char hrp2 = 0x00; // dummy data
        esp_gatt_rsp_t rsp;
        memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
        rsp.attr_value.handle = param->read.handle;
        rsp.attr_value.len = 2;
        rsp.attr_value.value[0] = hrp1;
        rsp.attr_value.value[1] = hrp2;
        esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp);
        break;
    case ESP_GATTS_WRITE_EVT: 
        Serial.println(" ESP_GATTS_WRITE_EVT");       
        break;
    case ESP_GATTS_EXEC_WRITE_EVT:
        Serial.println(" ESP_GATTS_EXEC_WRITE_EVT");       
        break;
    case ESP_GATTS_MTU_EVT:
        Serial.println(" ESP_GATTS_MTU_EVT");       
         break;
   case ESP_GATTS_CONF_EVT:
        Serial.println(" ESP_GATTS_CONF_EVT");       
        break;
   case ESP_GATTS_UNREG_EVT:
        Serial.println(" ESP_GATTS_UREG_EVT");       
        break;
   case ESP_GATTS_DELETE_EVT:
        Serial.println(" ESP_GATTS_DELETE_EVT");       
        break;
   case ESP_GATTS_START_EVT:
        Serial.println(" ESP_GATTS_START_EVT");       
        break; 
   case ESP_GATTS_STOP_EVT:
        Serial.println(" ESP_GATTS_STOP_EVT");       
        break;
   case ESP_GATTS_CONNECT_EVT:
        Serial.println(" ESP_GATTS_CONNECT_EVT");       
        break;
   case ESP_GATTS_DISCONNECT_EVT:
        Serial.println(" ESP_GATTS_DISCONNECT_EVT");       
        break;
   case ESP_GATTS_OPEN_EVT:
        Serial.println(" ESP_GATTS_OPEN_EVT");       
        break;
   case ESP_GATTS_CANCEL_OPEN_EVT:
        Serial.println(" ESP_GATTS_CANCEL_OPEN_EVT");       
        break;
   case ESP_GATTS_CLOSE_EVT:
        Serial.println(" ESP_GATTS_CLOSE_EVT");       
        break;
   case ESP_GATTS_LISTEN_EVT:
        Serial.println(" ESP_GATTS_LISTEN_EVT");       
        break;
   case ESP_GATTS_CONGEST_EVT:
        Serial.println(" ESP_GATTS_CONGEST_EVT");       
        break;
   case ESP_GATTS_CREAT_ATTR_TAB_EVT:{
            Serial.println("ESP_GATTS_CREAT_ATTR_TAB_EVT");
            if (param->add_attr_tab.status != ESP_GATT_OK){
                Serial.println("Create attribute table failed");
            } else if (param->add_attr_tab.num_handle != HRS_IDX_NB){
                Serial.println("Create attribute table abnormally");
            } else {
                memcpy(heart_rate_handle_table, param->add_attr_tab.handles, sizeof(heart_rate_handle_table));
                esp_ble_gatts_start_service(heart_rate_handle_table[HRS_IDX_SVC]);
            }
        }
        break;
   default:
        break;
   }
}


static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if,  esp_ble_gatts_cb_param_t *param)
{
    Serial.println("gatts_event_handler:");

    /* If event is register event, store the gatts_if for each profile */
    if (event == ESP_GATTS_REG_EVT) {
        if (param->reg.status == ESP_GATT_OK) {
            Serial.println("  Reg app success");
            heart_rate_profile_tab[HEART_PROFILE_APP_IDX].gatts_if = gatts_if;
        } else {
            Serial.println("  Reg app failed");
            return;
        }
    }
  
    do {
        int idx;
        for (idx = 0; idx < HEART_PROFILE_NUM; idx++) {
            if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
                    gatts_if == heart_rate_profile_tab[idx].gatts_if) {
                if (heart_rate_profile_tab[idx].gatts_cb) {
                    heart_rate_profile_tab[idx].gatts_cb(event, gatts_if, param);
                }
            }
        }
    } while (0);
}



void setup() {

    Serial.begin(115200);
    /* initialize advertising info */
    heart_rate_adv_params.adv_int_min = 0x20;
    heart_rate_adv_params.adv_int_max = 0x40;
    heart_rate_adv_params.adv_type = ADV_TYPE_IND;
    heart_rate_adv_params.own_addr_type = BLE_ADDR_TYPE_PUBLIC;
    heart_rate_adv_params.channel_map = ADV_CHNL_ALL;
    heart_rate_adv_params.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY;
    
    esp_err_t ret;
    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    ret = esp_bt_controller_init(&bt_cfg);
    if (ret) {
        Serial.println("esp_bt_controller_init failed");
        return;
    }

    ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM);
    if (ret) {
        Serial.println("esp_bt_controller_enable enable controller");
        return;
    }

    Serial.println("Init bluetooth");
    ret = esp_bluedroid_init();
    if (ret) {
        Serial.println("esp_bluedroid_init failed");
        return;
    }
    ret = esp_bluedroid_enable();
    if (ret) {
        Serial.println("esp_bluedroid_enable failed");
        return;
    }

    esp_ble_gatts_register_callback(gatts_event_handler);
    esp_ble_gap_register_callback(gap_event_handler);
    esp_ble_gatts_app_register(ESP_HEART_RATE_APP_ID);
}

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

}



何も考えずに移植したコードなので、うまく動かないだろうなぁと思いつつ試してみました。

Init bluetooth
gatts_event_handler:
  Reg app success
gatts_profile_event_handler:
 ESP_GATTS_REG_EVT
gatts_event_handler:
gatts_profile_event_handler:
gap_event_handler
 ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT
gap_event_handler
 ESP_GAP_BLE_ADV_START_COMPLETE_EVT
gatts_event_handler:
gatts_profile_event_handler:
gap_event_handler



とりあえずログは出ましたがそれらしい動きは一切なし。やっぱダメですね。ぼちぼち調べていくかぁ。
(´・ω・`)





waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

waves ESP32-DevKitC ESP-WROOM-32 ESP32 DevKitC V2 WiFi BLE 技適取得済 国内発送

  • 出版社/メーカー: waves(ウェイブス)
  • メディア: エレクトロニクス



SparkFun ESP32 Thing Development Workshop (English Edition)

SparkFun ESP32 Thing Development Workshop (English Edition)

  • 出版社/メーカー: PE Press
  • 発売日: 2017/04/09
  • メディア: Kindle版



MicroPython for ESP32 Development Workshop (English Edition)

MicroPython for ESP32 Development Workshop (English Edition)

  • 出版社/メーカー:
  • 発売日: 2017/08/19
  • メディア: Kindle版




タグ:ESP32 Arduino BLE GATT
nice!(26)  コメント(2) 
共通テーマ:趣味・カルチャー

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。