ESP-WROOM-32

ESP-WROOM-32 に関する記事です。



ESP-WROOM-32

Espressif Systems 社の ESP-WROOM-32 は Arduino ではないのですが、Arduino IDE で Arduino ライクな使い方ができます。

ESP-WROOM-32 の SoC が ESP32 で、ESP32 の MCU (CPU) が "32bit で 240MHz デュアルコア" の Tensilica LX6 です。520KB の SRAM と 4MB のフラッシュメモリを持っています。実際に書き込めるスケッチの最大サイズはファームウェアに依存しますが、最低でも Arduino UNO (ATmega328P) の 10 倍以上のメモリが使えます。

See Also:



購入

ESP-WROOM-32 単体

どこでも購入できます。

ESP-WROOM-32 だけでは何もできません。最低でも 3.3V 電源USB<->シリアル変換モジュールが別途必要となります。

ESP-WROOM-32 ブレークアウトボード

ESP-WROOM-32 はそのままでは使いにくい (ピン間隔 1.27mm) ので、ブレッドボードに挿せるようなブレークアウトボードも各社から出ています。

別途ピンヘッダが必要かもしれません。

ESP-WROOM-32 開発ボード

USB シリアル変換等が含まれる開発ボードです。買ったその日から ESP-WROOM-32 を試すことができます。

開発ボードも種類が増えてきましたが、最初の一つなら ESP32-DevKitC をオススメします。



ESP-WROOM-32 の概要

ピンアウト

ピンアウトは以下のようになっています。

最低限、EN を 10kΩ でプルアップして電源 (3.3V) を繋げば動作します。

See Also:

起動モード

起動モードを決定するピンは 5 つあります。

オレンジの設定がデフォルトになります。



ブレイクアウトボード各部詳細

頂き物のブレークアウトボードです。ブレッドボードで使えるように、一部ピンソケットにしてあります。

表面の GND と 3V3 の間に 0.1μF のチップコンデンサを、3V3 と EN の間に 10kΩのチップ抵抗を取り付けました (0805 / 2012 でギチギチです。後で取り付けるなら 0603 / 1608 がいいと思います)。

別バージョンです。こちらはピンソケットを立ててみました。Arduino Uno みたいな使い方ができます。

真ん中の穴はハンダしておくと安定性と放熱性が上がるらしいのですが、ハンダごてのワット数が小さいとハンダできないので注意が必要です。この穴と ESP-WROOM-32 が熱を吸ってしまい、うまくハンダできません...放熱性能は確かだと言えるでしょう。

三択です (w

生の ESP-WROOM-32 を使うには以下の図 (ESP-WROOM-32 Datasheet: 3.5.2 Peripheral Schematics) が参考になると思います。

ESP-WROOM-32 は ESP-WROOM-02 よりも必要な外部パーツが少ないので、開発ボードではなく、ブレークアウトボードだけでもいいかもしれませんね。

See Also:



ESP32-DevKitC 各部詳細

開発ボード (ESP32 Core Board / DevKitC) です。裏面にあるように Ver2 のボードです。

普通のピンヘッダで 19ピンx2列のものをブレッドボードに挿したら、モノによってはちゃんと刺さらないか、抜く時に大変だと思います。ピンヘッダはハンダされていない方がよかったなぁ...。

このボード、Windows だと自動プログラムできない / 自動プログラムが不安定って報告があったのですが、ごく普通に自動プログラムできていますね。なお、自動プログラムに問題がある場合の対処法はコンデンサ容量の増量です (0.22μF~2.2μF)。

対処方法は上に行くほど難易度が高いです。まずはブレッドボードで試してみる事をオススメします。

See Also:

ピンアウト

ピンアウトは以下のようになっています。

類似品 (DOIT V1)

紛らわしい見た目をしていますが、ESP-WROOM-32 モジュールが飛び出していないのが V1 (DOIT 社製) で、飛び出ているのが V2 (espressif 社製) です。四隅に穴が開いてるのが V1 (DOIT 社製)です。

ESP32.net さん情報によると、青い espressif 社製 V1 もあるとの事です。V1 のボードは自動プログラムで問題が発生することがあります。DOIT V1 は EN<->GND 間にコンデンサが取り付けられていません。

See Also:

ブレッドボード

ESP32-DevKitC はピン数が多く、安物中華ブレッドボードを使うと挿すのも困難、外すのも困難です。しかも、片側一列しかピンが空かないので、ジャンパーワイヤーでの配線も面倒です。普通のブレッドボードを二つ上下に連結するのが最も簡単な解決方法ですが、安物中華ブレッドボードの場合、連結するとピッチがズレてしまって挿しにくい事があります。

なんだかんだで ESP-WROOM-02 / ESP-WROOM-32 開発ボード用のブレッドボードにはサンハヤトの SAD-101 や E-Call の EIC-3901 が最適だと思います。

普通のブレッドボードは A-E・F-J の 5 穴ですが、これは A-F・G-L の 6 穴なので片側一列、もう片側は二列空きます。加えて縦にも横にも連結できます。

See Also:



スイッチサイエンス ESPr Developer 32 各部詳細

スイッチサイエンスの ESPr Developer 32 です。

ピンヘッダは付属しないので秋月の細ピンヘッダ辺りを取り付けましょう。あと、USB 端子のランドにはハンダではなくフラックスが詰まってる気がしたので、強度を稼ぐためにハンダを盛っておきました。

この製品の特長は、

IO6~IO11 と一番下の左右 GND を削ればもう少し短くできたんではなかろうかと思いますが、総じていい開発ボードだと思います。

See Also:

ピンアウト

ピンアウトは以下のようになっています。

裏面の空きパッド

裏面の空きパッドにはパーツを追加できます。

現状、ESP-WROOM-32 のデータシートには "The ESP32 Wi-Fi/BT firmware can only support 40 MHz crystal oscillator for now." とあるので、クリスタルは取り付けない方がいいかもです。これが RTC 用途だとするなら、外部モジュールを追加した方がよさそうです。

See Also:

ボードの追加

Arduino IDE にこのボードの定義を追加してみます。環境構築がまだの方は先にセットアップのトピックを読んでください。

  1. ESP32 の boards.txt をテキストエディタで開く。
    このサイトのセットアップの通りにやった方は Arduino インストールフォルダ\hardware\espressif\esp32 にあるはずです。
  2. 以下を追記する。
    ##############################################################
    espr-developer-32.name=SWITCH SCIENCE ESPr Developer 32
    
    espr-developer-32.upload.tool=esptool
    espr-developer-32.upload.maximum_size=1310720
    espr-developer-32.upload.maximum_data_size=294912
    espr-developer-32.upload.wait_for_upload_port=true
    
    espr-developer-32.serial.disableDTR=true
    espr-developer-32.serial.disableRTS=true
    
    espr-developer-32.build.mcu=esp32
    espr-developer-32.build.core=esp32
    espr-developer-32.build.variant=esp32
    espr-developer-32.build.board=ESP32_DEV
    
    espr-developer-32.build.f_cpu=240000000L
    espr-developer-32.build.flash_mode=dio
    espr-developer-32.build.flash_size=4MB
    espr-developer-32.build.boot=bootloader
    
    espr-developer-32.menu.FlashMode.qio=QIO
    espr-developer-32.menu.FlashMode.qio.build.flash_mode=dio
    espr-developer-32.menu.FlashMode.qio.build.boot=bootloader_qio
    espr-developer-32.menu.FlashMode.dio=DIO
    espr-developer-32.menu.FlashMode.dio.build.flash_mode=dio
    espr-developer-32.menu.FlashMode.qout=QOUT
    espr-developer-32.menu.FlashMode.qout.build.flash_mode=dout
    espr-developer-32.menu.FlashMode.qout.build.boot=bootloader_qio
    espr-developer-32.menu.FlashMode.dout=DOUT
    espr-developer-32.menu.FlashMode.dout.build.flash_mode=dout
    
    espr-developer-32.menu.FlashFreq.80=80MHz
    espr-developer-32.menu.FlashFreq.80.build.flash_freq=80m
    espr-developer-32.menu.FlashFreq.40=40MHz
    espr-developer-32.menu.FlashFreq.40.build.flash_freq=40m
    
    espr-developer-32.menu.FlashSize.4M=4MB (32Mb)
    espr-developer-32.menu.FlashSize.4M.build.flash_size=4MB
    espr-developer-32.menu.FlashSize.2M=2MB (16Mb)
    espr-developer-32.menu.FlashSize.2M.build.flash_size=2MB
    espr-developer-32.menu.FlashSize.2M.build.partitions=minimal
    
    espr-developer-32.menu.UploadSpeed.115200=115200
    espr-developer-32.menu.UploadSpeed.115200.upload.speed=115200
    espr-developer-32.menu.UploadSpeed.256000.windows=256000
    espr-developer-32.menu.UploadSpeed.256000.upload.speed=256000
    espr-developer-32.menu.UploadSpeed.230400=230400
    espr-developer-32.menu.UploadSpeed.230400.upload.speed=230400
    espr-developer-32.menu.UploadSpeed.230400.windows.upload.speed=256000
    espr-developer-32.menu.UploadSpeed.460800.linux=460800
    espr-developer-32.menu.UploadSpeed.460800.macosx=460800
    espr-developer-32.menu.UploadSpeed.460800.upload.speed=460800
    espr-developer-32.menu.UploadSpeed.512000.windows=512000
    espr-developer-32.menu.UploadSpeed.512000.upload.speed=512000
    espr-developer-32.menu.UploadSpeed.921600=921600
    espr-developer-32.menu.UploadSpeed.921600.upload.speed=921600
    espr-developer-32.menu.UploadSpeed.960000=960000
    espr-developer-32.menu.UploadSpeed.960000.upload.speed=960000
    espr-developer-32.menu.UploadSpeed.1000000=1000000
    espr-developer-32.menu.UploadSpeed.1000000.upload.speed=1000000
    espr-developer-32.menu.UploadSpeed.1200000=1200000
    espr-developer-32.menu.UploadSpeed.1200000.upload.speed=1200000
    espr-developer-32.menu.UploadSpeed.1500000=1500000
    espr-developer-32.menu.UploadSpeed.1500000.upload.speed=1500000
    espr-developer-32.menu.UploadSpeed.2000000=2000000
    espr-developer-32.menu.UploadSpeed.2000000.upload.speed=2000000
    espr-developer-32.menu.UploadSpeed.3000000=3000000
    espr-developer-32.menu.UploadSpeed.3000000.upload.speed=3000000
    
    espr-developer-32.menu.DebugLevel.none=None
    espr-developer-32.menu.DebugLevel.none.build.code_debug=0
    espr-developer-32.menu.DebugLevel.error=Error
    espr-developer-32.menu.DebugLevel.error.build.code_debug=1
    espr-developer-32.menu.DebugLevel.warn=Warn
    espr-developer-32.menu.DebugLevel.warn.build.code_debug=2
    espr-developer-32.menu.DebugLevel.info=Info
    espr-developer-32.menu.DebugLevel.info.build.code_debug=3
    espr-developer-32.menu.DebugLevel.debug=Debug
    espr-developer-32.menu.DebugLevel.debug.build.code_debug=4
    espr-developer-32.menu.DebugLevel.verbose=Verbose
    espr-developer-32.menu.DebugLevel.verbose.build.code_debug=5
  3. Arduino IDE を開いていれば再起動する。

すると Arduino IDE で SWITCH SCIENCE ESPr Developer 32 が使えるようになります。

また、このボードは USB シリアルに FTDI FT231XS を採用しているので、スケッチを 3M (3000000) baud で転送する事が可能です。

なお、定義を追加すれば ESP32-DevKitC (CP2102) でもスケッチを 1.5M (1500000) baud で転送できます...CP2102N だと 3M 転送可能なんですけどね。



セットアップ

スケッチを書き込むための準備です。

ハードウェア (開発ボードの場合には読み飛ばしてください)

ESP-WROOM-32 にスケッチを書き込むには電源と何らかの USB<->シリアル変換モジュールが必要です。

この ESP32 ブレークアウトボードの EN ピンは 10kΩ抵抗でプルアップされている事に注意してください。EN<->3V3 間に10kΩ抵抗が必要です。

自動プログラム回路は ESP-WROOM-02 のものを流用できますN-ch MOSFET の回路がスッキリしていいかと思います。

ESP-WROOM-32 変換モジュール USB シリアル
TXD RXD
RXD TXD
ID0 6 D2
EN 8 D1
2 G1 DTR
4 G2 RTS

自動プログラムが安定しない場合には、EN <-> GND 間1nF (0.001μF / 1000pF)~0.1μF のコンデンサを入れてみてください (この図の C3 コンデンサに相当)。

Windows で USB<->シリアル変換に CP2102 を使う場合には EN <-> GND 間にもっと大きな 0.22μF~2.2μF のコンデンサを入れてください。CP2102 を使っている開発ボードも DOIT V1 の回路図通りならコンデンサを追加する必要があると思います。

自動プログラム回路を使わない、または "RTS / DTR の引き出せない USB<->シリアル変換モジュールしか持っていない" 場合にはボタンの実装が必要となります。

ボタンはチャタリング (バウンシング) を考慮しないのであれば、IO0<->GND 間 (FLASH / KEY / BOOT ボタン) と EN<->GND 間 (EN / RST ボタン) にスイッチを取り付けるだけです。

See Also:

ソフトウェア

ESP-WROOM-32 を Arduino IDE で使うには Arduino core for the ESP32 をインストールします。

  1. https://github.com/espressif/arduino-esp32 から [Clone or download] ボタンを押し、zip アーカイブを取得。
  2. アーカイブを適当な場所に解凍。
  3. Arduino インストールフォルダの中の hardware フォルダに、espressif サブフォルダを作成。
  4. espressif フォルダの中に esp32 サブフォルダを作成。
  5. 解凍したアーカイブの中身を esp32 フォルダ内にコピー。
  6. 階層は以下のようになる。
  7. Arduino インストールフォルダ\hardware\espressif\esp32\tools にある get.exe を右クリックし、[管理者として実行] で実行。

    コマンドプロンプトが消えるまでしばらく待つ (あまりにも時間が掛かるようなら〔Enter〕キーを叩いてみる)。

以上で ESP-WROOM-32 が Arduino IDE から使えるようになりました。

See Also:

はい、ちょっと待って!

Arduino IDE で開発する前に、まずは工場出荷時のファームウェアをバックアップしましょう。

@echo off
SET COM_PORT=COM4
esptool.exe --chip esp32 --port %COM_PORT% --baud 921600 read_flash 0 0x400000 esp32_firmware.bin

このスクリプトを Firmware_Backup.cmd という名前で Arduino インストールフォルダ\hardware\espressif\esp32\tools に保存します。

@echo off
SET COM_PORT=COM4
esptool.exe --chip esp32 --port %COM_PORT% --baud 921600 write_flash 0 esp32_firmware.bin

このスクリプトを Firmware_Restore.cmd という名前で Arduino インストールフォルダ\hardware\espressif\esp32\tools に保存します。

そして、Firmware_Backup.cmd を管理者として実行してください。Arduino インストールフォルダ\hardware\espressif\esp32\tools フォルダに 4MB の esp32_firmware.bin が生成されます。赤字の部分はご自分の環境に合わせて適宜書き換えてください。

See Also:



Blink

L チカ (Blink) のサンプルスケッチは [ファイル | スケッチ例 | 01.Basics | Blink] です。コンパイルするには...

基本的にこの 2 つを指定するだけです。

オンボード LED が存在しない開発ボードも多く、コンパイル時に LED_BUILTIN が未定義エラーになる事があります。LED_BUILTIN が定義されていないボードをお使いの場合には、LED_BUILTIN の部分を LED を接続したピン番号で置き換えてください。

 

自動書き込み

開発ボードを使うか自動プログラム回路を付けていれば Arduino UNO 並のお手軽さで使えます。何も考えずに [マイコンボードに書き込む] ボタンを押すだけです。

開発ボードを使っているのに自動プログラムできない場合は EN<->GND 間にコンデンサを追加してみましょう。
 

手動書き込み

ボタンを使ってスケッチを書き込むには...

  1. IO0 (FLASH / KEY / BOOT) ボタンを押しっぱなしにする
  2. EN (RST / RESET) ボタンを押して離す
  3. スケッチをコンパイル&転送 ([マイコンボードに書き込む] ボタンを押す)
  4. 転送が始まったら IO0 ボタンを離す
  5. 書き込みが完了したら EN ボタンを押して離す

ESP-WROOM-02 の時と似たような感じですね。



ピンの説明

ESP-WROOM-32 DataSheet (espressif.com) からの抜粋です。

名称 No. 種類 機能
GND 1 P Ground
3V3 2 P Power supply.
EN 3 I Chip-enable signal. Active high.
SENSOR_VP 4 I GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0
SENSOR_VN 5 I GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3
IO34 6 I GPIO34, ADC1_CH6, RTC_GPIO4
IO35 7 I GPIO35, ADC1_CH7, RTC_GPIO5
IO32 8 I/O GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9
IO33 9 I/O GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8
IO25 10 I/O GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
IO26 11 I/O GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
IO27 12 I/O GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
IO14 13 I/O GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2
IO12 14 I/O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3
GND 15 P Ground
IO13 16 I/O GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER
SHD/SD2* 17 I/O GPIO9, SD_DATA2, SPIHD, HS1_DATA2, U1RXD
SWP/SD3* 18 I/O GPIO10, SD_DATA3, SPIWP, HS1_DATA3, U1TXD
SCS/CMD* 19 I/O GPIO11, SD_CMD, SPICS0, HS1_CMD, U1RTS
SCK/CLK* 20 I/O GPIO6, SD_CLK, SPICLK, HS1_CLK, U1CTS
SDO/SD0* 21 I/O GPIO7, SD_DATA0, SPIQ, HS1_DATA0, U2RTS
SDI/SD1* 22 I/O GPIO8, SD_DATA1, SPID, HS1_DATA1, U2CTS
IO15 23 I/O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3
IO2 24 I/O GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0
IO0 25 I/O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
IO4 26 I/O GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER
IO16 27 I/O GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
IO17 28 I/O GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
IO5 29 I/O GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
IO18 30 I/O GPIO18, VSPICLK, HS1_DATA7
IO19 31 I/O GPIO19, VSPIQ, U0CTS, EMAC_TXD0
NC 32 -
IO21 33 I/O GPIO21, VSPIHD, EMAC_TX_EN
RXD0 34 I/O GPIO3, U0RXD, CLK_OUT2
TXD0 35 I/O GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
IO22 36 I/O GPIO22, VSPIWP, U0RTS, EMAC_TXD1
IO23 37 I/O GPIO23, VSPID, HS1_STROBE
GND 38 P Ground
GND 39 P Ground
Note:
    * Pins SCK/CLK, SDO/SD0, SDI/SD1, SHD/SD2, SWP/SD3 and SCS/CMD, namely, GPIO6 to GPIO11 are connected
    to the integrated SPI flash integrated on ESP-WROOM-32 and are not recommended for other uses.

注意書きを要約すると、

という事のようです。また、EN, SENSOR_VP (IO36), SENSOR_VN (IO39), IO34, IO35 は入力専用となっています。

See Also:



ペリフェラルとセンサー

ESP-WROOM-32 DataSheet (espressif.com) からの抜粋です。

インターフェイス 信号 ピン 機能
ADC ADC1_CH0 SENSOR_VP (IO36) Two 12-bit SAR ADCs
ADC1_CH3SENSOR_VN (IO39)
ADC1_CH4IO32
ADC1_CH5IO33
ADC1_CH6IO34
ADC1_CH7IO35
ADC2_CH0IO4
ADC2_CH1IO0
ADC2_CH2IO2
ADC2_CH3IO15
ADC2_CH4IO13
ADC2_CH5IO12
ADC2_CH6IO14
ADC2_CH7IO27
ADC2_CH8IO25
ADC2_CH9IO26
Ultra Low Noise
Analog Pre-Amplifier
SENSOR_VP IO36 Provides about 60dB gain by using larger
capacitors on PCB
SENSOR_VNIO39
DAC DAC_1 IO25 Two 8-bit DACs
DAC_2IO26
Touch Sensor TOUCH0 IO4 Capacitive touch sensors
TOUCH1IO0
TOUCH2IO2
TOUCH3IO15
TOUCH4IO13
TOUCH5IO12
TOUCH6IO14
TOUCH7IO27
TOUCH8IO33
TOUCH9IO32
SD / SDIO / MMC
Host Controller
HS2_CLK MTMS (IO14) Supports SD memory card V3.01 standard
HS2_CMDMTDO (IO15)
HS2_DATA0IO2
HS2_DATA1IO4
HS2_DATA2MTDI (IO12)
HS2_DATA3MTCK (IO13)
Motor PWM Any GPIOs* Three channels of 16-bit timers generate
PWM waveforms; each has a pair of
output signals. Three fault detection
signals. Three event capture signals. Three
sync signals.
LED PWM Any GPIOs* 16 independent channels @80MHz
clock/RTC CLK. Duty accuracy: 16 bits.
UART Any GPIOs* Two UART devices with hardware
flow-control and DMA
I2C Any GPIOs* Two I2C devices in slave or master modes
I2S Any GPIOs* Stereo input and output from/to the audio
codec, and parallel LCD data output
Remote Controller Any GPIOs* Eight channels of IR transmitter and
receiver for various waveforms
Parallel QSPI SPIHD SHD/SD2 (IO9) Supports Standard SPI, Dual SPI, and
Quad SPI that can be connected to the
external flash and SRAM
SPIWPSWP/SD3 (IO10)
SPICS0SCS/CMD (IO11)
SPICLKSCK/CLK (IO6)
SPIQSDO/SD0 (IO7)
SPIDSDI/SD1 (IO8)
HSPICLKIO14
HSPICS0IO15
HSPIQIO12
HSPIDIO13
HSPIHDIO4
HSPIWPIO2
VSPICLKIO18
VSPICS0IO5
VSPIQIO19
VSPIDIO23
VSPIHDIO21
VSPIWPIO22
General Purpose SPI Any GPIOs* Standard SPI consists of clock,
chip-select, MOSI and MISO. These SPIs
can be connected to LCD and other
external devices. They support the
following features:
  • both master and slave modes;
  • 4 sub-modes of the SPI format
    transfer that depend on the clock
    phase (CPHA) and clock polarity
    (CPOL) control;
  • CLK frequencies by a divider;
  • up to 64 bytes of FIFO and DMA.
JTAG MTDI IO12 JTAG for software debugging
MTCKIO13
MTMSIO14
MTDOIO15
SDIO Slave

※ESP-WROOM-32
では使えません
SD_CLK IO6 SDIO interface that conforms to the
industry standard SDIO 2.0 card
specification. On ESP-WROOM-32 these
pins are connected to the integrated SPI
flash.
SD_CMDI11
SD_DATA0IO7
SD_DATA1IO8
SD_DATA2IO9
SD_DATA3IO10
EMAC EMAC_TX_CLK IO0 Ethernet MAC with MII/RMII interface
EMAC_RX_CLKIO5
EMAC_TX_ENIO21
EMAC_TXD0IO19
EMAC_TXD1IO22
EMAC_TXD2IO14
EMAC_TXD3IO12
EMAC_RX_ERIO13
EMAC_RX_DVIO27
EMAC_RXD0IO25
EMAC_RXD1IO26
EMAC_RXD2TXD (IO1)
EMAC_RXD3IO15
EMAC_CLK_OUTIO16
EMAC_CLK_OUT_180IO17
EMAC_TX_ERIO4
EMAC_MDC_outAny GPIOs*
EMAC_MDI_in
EMAC_MDO_out
EMAC_CRS_out
EMAC_COL_out
Note:
  • Functions of Motor PWM, LED PWM, UART, I2C, I2S, general purpose SPI and Remote Controller can be configured
    to any GPIO except GPIO6, GPIO7, GPIO8, GPIO9, GPIO10 and GPIO11.
  • In Table 6, for the items marked with "Any GPIOs*" in the "Pin" column, users should note that GPIO6, GPIO7,
    GPIO8, GPIO9, GPIO10 and GPIO11 are connected to the integrated SPI flash of ESP-WROOM-32 and are not
    recommended for other uses.

注意書きを要約すると、

という事のようです。また、EN, SENSOR_VP (IO36), SENSOR_VN (IO39), IO34, IO35 は入力専用となっています。

See Also:



analogRead()

ADC に使えるピンは以下の通りです。

定数 ピン 信号名
A0SENSOR_VP (IO36) ADC1_CH0
A3SENSOR_VN (IO39) ADC1_CH3
A4IO32 ADC1_CH4
A5IO33 ADC1_CH5
A6IO34 ADC1_CH6
A7IO35 ADC1_CH7
A10IO4 ADC2_CH0
A11IO0 ADC2_CH1
A12IO2 ADC2_CH2
A13IO15 ADC2_CH3
A14IO13 ADC2_CH4
A15IO12 ADC2_CH5
A16IO14 ADC2_CH6
A17IO27 ADC2_CH7
A18IO25 ADC2_CH8
A19IO26 ADC2_CH9

ESP-WROOM-32 での ADC の基準電圧は 1.1V ですが、減衰器 (アッテネータ) により 3.3V での読み取りが可能になっています。ESP-WROOM-02 のような罠はありません。但し、緑字のピンは動作モードに関連するので注意が必要です。

ADC。

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

void loop() {
  int adc_key_in = analogRead(4);
  Serial.println(adc_key_in);  
}

適当なアナログピン (スケッチでは IO4) に可変抵抗を付けます。シリアルモニタ (115200) を開いてボリュームを回してみると、値は 0~4095 の間で変化するはずです (12bit)。

See Also:

リニアじゃない!

読み取ったアナログ値がリニアに変換されない という話があるようですが、上記スケッチで値から電圧を実測してみた限りではそこまで極端な誤差はない気がします。

実測電圧 理論電圧
40953.31 3.310
35832.88 2.896
30712.54 2.483
25592.15 2.069
20471.7511.655
15351.3511.241
10230.9350.828
511 0.5260.414
0 0 0.000

最大の実測電圧が 3.31V だったので、理論電圧の上限も 3.31V に合わせてあります。安物テスターとブレッドボードでの実測なのでデータに信頼性はありません (w

グラフにするとこうなります。青が実測値で、赤が理論値です。

既に補正が入っているのでしょうかね、言うほどズレてないような?それでも、ちゃんとやるなら更なる補正関数を噛ますか、外部 ADC IC を使わないといけないかもしれません。特にアナログ値で読み取る温度センサー等ではこの誤差は看過できないと思われます。

See Also:

Wi-Fi 使用時

Wi-Fi 使用時 には ADC2 が使えません。つまり、実質 A4 (IO32) ~ A7 (IO35) の 4 本しか使えません。



analogWrite()

arduino-esp32 には、現状 analogWrite() がありません

似たような事はできます。[ファイル | スケッチ例 | ESP32 | AnalogOut] にあるスケッチを参考にしてみてください。

LED Control PWM (LEDC)

L チカ用のサンプルスケッチは LEDCSoftwareFade です。

以下は [ファイル | スケッチ例 | 01.Basics] にある Fade と同等のスケッチです。

int LEDC_CHANNEL_0 = 0;     // LEDC channel (0-15)
int LEDC_BASE_FREQ = 4900;  // use 4900 Hz as a LEDC base frequency  
int LEDC_TIMER_13_BIT = 13// use 13 bit precission for LEDC timer
int led = 5;                // LED connected to IO5
int brightness = 0;         // how bright the LED is
int fadeAmount = 5;         // how many points to fade the LED by

// Arduino like analogWrite
// value has to be between 0 and valueMax
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
  // calculate duty
  uint32_t dutybase = (1 << LEDC_TIMER_13_BIT) - 1;
  uint32_t duty = (dutybase / valueMax) * min(value, valueMax);
  // write duty to LEDC
  ledcWrite(channel, duty);
}

void setup() {
  // Setup timer and attach timer to a led pin
  ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(led, LEDC_CHANNEL_0);
}

void loop() {
  // set the brightness on LEDC channel 0
  ledcAnalogWrite(LEDC_CHANNEL_0, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
}

Arduino の analogWrite() の周波数は多くの場合で 490Hz です。LEDC_BASE_FREQ の値は 4900 等、490 の倍数の方が UNO での動作に近いと思います。

Sigma-Delta Modulation

こちらはΔΣ変調のようです。SigmaDelta がサンプルスケッチです。(ソースコード的に) Arduino 標準の analogWrite() の使い方に近いのはこちらです。

以下は [ファイル | スケッチ例 | 01.Basics] にある Fade と同等のスケッチです。

int SIGMADELTA_CHANNEL_0 = 0// SigmaDelta channel (0-7)
int SIGMADELTA_FREQ = 4900;   // use 4900 Hz as a SigmaDelta base frequency   
int led = 5;                  // LED connected to IO5
int brightness = 0;           // how bright the LED is
int fadeAmount = 5;           // how many points to fade the LED by

// the setup routine runs once when you press reset:
void setup()
{
    sigmaDeltaSetup(SIGMADELTA_CHANNEL_0, SIGMADELTA_FREQ); // setup channel 0 with frequency 4900 Hz
    sigmaDeltaAttachPin(led, SIGMADELTA_CHANNEL_0);         // attach pin 5 to channel 0
    sigmaDeltaWrite(SIGMADELTA_CHANNEL_0, 0);               // initialize channel 0 to off
}

// the loop routine runs over and over again forever:
void loop() {
  // set the brightness of channel 0:
  sigmaDeltaWrite(SIGMADELTA_CHANNEL_0 , brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
}

SigMaDelta の周波数指定は 1220 Hz~312500 Hz の間で行う必要があります。

See Also:



ledcWriteNote() / ledcWriteTone()

LEDC には何故か Note / Tone 関係の関数が含まれています。esp32-hal-ledc に ledcWriteNote() / ledcWriteTone() が実装されていますので、これで音を鳴らすことができます。

ledcWriteNote()

Arduino チュートリアルの Play a Melody using the tone() function と同等のメロディを鳴らしてみます。

// use first channel of 16 channels (started from zero)
#define LEDC_CHANNEL_0     0

// use 13 bit precission for LEDC timer
#define LEDC_TIMER_13_BIT  13

// use 5000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ     5000

// SPEAKER PIN
#define SPEAKER_PIN        22

const int NOTE_NONE = NOTE_MAX;

int melody[] = {
  NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_NONE, NOTE_B, NOTE_C
};

int noteOctaves[] = {
  43333034
};

int noteDurations[] = {
  48844444
};

void setup() {
  ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(SPEAKER_PIN, LEDC_CHANNEL_0);
}

void loop() {
  for (int thisNote = 0; thisNote < 8; thisNote++) {
    ledcWriteNote(LEDC_CHANNEL_0, (note_t)melody[thisNote], noteOctaves[thisNote]);
    int pauseBetweenNotes = 1000 / noteDurations[thisNote] * 1.30;
    delay(pauseBetweenNotes);
    ledcWriteTone(LEDC_CHANNEL_0, 0); // stop the tone playing:
  }
  delay(2000);  
}

IO22 にスピーカー (パッシブブザー) を接続してスケッチを実行してみてください。以下、ノートとオクターブの対応表です (単位は Hz)。

ノート ノート定数
(note_t)
オクターブ
0 1 2 3 4 5 6 7 8
NOTE_C 16.3532.7065.41 130.81261.62523.251046.502093.004186.00
ド♯ NOTE_Cs 17.3234.6569.30 138.59277.19554.371108.752217.504435.00
NOTE_D 18.3636.7173.42 146.84293.69587.371174.752349.504699.00
ミ♭ NOTE_Eb 19.4538.8977.78 155.56311.12622.251244.502489.004978.00
NOTE_E 20.6041.2082.41 164.81329.62659.251318.502637.005274.00
ファ NOTE_F 21.8343.6687.31 174.62349.25698.501397.002794.005588.00
ファ♯NOTE_Fs 23.1246.2592.50 185.00370.00740.001480.002960.005920.00
NOTE_G 24.5049.0098.00 196.00392.00784.001568.003136.006272.00
ソ♯ NOTE_Gs 25.9651.91103.83207.66415.31830.621661.253322.506645.00
NOTE_A 27.5055.00110.00220.00440.00880.001760.003520.007040.00
シ♭ NOTE_Bb 29.1458.27116.55233.09466.19932.371864.753729.507459.00
NOTE_B 30.8761.73123.47246.94493.87987.751975.503951.007902.00

ちなみに SHARP PC-E500 の BEEP で鳴らせる範囲は ド(4)~ド(7) までです。

ledcWriteTone()

Arduino 純正 tone() と同じように音を鳴らせるハズですが...試しにサインスマートのプロジェクト練習教本 Chapter 7: Buzzer 用のスケッチを改変して鳴らしてみます。

// use first channel of 16 channels (started from zero)
#define LEDC_CHANNEL_0     0

// use 13 bit precission for LEDC timer
#define LEDC_TIMER_13_BIT  13

// use 5000 Hz as a LEDC base frequency
#define LEDC_BASE_FREQ     5000

int passiveBuzPin = 22;
int i = 0;
int numOfLoops = 0;
int noteDuration = 1000/8;  // an eighth note
int pauseBetweenNotes = noteDuration * 0.2;

void setup() {
  ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(passiveBuzPin, LEDC_CHANNEL_0);
}

void loop() {
  // This outer for statement determines the number
  // of siren cycles that are played.
  for(numOfLoops =0; numOfLoops < 4; numOfLoops++) {
    // Play low to high frequencies
    for(i=25;i<120;i++){
      ledcWriteTone(LEDC_CHANNEL_0, 20*i);
      delay(noteDuration);
      //ledcNoTone(LEDC_CHANNEL_0);
      //delay(pauseBetweenNotes);
    }
    // Play high to low frequencies
    for(i=120;i>=25;i--){
      ledcWriteTone(LEDC_CHANNEL_0, 20*i);
      delay(noteDuration);
      //ledcNoTone(LEDC_CHANNEL_0);
      //delay(pauseBetweenNotes);
    }
  }
}

void ledcNoTone(uint8_t channel){
  ledcWriteTone(channel, 0);  
}

IO22 にスピーカー (パッシブブザー) を接続してスケッチを実行してみてください。私のやり方が悪いのか、音と音がキレイに繋がりません。

SHARP PC-E500 の BEEP 1 で鳴るビープ音は以下のソースコードで再現できます (大体合ってる)。

  ledcWriteTone(LEDC_CHANNEL_0, 4000); // 4KHz
  delay(583);                          // 583 ms
  ledcWriteTone(LEDC_CHANNEL_0, 0);

マニアックすぎましたかね (^^;A



8bit DAC

IO25 と IO26 は dacWrite() を用いて 8bit DAC ができます。UNOanalogWrite() のような PWM ではなく DAC を使ったアナログ出力です。Arduino DUE で DAC1 / DAC2 ピンに対して analogWrite() するのと同等です (但し DUE は 12bit DAC)。

以下は [ファイル | スケッチ例 | 01.Basics] にある Fade と似たような動作をするスケッチです。PWM ではないので、LED が光っている時間は短いです (値が 127 でも 1.65V 付近なので LED は光らない)。

int led = 25;       // DAC pin (25 or 26)
int brightness = 0// how bright the LED is
int fadeAmount = 5// how many points to fade the LED by

void setup() {
  dacWrite(led, 0);
}

void loop() {
  // set the brightness on LEDC pin 25
  dacWrite(led, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
}

当方の環境で dacWrite(25, 127); を実測したら、1.637V になりました。

See Also:



SPI

SPI に使えるピンはデフォルトで以下の通りです。これは VSPI と呼ばれます。

SPI ピン VSPI
SCK IO18 VSPICLK
MISOIO19 VSPIQ
MOSIIO23 VSPID
SS IO5 VSPICS0
IO21 VSPIHD
IO22 VSPIWP

Arduino ESP32 の SPIClass.begin() は引数を持っており、任意のピンを使った 汎用 SPI (General-Purpose SPI) 通信ができます。

void begin(int8_t sck=SCK, int8_t miso=MISO, int8_t mosi=MOSI, int8_t ss=-1);

さらに VSPI とは別系統の SPI ポートがあります。これは HSPI と呼ばれます。

SPI ピン HSPI
SCK IO14 HSPICLK
MISOIO12 HSPIQ
MOSIIO13 HSPID
SS IO15 HSPICS0
IO4 HSPIHD
IO2 HSPIWP

HSPI を使うには SPIClass のコンストラクタに HSPI を指定します (明示的に指定しなかった場合も HSPI になります)。

#include "SPI.h"

  ...

SPIClass hspi(HSPI);  

上記コードで、SPI オブジェクト (VSPI) とは別に、hspi オブジェクト (HSPI) が使える事になります。

SD (VSPI 接続)

SD カードを SPI 接続 (VSPI) する場合についてです。この接続方法のスケッチは [ファイル| スケッチ例 | SD(esp32)] にある SD_Test です。

SD SPI ピン VSPI
9 DAT2
1 DAT3SS IO5 VSPICS0
2 CMD MOSIIO23 VSPID
3 VSS1 GND
4 VCC VCC/3.3V
5 CLK SCK IO18 VSPICLK
6 VSS2 GND
7 DAT0MISOIO19 VSPIQ
8 DAT1

SD カードを接続したい場合には、MISO (DAT0 / DO) に指定したピンを忘れずにプルアップする必要があります。

外部抵抗を使わず、setup() で pinMode(MISO, PULLUP) として、

void setup(){
    pinMode(MISO, PULLUP); // ADD

    Serial.begin(115200);
    if(!SD_MMC.begin()){
        Serial.println("Card Mount Failed");
        return;
    }
    ...

内部プルアップでも動作するかもしれませんが、確実性を求めるならば MISO (IO19) を 10kΩ抵抗でプルアップしてください。

bool begin(uint8_t ssPin=SS, SPIClass &spi=SPI, uint32_t frequency=4000000const char * mountpoint="/sd");

SD.begin() メソッドにはオリジナルの SD ライブラリ同様、チップセレクトピンを引数として指定する事ができます (デフォルトで SS が指定されます)。

See Also:

SD MMC (HS2 接続)

HSPI 接続と同じピンを使って、SD_MMC (HS2) 接続ができます。この接続方法のスケッチは [ファイル| スケッチ例 | SD_MMC] にある SDMMC_Test です。VSPI 接続に比べると配線するピンが多くなります

SD ピン HS2
9 DAT2IO12 HS2_DATA2
1 DAT3IO13 HS2_DATA3
2 CMD IO15 HS2_CMD
3 VSS1GND
4 VCC VCC/3.3V
5 CLK IO14 HS2_CLK
6 VSS2GND
7 DAT0IO2 HS2_DATA0
8 DAT1IO4 HS2_DATA1

面倒臭いなぁ...この方式を選択するメリットあるんですかね?

  1. SD カードモジュールを HS2 で結線する
  2. IO4 (DAT1) と IO13 (DAT3) を 10KΩ抵抗でプルアップする。IO2 (DAT0) と IO12 (DAT2) はプルアップしない (プルアップが不要とは言ってない)。
  3. setup() に以下のコードを追加し、IO2 (DAT0) と IO12 (DAT2) を内部プルアップする。
    void setup(){
        pinMode( 2, PULLUP); // ADD
        pinMode(12, PULLUP); // ADD
    
        Serial.begin(115200);
        if(!SD_MMC.begin()){
            Serial.println("Card Mount Failed");
            return;
        }
        ...

一応、この手順で SD_MMC が使え、自動プログラムとも両立できるようですが、確実性を求めるなら 魔法の大鍋さんの ESP-WROOM-32開発ボード+microSD を参考に回路を追加した方がいいでしょうね。

See Also:

使えない SPI (SPI / SDIO Slave)

IO6~IO11 を使った SPI は ESP-WROOM-32 では利用不可です。理由は内部 FLASH との接続に使われているからです。これらのピンは SPI 以外の用途であっても使うべきではありません。

つまり、ESP32 では使えますが、ESP-WROOM-32 では実質使えない SPI という事になります。ソースコード内ではこの SPI を FSPI と呼んでいる箇所があります。

See Also:



Serial (UART)

Serial

Serial (UART) に使えるピンはデフォルトで以下の通りです。

定数 ピン
TXDIO3 (TXD0)
RXDIO1 (RXD0)

Serial オブジェクトは宣言なしに利用可能です。以下は ESP32 のチップ情報を表示するスケッチです。

// Model Strings
const char* ModelStrings[] PROGMEM = {"""ESP32"};

// Add Feature String
void AddFeatureString(String &S, const String F) {
  if (S.length() != 0) S.concat(", ");
  S.concat(F);
}

void setup() {
  // Get Chip Information
  esp_chip_info_t chip_info;
  esp_chip_info(&chip_info);

  // Start Serial Communication
  Serial.begin(115200);
  while (!Serial);
  Serial.println("\r\n***** Chip Information *****");

  // Model
  Serial.printf("Model: %s\r\n", ModelStrings[chip_info.model]);

  // Features
  String Features = "";
  if (chip_info.features & CHIP_FEATURE_EMB_FLASH) AddFeatureString(Features, "Embedded Flash");
  if (chip_info.features & CHIP_FEATURE_WIFI_BGN ) AddFeatureString(Features, "Wifi-BGN"      );
  if (chip_info.features & CHIP_FEATURE_BLE      ) AddFeatureString(Features, "BLE"           );
  if (chip_info.features & CHIP_FEATURE_BT       ) AddFeatureString(Features, "Bluetooth"     );
  Serial.println("Features: " + Features);

  // Cores
  Serial.printf("Cores: %d\r\n", chip_info.cores);

  // Revision
  Serial.printf("Revision: %d\r\n", chip_info.revision);

  // MAC Address
  String MACString = "";
  uint64_t chipid = ESP.getEfuseMac(); 
  for (int i=0; i<6; i++) {
    if (i > 0) MACString.concat(":");
    uint8_t Octet = chipid >> (i * 8);
    if (Octet < 16) MACString.concat("0");
    MACString.concat(String(Octet, HEX));
  }
  Serial.println("MAC Address: " + MACString);

  // Flash Size
  uint32_t FlashSize = ESP.getFlashChipSize();
  String ValueString = "";
  do {
    String temp = String(FlashSize);
    if (FlashSize >= 1000) {
      temp = "00" + temp;
      ValueString = "," + temp.substring(temp.length() - 3, temp.length()) + ValueString;
    } else {
      ValueString = temp + ValueString;
    }  
    FlashSize /= 1000;
  } while (FlashSize > 0);
  Serial.println("Flash Size: " + ValueString);
}

void loop() {

}

See Also:

SoftwareSerial

2017/07 現在、SoftwareSerial は利用できません。外部ライブラリを使用してください。

See Also:

HardwareSerial

3系統のハードウエアシリアルを利用可能です。よく使う Serial オブジェクトはハードウェアシリアルです (UART0)。

UART0 UART1 UART2
TXDIO3 (TXD0)IO10 IO17
RXDIO1 (RXD0)IO9 IO16
RTSIO22 IO11IO7
CTSIO19 IO6 IO8

ハードウェアシリアルは以下のようなコードで使えるようになります。

HardwareSerial mySerial(2); // UART2

void setup() {
  mySerial.begin(115200);
}

void loop() {
  ...
}

ESP-WROOM32 には IO6~IO11 を使ってはいけないという制約があるので、UART1 は使えません

但し、UART はピンを変更可能なため、ピンを変更した UART1 なら利用可能です。

HardwareSerial mySerial1(1); // UART1 (RX=9, TX=10)
HardwareSerial mySerial2(2); // UART2 (RX=16, TX=17)

void setup() {
  mySerial1.begin(115200, SERIAL_8N1, 3233); // ピンを変更 (RX=32, TX=33)
  mySerial2.begin(115200);
}

void loop() {
  ...
}

IO6~IO11, IO34, IO35 以外なら任意の GPIO に割り当て可能だと思われます。



I2C

I2C に使えるピンはデフォルトで以下の通りです。

定数 ピン
SDAIO21
SCLIO22

但し、ESP-WROOM-32 の Wire.begin() は引数を持っており、任意のピンを使った I2C 通信ができます。

void begin(int sda=-1int scl=-1, uint32_t frequency=100000);

See Also:



ホール効果センサー

ESP32 にはホール効果センサー (Hall Effect Sensors) が内蔵されています。簡単に言えば磁気センサーです。

ESP-WROOM-32 では追加回路なしにこのホール効果センサーを使うことができます。

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

void loop() {
  int v = hallRead();
  Serial.println(v, DEC);
  delay(200);
}

このスケッチを書き込んでシリアルモニタを開いたら、ESP-WROOM-32 の上で磁石の N 極を近付けたり、S 極を近付けたりしてみましょう。

※ [ファイル | スケッチの例 | ESP32 | HallSensor] にもサンプルスケッチがあります。

See Also:



タッチセンサー

ESP32 にはタッチセンサーが内蔵されています。テストスケッチは [ファイル | スケッチ例 | ESP32 | Touch] です。TouchRead を簡易的に動作させるには、IO4 にジャンパーワイヤーを接続してそれを触ってみてください。

ミノムシクリップでコインを挟んでも、ジャンパーワイヤーをバナナに刺してもイケます (本当)。

定数 ピン
T0IO4
T1IO0
T2IO2
T3IO15
T4IO13
T5IO12
T6IO14
T7IO27
T8IO33
T9IO32

タッチセンサーに使えるピンは全部で 10 本です。うまくやれば 4 ピンで表面型静電容量方式タッチスクリーン がやれるのではないかと思います。

See Also:



SPIFFS (SPI Flash File System)

ESP-WROOM-32 には 4MB のフラッシュメモリが内蔵されており、これは SPI で接続されています。スケッチをコンパイルしたバイナリ...いわゆるファームウェアはこのフラッシュメモリに格納されるのですが、余剰分のフラッシュメモリをストレージのように使う事ができます。この機能は SPIFFS と呼ばれています。

アップローダのインストール

SPIFFS にファイルを格納する方法はいくつかあります。

最も簡単な方法はアップローダを使う方法です。以下、アップローダのインストール方法です。

  1. アップローダの最新版を DL する。
  2. アーカイブを解凍する。
  3. <Arduino のインストールフォルダ>\tools\ESP32FS\tool に esp32fs.jar をコピーする (存在しないフォルダは作成)
  4. Arduino IDE を再起動する。
  5. [ツール] に ESP32 Sketch Data Upload が追加される。

See Also:

ファイルのアップロード方法

ファイルをアップロードするのは簡単です。

  1. スケッチ (*.ino) のあるフォルダに data というサブフォルダを作成する
  2. data フォルダにアップロードしたいファイルをコピーする
  3. [ツール | ESP32 Sketch Data Upload] でファイルをアップロードする

※アップロードの前にシリアルモニタやシリアルプロッタは閉じておきましょう。

スケッチでのファイル操作

ほぼ C 言語のファイル操作関数と同じなので難しくはないと思います。

#include "FS.h"
#include "SPIFFS.h"

const uint32_t BUF_SIZE = 255;

void setup() {
  Serial.begin(115200);
  while(!Serial);
  Serial.println("");

  SPIFFS.begin(true);

  /* CREATE FILE */
  File fp = SPIFFS.open("/TEST.TXT", FILE_WRITE); // 書き込み、存在すれば上書き
  char buf[BUF_SIZE + 1];
  String s = "The quick brown fox jumps over the lazy dog.\r\n";
  s.toCharArray(buf, BUF_SIZE);
  for (int i=0; i<20; i++)
    fp.write((uint8_t *)buf, BUF_SIZE);
  fp.close();

  /* READ FILE */
  fp = SPIFFS.open("/TEST.TXT", FILE_READ); // 読み取り
  while (fp.read((uint8_t *)buf, BUF_SIZE) == BUF_SIZE)
    Serial.print(buf);
  fp.close();

  /* DELETE FILE */
  SPIFFS.remove("/TEST.TXT");

  SPIFFS.end();  
}

void loop() {

}

SPIFFS は便利ですが、秒単位でログを取るような用途には向いていません (フラッシュメモリなので書き換え回数に上限があります)。

See Also:



Over The Air (OTA)

OTA は、簡単に言えば無線 LAN 経由でスケッチを書き込む機能です。Delphi は関係ないです。

環境構築

OTA をやるのに必要なのは

これだけです。ESP-WROOM-02 の時のように Python は要らないと思います。

概要

最近の ESP32 ライブラリには OTA ライブラリが含まれています。

  1. OTA 用スケルトンスケッチに無線 LAN アクセスポイントの SSID / Password を記述
  2. OTA 用スケルトンスケッチをコンパイル、USB<->シリアル変換モジュール経由でアップロード
  3. OTA 用スケルトンスケッチをベースにしたスケッチをコンパイル、無線 LAN 経由でアップロード

このような理屈なので、同じ機能のスケッチを書いたとしても OTA 経由で転送したものの方がサイズが大きくなります。

セットアップ

まずは OTA 用スケルトンスケッチをコンパイルしてアップロードします。

  1. [ファイル | スケッチの例 | Arduino OTA | Basic OTA]
  2. (自動プログラムが有効でない場合) IO0 ボタンを押しっぱなしにする。
  3. スケッチをコンパイルして USB<->シリアル変換モジュール経由でアップロード
  4. (自動プログラムが有効でない場合) IO0 ボタンを離す。
  5. アップロード完了
  6. (自動プログラムが有効でない場合) リセットボタン (EN ボタン) を押す
  7. シリアルモニタを開き 115200 で繋ぐと ESP-WROOM-32 が取得した IP アドレスが見れる
  8. Arduino IDE を再起動

次に任意のスケッチをコンパイルしてアップロードします。OTA 用スケルトンスケッチをベースにする必要があります。

  1. [ファイル | スケッチの例 | Arduino OTA | Basic OTA]
  2. [ファイル | 名前を付けて保存] で一旦保存
  3. 例は IO23 で L チカするスケッチ。
    #include <WiFi.h>
    #include <ESPmDNS.h>
    #include <WiFiUdp.h>
    #include <ArduinoOTA.h>
    
    const char* ssid = "あなたの AP の SSID";
    const char* password = "SSID に対するパスワード";
    
    void setup() {
    
      (中略)
    
      // 以降に初期化コード
      pinMode(23, OUTPUT);
    }
    
    void loop() {
      ArduinoOTA.handle();
    
      // 以降に実装コード
      digitalWrite(23, HIGH);
      delay(1000);
      digitalWrite(23, LOW);
      delay(1000);          
    }
  4. [ツール | シリアルポート] の下部に OTA スケッチを書き込んだ ESP-WROOM-32 が見えるのでそれを選択する。
  5. スケッチをコンパイルしてアップロード。当然ながら、OTA 経由の場合には IO0 が HIGH でも (IO0 ボタンを押さなくても) 書き込める。

OTA で書き込めない場合にはウィルス対策ソフトやファイアーウォールを疑ってみてください。OTA はデフォルトで 3232 番ポートを使用します。また、前回の OTA スケッチを変な設定で書き込んでしまったのかもしれません。設定をよく確認してから、スケルトンスケッチを USB<->シリアル変換モジュール経由で書き込んでみてください。

See Also:



チップバグ

ESP-WROOM-32 の revision 0 にはバグがあります。バグ持ちかどうかを確認するには以下のスケッチを実行します。

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

  Serial.printf("Revision: %d\r\n" , ESP.getChipRevision());
}

void loop() {

}

Arduino-ESP32 に付属の esptool.exe を実行する事でもリビジョンを確認できます。

C:\Arduino\hardware\espressif\esp32\tools>esptool.exe --port COM8 flash_id
esptool.py v2.1-beta1
Connecting....
Detecting chip type... ESP32
Chip is ESP32D0WDQ6 (revision 0)
Uploading stub...
Running stub...
Stub running...
Manufacturer: c8
Device: 4016
Detected flash size: 4MB
Hard resetting...

大まかなリビジョンは外観からも判断できるようです。

具体的なバグの内容については以下のドキュメントを参照してください。

何が困るの?

問題がなければそれでいいのですが、イロイロやっていると (多分) 遭遇するであろう問題は液晶ディスプレイや OLED を接続するとゴミが描画されるというものではないかと思います。これについては回避策があります。

  1. Arduino-ESP32 のインストールフォルダで esp32.peripherals.ld を探す (tools\sdk\ld にあるハズ)。
  2. esp32.peripherals.ld をテキストエディタで開く
  3. PROVIDE ( GPIO =... の行を書き換える。// でのコメントアウトはできないので、コメントアウトしたいのなら /* */ で括る事。
    /* PROVIDE ( GPIO = 0x3ff44000 ); */
    PROVIDE ( GPIO = 0x60004000 );

Arduino-ESP32 を更新した場合には、このファイルを忘れずにチェックしてください。

See Also:



ビルトイン BASIC

ESP-WROOM-32 にはビルトイン BASIC が仕込まれています。ビルトイン BASIC を起動する方法は以下の通りです:

  1. IO12 を 10kΩ抵抗でプルアップ (IO12 と 3V3 を10kΩ抵抗で繋ぐ)
  2. 電源 ON またはリセット
  3. シリアルモニタを 115200 bps で開く (任意のターミナルエミュレータで構わない)
  4. 以下のようなメッセージが繰り返し出る (IO15 をプルダウンしている場合には OK のみが繰り返し表示される) ので Enter を入力する。
    ets Jun  8 2016 00:22:57
    
    rst:0x10 (RTCWDT_RTC_RESET),boot:0x33 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0x00
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:2
    cmd len -1
    Falling back to built-in command interpreter.
    OK
    >
  5. ビルトイン BASIC が起動する。

about〔Enter〕とすると、このビルトイン BASIC が TinyBasic Plus、そして ROM BASIC である事が判ります。

>about
ESP32 ROM Basic (c) 2016 Espressif Shanghai
Derived from TinyBasic Plus by Mike Field and Scott Lawrence

mem〔Enter〕でフリーエリアを確認できます。

>mem
32560 bytes free.

help〔Enter〕で使えるコマンド (ステートメント) が確認できます。

>help
A very Basic ROM console. Available commands/functions:
LIST
NEW
RUN
NEXT
LET
IF
GOTO
GOSUB
RETURN
REM
FOR
INPUT
PRINT
PHEX
POKE
STOP
BYE
MEM
?
'
DELAY
END
RSEED
HELP
ABOUT
IOSET
IODIR
PEEK
ABS
RND
IOGET
USR

ファイル関係が実装されていないのがちょっと残念ですね。

BASIC 簡易リファレンス

ステートメント / 関数 書式 説明
' ' 〔<注釈文>〕 プログラム内に注釈を入れます。
→REM
? ? <式> 画面に文字列や数値を表示します。
→PRINT
ABOUT ABOUT ROM BASIC の詳細 (クレジット) を表示します。
ABS ABS(式) 式の絶対値を返します。
BYE BYE ROM BASIC を終了します
DELAY DELAY <ミリ秒> プログラムを指定した時間だけ止めます。単位はミリ秒です(1,000ミリ秒=1秒)。
delay()
END END プログラムを終了します
→STOP
FOR~NEXT FOR <変数>=<初期値> TO <最終値> 〔STEP <増分>〕
<ループの内容>
NEXT <変数>
FOR から NEXT までの指定されたループの内容を指定された回数だけ繰り返します。
NEXT の変数は省略できません。
GOSUB~RETURN GOSUB <行番号>
<処理>
RETURN
指定した行にあるサブルーチンを呼び出します。RETURN でサブルーチンから戻ります。
GOTO GOTO <行番号> 指定した行へジャンプします。
HELP HELP ヘルプ (ステートメント一覧) を表示します
IF IF <条件> <文> <条件> で条件判断を行い、その結果に応じて <文> を実行します。THEN ステートメントはありません。
INPUT INPUT <変数> 入力したデータを指定した変数に代入します。
IODIR IODIR <ピン番号>, <方向> ピン番号の入出力を指定します。0 が入力で、1 が出力、2 が恐らく内部プルアップ有効な入力です。
pinMode()
IOGET IOGET(<ピン番号>) 指定したピンの値を読み取ります。その結果は HIGH (1) または LOW (0) となります。
digitalRead()
IOSET IOSET <ピン番号>, <値> HIGH (1) または LOW (0) を、指定したピンに出力します。
digitalWrite()
LET LET <変数>=<値> 変数に値を代入します。LET は省略可能です。
LIST LIST 〔<行番号>〕 メモリにあるプログラムリストを画面に表示します。
MEM MEM フリーエリア (空きメモリ) を表示します。
NEW NEW メモリにあるプログラムを消去し、すべての変数を初期化します。
PEEK PEEK(<アドレス>) 指定されたアドレスの値を読み出します。
PHEX PHEX <値> 整数値を16進表現の文字列に変換して表示します。
POKE POKE <アドレス>, <値> 指定されたアドレスに値を書き込みます。
PRINT PRINT <式> 画面に文字列や数値を表示します。
→?
REM REM〔<注釈文>〕 プログラム内に注釈を入れます。
→'
RND RND(<最大値>) 0..最大値の整数型乱数を返します。
RSEED RSEED <シード> RND() 関数の乱数系列を初期化します。
RUN RUN 〔<行番号>〕 メモリにあるプログラムを実行します。
STOP STOP プログラムの実行を停止します。
→END
USR USR(<アドレス>〔, <引数>〕) アドレスから始まる機械語サブルーチンを実行します。引数の指定が可能で、戻り値も受け取れます。

サンプルとして http://p112.sourceforge.net/tbp112.html にあったHI/LOW GAME を移植してみました。

10 REM ****************************
20 REM *** PLAY THE HI/LOW GAME ***
30 REM ****************************
40 N=RND(100): C=0
45 PRINT "GUESS A NUMBER?"
50 INPUT G
60 C=C+1
70 IF G=N GOTO 110
80 IF G>N PRINT "LOWER"
90 IF G<N PRINT "HIGHER"
100 GOTO 50
110 PRINT "YOU GUESSED IT IN ", C, " TRIES!"

移植と言っても、ESP32 の TinyBasic Plus では INPUT 文にプロンプト文が指定できなかったので別途 PRINT 文を追加しただけです (行番号: 45)。

See Also:



AT コマンド

ESP-WROOM-32 にプログラムを書き込んで使うのではなく、AT コマンドを使ってシリアル通信による外部制御を行う事もできます。ESP-WROOM-02 と違い、工場出荷時のファームではありません。

ファームウェア書き込みに必要なもの

AT コマンドファームを書き込むのに必要なものは以下の二つです。

※記事は最後まで読んだ方がいいと思います。

ファームウェア書き込み

Arduino IDE のシリアルモニタ等を開いていないか確認してください。ESP-WROOM-32 のシリアルポートを開いているとファームウェア書き込みに失敗します。

  1. Flash Download Tools を起動します。実行ファイルは Flash Download Tools のフォルダの中にある ESPFlashDownloadTool_xxxxxx.exe です (xxxxx はバージョン番号)。
  2. [ESP32 DownloadTool] を選択します。
  3. ESP32 DownloadTool が起動します。
  4. [Download Path Config] でファームウェアとアドレスを指定します。左側にあるチェックボックスにはチェックを入れてください。ファームウェアは ESP-WROOM-32 AT Bin を解凍したフォルダの中にあります。

    ファームウェアファイル アドレス 説明
    bootloader.bin0x1000bootloader フォルダの中
    phy_init_data.bin0xf000
    esp-at.bin0x100000
    partitions_at.bin0x8000
    blank.bin0x10000おそらく必須
  5. [FLASH SIZE] を指定します。ESP-WROOM-32 のフラッシュメモリは 4MB なので 32Mbit を指定します。

  6. COM ポートとボーレートを指定したら [START] ボタンを押してファームウェアを書き込みます。
  7. 書き込みが正常に終了すると、ステータスアイコンが FINISH になります。
  8. ESP-WROOM-32 をリセットまたは電源を切って再投入します。

AT コマンドの使い方

まずはシリアルモニタやターミナルソフトで ESP-WROOM-32 に接続してみましょう。ボーレートは 115200 で改行コードは CR+LF です。

最後までスクロールして、エラーが表示されていなければ AT コマンドが使える...のですが、このまま AT コマンドを入力しても何の反応もありません。実は AT コマンドは UART2 を使う必要があります...つまり、別途 USB<->シリアル変換器が必要となります。

接続は以下のようになります。

USB<->シリアル変換 ESP-WROOM-32
TXDIO16 (UART2: RXD)
RXDIO17 (UART2: TXD)
GNDGND

USB<->シリアル変換のポートで AT[ENTER] と入力してみます (ボーレートは 115200 で改行コードは CR+LF です)。OK が返ってくれば正常動作しています。

AT+GMR[ENTER] でバージョン情報を表示できます。AT コマンドの詳細については以下の資料を参考にしてください。

ビルトイン BASIC が...

Flash Download Tools を使って AT コマンドファームウェアを導入すると、ビルトイン BASIC起動しなくなってしまいますバックアップを書き戻して IO12 をプルアップしてもビルトイン BASIC は起動しません。これはフューズビット CONSOLE_DEBUG_DISABLE が 1 に設定されてしまうからのようです。

C:\ESP32> espefuse.py --port COM14 summary
espefuse.py v2.2-dev
Connecting......
Security fuses:
FLASH_CRYPT_CNT        Flash encryption mode counter                     = 0 R/W (0x0)
FLASH_CRYPT_CONFIG     Flash encryption config (key tweak bits)          = 0 R/W (0x0)
CONSOLE_DEBUG_DISABLE  Disable ROM BASIC interpreter fallback            = 1 R/W (0x1)
ABS_DONE_0             secure boot enabled for bootloader                = 0 R/W (0x0)
ABS_DONE_1             secure boot abstract 1 locked                     = 0 R/W (0x0)
JTAG_DISABLE           Disable JTAG                                      = 0 R/W (0x0)
DISABLE_DL_ENCRYPT     Disable flash encryption in UART bootloader       = 0 R/W (0x0)
DISABLE_DL_DECRYPT     Disable flash decryption in UART bootloader       = 0 R/W (0x0)
DISABLE_DL_CACHE       Disable flash cache in UART bootloader            = 0 R/W (0x0)
BLK1                   Flash encryption key
  = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
BLK2                   Secure boot key
  = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W
BLK3                   Variable Block 3
  = 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 R/W

Efuse fuses:
WR_DIS                 Efuse write disable mask                          = 0 R/W (0x0)
RD_DIS                 Efuse read disablemask                            = 0 R/W (0x0)
CODING_SCHEME          Efuse variable block length scheme                = 0 R/W (0x0)
KEY_STATUS             Usage of efuse block 3 (reserved)                 = 0 R/W (0x0)

Config fuses:
XPD_SDIO_FORCE         Ignore MTDI pin (GPIO12) for VDD_SDIO on reset    = 0 R/W (0x0)
XPD_SDIO_REG           If XPD_SDIO_FORCE, enable VDD_SDIO reg on reset   = 0 R/W (0x0)
XPD_SDIO_TIEH          If XPD_SDIO_FORCE & XPD_SDIO_REG, 1=3.3V 0=1.8V   = 0 R/W (0x0)
SPI_PAD_CONFIG_CLK     Override SD_CLK pad (GPIO6/SPICLK)                = 0 R/W (0x0)
SPI_PAD_CONFIG_Q       Override SD_DATA_0 pad (GPIO7/SPIQ)               = 0 R/W (0x0)
SPI_PAD_CONFIG_D       Override SD_DATA_1 pad (GPIO8/SPID)               = 0 R/W (0x0)
SPI_PAD_CONFIG_HD      Override SD_DATA_2 pad (GPIO9/SPIHD)              = 0 R/W (0x0)
SPI_PAD_CONFIG_CS0     Override SD_CMD pad (GPIO11/SPICS0)               = 0 R/W (0x0)
DISABLE_SDIO_HOST      Disable SDIO host                                 = 0 R/W (0x0)

Identity fuses:
MAC                    MAC Address                                       = xx:xx:xx:xx:xx:xx R/W
CHIP_VERSION           Chip version                                      = 0 R/W (0x0)
CHIP_PACKAGE           Chip package identifier                           = 0 R/W (0x0)

Flash voltage (VDD_SDIO) determined by GPIO12 on reset (High for 1.8V, Low/NC for 3.3V).

...確か ESP32 では ON にしたフューズビットを OFF にする事はできなかったような気が。

See Also:

ビルトイン BASIC も AT コマンドも使いたい

[Flash Download Tools] を使わずに AT コマンドファームを書き込めば、フューズビット CONSOLE_DEBUG_DISABLE は立たないようです。

  1. オリジナルのファームをバックアップする。
  2. ESP-WROOM-32 AT Bin を解凍し、ESP32_AT_BIN というフォルダごと Arduino インストールフォルダ\hardware\espressif\esp32\tools に保存する。
  3. 以下のスクリプトを Flash_AT_Firmware.cmd という名前で Arduino インストールフォルダ\hardware\espressif\esp32\tools に保存する (esptool.exe の行は一行なので注意)。
    @echo off
    SET COM_PORT=COM4
    esptool.exe --chip esp32 --port %COM_PORT% --baud 921600 write_flash 0x1000 ESP32_AT_BIN\bootloader\bootloader.bin 0xf000 ESP32_AT_BIN\phy_init_data.bin 0x100000 ESP32_AT_BIN\esp-at.bin 0x8000 ESP32_AT_BIN\partitions_at.bin 0x10000 ESP32_AT_BIN\blank.bin
  4. Flash_AT_Firmware.cmd を管理者として実行する。

要は "esptool を使って書き込め" という事なのですが、「ビルトイン BASIC なんてどうでもいいやー」という方は気にする必要はありません。



Tips

BLE ライブラリが不正と怒られる

Arduino-ESP32 のインストールフォルダにある libraries\BLE フォルダが空なので、ここに ESP32 BLE for Arduino をインストールする必要があります。

  1. https://github.com/nkolban/ESP32_BLE_Arduino/ から [Clone or download] ボタンを押し、zip アーカイブを取得。
  2. 解凍したアーカイブの中身を <Arduino-ESP32 インストールフォルダ>\libraries\BLE にコピー。
  3. 階層は以下のようになる。

ライブラリマネージャからもインストールできますが、その場合には Arduino-ESP32 のインストールフォルダにある libraries\BLE という空フォルダ (あれば) は削除した方がいいと思います。

将来はどうなるかわかりませんが、現状 (2017/10/15 現在) では上記手順を踏む必要があるようです。


ここにある情報が役に立って、「調べる手間が省けたからオマイに飯でもおごってやるよ」 というハートウォーミングな方がいらっしゃいましたら、下のボタンからどうぞ。

メニュー: