ESP32
Arduino core for the ESP32 リファレンス
・対応無線規格:
WiFi:802.11 b/g/n
Bluetooth v4.2 BLE
・デュアルコア Tensilica LX6
・クロック:80-240MHz
・SRAM(メインメモリ):520KB
・Flashメモリ:4MB ※8MB 16MBモデルもある
・電源電圧:2.2V~3.6V(推奨は3.3V)
・消費電流:平均80mA
・使用温度範囲:-40-85度
・静電容量タッチインターフェース:x10
・32kHzオシレータ:x1
・GPIO:x21
・UART:x3
・SPI:x2
・I2S:x2
・ADC:x16
・DAC:x2
・I2C:x2
・SDIO:マスター/スレーブ
・電源:5V(PCからのバスパワー給電: マイクロUSB-Bメス)
・シリアル⇔USB変換チップ:CP2102(Silicon Laboratories)
・LDO:NCP1117(5V⇒3.3V、1A)
・ピンの仕様:2×19、2.54mmピッチ、1000mil(25.4mm)
標準ピンヘッダ(ピンサイズ0.64×0.64mm)
TXD0、RXD0、IO13、IO15を除くすべてのGPIOが利用可
・GPIO
3.3V動作であり(5Vではない)他のマトリクス機能との衝突を起こす可能性がある点に注意する。
・5V/3.3V/GND
3.3V端子と5V端子があり2種類の電圧が利用可能。GND端子はどこを接続しても全て繋がっています。
また、マイクロUSB端子は5Vで、開発ボードでは5V入力を3.3Vに変換しています。
・ENボタン
常にHIGH状態(3.3V入力)にしておく必要があり内部で3.3Vに配線されています。
ボタンを押すとGNDに接続され本モジュールがリセットされます。
・BOOTボタン
起動時に書き込みモードへ移行する際に使用します。ENボタンと併用する。
従来のD1 Mini ESP8266-12Fと同様のピンレイアウトで、ほとんどのアクセサリーとピン互換性があります。
電源電圧(USB)5V DC
入力/出力電圧 3.3V DC
動作電流最小。 500mA。
CPU Xtensa シングルデュアルコア 32ビット-LX6
RAM 512kB。
I/O ピン 34
ADC チャネル 18
ADC解像度12ビット。
DACチャンネル2。
DAC解像度8ビット。
通信インターフェース SPI、I2C、CAN、UART。
GPIOピン40mAあたりの最大電流消費。
WiFiプロトコル 802.11 b/g/n (802/11n 最大150Mbps)
●Arduino IDEでの開発
1.Arduino IDEをインストール
2.GitHubからArduino Core for the ESP32からボード情報を追加します。
https://github.com/espressif/arduino-esp32
そのページで、下図の様に、Installation Instructions 項目の、Instructions for Boards Managerというリンクを開きます。
ページが飛ぶので、Stable release link のところの URL をコピーします。
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
3.Arduino IDE を起動し、ファイルメニューの環境設定を開きます。
設定タブにて、「追加のボードマネージャーのURL」にコピーしたURLを貼り付けます。OKボタンを押します。
4.ツールメニューのボードからボードマネージャを開きます。
一覧が表示されたら「esp32」を検索しインストールボタンを押します。
5.インストールが完了したら、再度、ツールメニューから以下の項目を選択します。
ボート:"ESP32 Dev Module"
シリアルポート: ※デバイスマネージャで確認
書込装置:"USBasp"
6.書き込み等の確認は、ファイルメニューのスケッチ例から「ESP32」のサンプルを読み込み
コンパイルおよび、書き込みを行う。
購入した直後はスケッチが何も書き込まれていないため、ダウンロードモードにして書き込みをします。
また、書き込まれているスケッチによっては、USBでの通信ができなくなっていることもあり、その場合にもダウンロードモードにて書き込みを行う。
1.USBケーブルを接続して、BOOTボタンを押しながらENボタンを押す。
2.ENボタンを離し、スケッチを書き込みする。
3.正常に書き込みが進んだらBOOTボタンを離す。
1.ArduinoIDEにて書き込み時にesptoolコマンドおよびファイルの情報を確認する。
ArduinoIDEの環境設定にて”より詳細な情報を表示する:”の設定で書き込みにチェックを入れる。
その後、実際に書き込みを行いエディタウィンドウにてesptoolコマンドの内容(一行)をコピーしテキストファイルに保存する。
2.esptoolコマンドの内容より、binファイル(コンパイル後のバイナリデータ)を全てコピーしておく。
ArduinoIDEのスケッチ→コンパイル済みバイナリをエクスポートにてinoと同一フォルダにbinファイルを作成することができる。
3.1で作成したテキストファイルを編集し、2でコピーしたファイルの保存先にパスを変更する。
4.テキストファイルの拡張子を.batにして実行すると書き込みができます。
また、esptool.exeとbinファイルを同一フォルダにコピーして配布することで、IDEの開発環境が無くても書き込み作業ができます。
[ツール]-[Partition Scheme]メニューで設定する。
標準で用意されたパーティションの一例
プリセット プログラム SPIFFS EEPROM OTA
default.csv 1.28MB 1.46MB 4KB 有効
minimal.csv 1.28MB 700KB 4KB 無効
no_ota.csv 2MB 1.98MB 4KB 無効
huge_app.csv 3.07MB 956KB 4KB 無効
min_spiffs.csv 1.92MB 188KB 4KB 有効
●GPIOマトリクス機能
「(物理的な)ピン」「IO MUX(マルチプレクサ)」「GPIO マトリックス」という3つの回路があります。
GPIOピンは再割り当てすることが可能です。基本的に内蔵ペリフェラルのほぼ全てが変更できます。
ただし、以下の制約があります。
・GPIO 0,2 回路的にブートモードの設定に利用
・GPIO 1,3 シリアル通信(UART U0RXD、U0TXD)に利用するため注意
・GPIO 6~11 ESP-WROOM-32モジュール内部では既にFLASHメモリと接続されている
・GPIO 12 内蔵LDOの電圧設定に利用
・GPIO 15 U0TXDピンのデバッグログの設定に利用されることがある
・GPIO 34~39 入力のみ
Ethernet, SDIO, SPI, JTAG, UARTなどの高速信号は、パフォーマンス低下を回避するためにGPIOマトリクスを介さないで接続可能なものがあり、その場合は出力ピンが固定される。
GPIO 種類 アナログ入力 タッチ入力 RTC PULL pinMode初期値
GPIO0 I/O ADC2_CH1 TOUCH1 RTC_GPIO11 ○ PULLUP
GPIO1 I/O ○ PULLUP
GPIO2 I/O ADC2_CH2 TOUCH2 RTC_GPIO12 ○ PULLDOWN
GPIO3 I/O ○ PULLUP
GPIO4 I/O ADC2_CH0 TOUCH0 RTC_GPIO10 ○ PULLDOWN
GPIO5 I/O ○ PULLUP
GPIO6 I/O ○ PULLUP
GPIO7 I/O ○ PULLUP
GPIO8 I/O ○ PULLUP
GPIO9 I/O ○ PULLUP
GPIO10 I/O ○ PULLUP
GPIO11 I/O ○ PULLUP
GPIO12 I/O ADC2_CH5 TOUCH5 RTC_GPIO15 ○ PULLDOWN
GPIO13 I/O ADC2_CH4 TOUCH4 RTC_GPIO14 ○ INPUT
GPIO14 I/O ADC2_CH6 TOUCH6 RTC_GPIO16 ○ INPUT
GPIO15 I/O ADC2_CH3 TOUCH3 RTC_GPIO13 ○ PULLUP
GPIO16 I/O ○ INPUT
GPIO17 I/O ○ INPUT
GPIO18 I/O ○ INPUT
GPIO19 I/O ○ INPUT
GPIO21 I/O ○ INPUT
GPIO22 I/O ○ INPUT
GPIO23 I/O ○ INPUT
GPIO25 I/O ADC2_CH8 RTC_GPIO6 ○
GPIO26 I/O ADC2_CH9 RTC_GPIO7 ○
GPIO27 I/O ADC2_CH7 TOUCH7 RTC_GPIO17 ○ INPUT
GPIO32 I/O ADC1_CH4 TOUCH9 RTC_GPIO9 ○
GPIO33 I/O ADC1_CH5 TOUCH8 RTC_GPIO8 ○
GPIO34 I ADC1_CH6 RTC_GPIO4 ×
GPIO35 I ADC1_CH7 RTC_GPIO5 ×
GPIO36 I ADC1_CH0 RTC_GPIO0 ×
GPIO37 I ADC1_CH1 RTC_GPIO1 ×
GPIO38 I ADC1_CH2 RTC_GPIO2 ×
GPIO39 I ADC1_CH3 RTC_GPIO3 ×
●pinMode()一覧
ピンによって起動時に設定されているモードが違うので、使用するピンは初期化してから使うようにしたほうが安全です。
モード 入力接続
INPUT 入力(LOW=0、HIGH=1)
INPUT_PULLUP 入力(3.3Vに抵抗経由で接続)
INPUT_PULLDOWN 入力(GNDに抵抗経由で接続)
ANALOG 入力(0~4095)
OUTPUT 出力(LOW:0V、HIGH:3.3V)
OUTPUT_OPEN_DRAIN 出力(LOWのときにはGND接続で変わらないが、HIGHのときには3.3Vを出力するのではなく、なにも接続されていないハイインピーダンス状態になります。)
pinMode(4, OUTPUT); // GPIO_4番pinを出力設定
●デジタル入力 digitalRead()
25%の0.825Vより低い電圧の場合LOWになり、75%の2.475Vより高いとHIGHになります。
●デジタル出力 digitalWrite()
LOWの場合には0V、HIGHの場合には3.3Vの電圧を出力します。
LOWの場合には内部でGNDに接続するイメージになり、外部電源からGPIOに接続してLOWすることで、HIGHよりも多くの電流を流すことが可能です。
使用できるGPIOピンは、0~33
digitalWrite(4, HIGH); // GPIO_4番pinをHIGH
digitalWrite(4, LOW); // GPIO_4番pinをLOW
●PWM出力 ledcWrite()
パルス幅変調出力です。電流を周期的にON/OFFすることで出力量を制御します。ArduinoのanalogWrite()と同様の振る舞いをします。
チャンネルが0~15まであり、各チャンネル毎に周波数と分解能を設定して複数ピンへの割り当てが可能。
LEDCには Note / Tone 関係の関数が含まれています。ledcWriteNote() / ledcWriteTone() にて音を鳴らすことができます。
また、通信用のクロックとしても使用できます。
使用できるGPIOピンは、0~33
ledcSetup(0, 12000, 8); // チャンネル設定(channel, Hz, bit)8bitの場合は0~256の範囲で出力できる
ledcAttachPin(4, 0); // GPIO_4番pinをPWMの0チャンネルに設定
ledcWrite(0, 128); // 128/256で 50%の出力
●アナログ出力 dacWrite()
アナログ電圧が直接ピンから出力される。主にスピーカーを鳴らす場合に利用することが多い
出力値は、0~255 ※256ではない
ESP32は2chの8bit DACを内蔵しており、出力ピンはGPIO25,26ピンの位置に固定されています。
使用できるGPIOピンは、25、26
dacWrite(25, 128); // GPIO_25番pinを128/255で 50%の出力
double i=0.0;
void loop() {
dacWrite(25, 128+128*sin(i));
i+=0.01;
}
●アナログ入力(ADC) analogRead()
アナログ入力として0~4095の値が返ってきます。
入力範囲はanalogReadResolution()にて解像度設定でより荒い値に変更することができます。
0は0V、4095は3.3Vに対応していますが、精度はそれほど高くないので注意して利用してください。
ADCに接続されているGPIOでのみアナログ入力が可能です。GPIO32以降であればどんな状況でも利用可能です。無線を利用しない場合にはADC2に接続されている端子でも利用が可能です。
ESP32には逐次比較型(SAR)ADCモジュールが2つ内蔵されています。分解能は9~12bitで、デフォルトは12bitです。
ADC1 には、GPIO32~39に相当するピンと、後述するホールセンサが接続されています。
ADC2 には、それ以外のピンと、deep sleep機能用の入力などが接続されています。
Wi-Fi使用時には ADC2が使えません。つまり、実質 A4 (IO32) ~ A7 (IO35) の 4 本しか使えません。
また、ADCの入力には減衰器を設定することができます。実のところ、ESP32のADCモジュールは0~1 Vの間でAD変換を行っています。
このモジュールに例えば11db(約1/3.6倍)の減衰器を設定することで、0~3.6 Vの間のAD変換ができるようになります。
デフォルトでは11dBの減衰が設定され、12bitでの最大値は3.6 Vを示しています。
また、現在AD変換の結果は少し誤差があるとのことです(?公式スレッド参照)。
他にも議論が見受けられ(?例1,?例2)、状況によって値が変わる可能性がある点に注意したほうが良いでしょう。
このADCの補正に関しては色々議論が進んでいるようです。参考情報として、電源電圧3.31 VでA0ピン(GPIO36)に1.667 Vを入力した時のADCの値は、
1950程度でした。値が4095の時3.50 Vになる計算です。この値も何度かのアップデートで変わっている可能性があります。
setupのブロックでanalogSetAttenuation()関数を呼ぶことで減衰率の設定ができます。
例えば減衰無し(入力電圧範囲 0~1 V)であれば、analogSetAttenuation(ADC_0db);と設定します。詳しくは?このあたりを参照ください。
また、ADC2回路を利用するピンは、今のところWiFi機能と並行して利用できず、常に値が4095になります(?参照)。
将来的に修正するようですが、注意してください。
ADCに使えるピンを以下の表に示します。
GPIO ADC WiFi使用時
0 ADC2_CH1 不可
2 ADC2_CH2 不可
4 ADC2_CH0 不可
12 ADC2_CH5 不可
13 ADC2_CH4 不可
14 ADC2_CH6 不可
15 ADC2_CH3 不可
25 ADC2_CH8 不可
26 ADC2_CH9 不可
27 ADC2_CH7 不可
32 ADC1_CH4
33 ADC1_CH5
34 ADC1_CH6
35 ADC1_CH7
36 ADC1_CH0
37 ADC1_CH1
38 ADC1_CH2
39 ADC1_CH3
Serial.println(analogRead(4)); // GPIO_4番pinからアナログ入力
●Serial (UART)
Serialオブジェクトは、Serial、Serial1、Serial2として定義されており宣言なしに利用可能です。
3系統のハードウエアシリアルを利用可能です。※UART0は、USBポートで使用。
UART0 UART1 UART2
IO1 IO10 IO17 TXD
IO3 IO9 IO16 RXD
IO22 IO11 IO7 RTS
IO19 IO6 IO8 CTS
UART1を使用する場合は、制約上IO6~IO11が使用できないためピンを変更する必要があります。
HardwareSerial mySerial1(1); //UART1 (RX=9, TX=10)
HardwareSerial mySerial2(2); //UART2 (RX=16, TX=17)
void setup() {
mySerial1.begin(115200, SERIAL_8N1, 32, 33); //ピンを変更 (RX=32, TX=33)
mySerial2.begin(115200);
while(!mySerial1); //ポートを開くまでの待ち
Arduinoから機能拡張されている点は下記になります。
また、送受信バッファサイズがデフォルトで256バイトになり、変更も可能で Serial.setRxBufferSize(512); と記述すると512バイトになります。
.begin() UARTを設定します。Serial1.begin(115200, SERIAL_8N1, 32, 33);
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1,
bool invert=false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112);
.readStringUntil() 指定した文字を受信するまで読み込みます。Serial.readStringUntil('\r')
UART2(IO16,IO17)を使った例です。
HardwareSerial Serial1(2);
void setup() {
// initialize both serial ports:
Serial.begin(115200);
Serial1.begin(115200);
}
void loop() {
// read from port 1, send to port 0:
if (Serial1.available()) {
int inByte = Serial1.read();
Serial.write(inByte);
}
// read from port 0, send to port 1:
if (Serial.available()) {
int inByte = Serial.read();
Serial1.write(inByte);
}
}
受信したデータがAsciiの場合は、Serial.write(inByte);とすることで、文字が出力されます。
サンプルの関数Serial.read()は1byteを読み込みします。
また、Serial.avialable()は、取得可能なバイト数を確認できます。
●I2C(Inter-Integrated Circuit)通信
半二重シリアル通信方式です。モーターや温度、湿度センサーなど多くの対応デバイスがあり、それら利用する場合にこの端子を利用します。
I2C0、I2C1の2系統があり、デフォルトでは以下のピンが設定されています。
・I2C0
GPIO 定数
21 SDA
22 SCL
・I2C1 未定義
ArduinoIDEでは、Wire.begin() は引数を持っており、任意のピンに変更ができます。
ピンを指定するときはWire.begin(SDA, SCK);もしくはWire.begin(SDA, SCL, FREQ);というふうに引数を指定します。
FREQはuint32_t型の動作周波数で、標準では100kHzです。
void begin(int sda=-1, int scl=-1, uint32_t frequency=100000);
●SPI(Serial Peripheral Interface)通信
同期式全二重シリアル通信で、I2Cより高速にデータ通信を行うことができ、主にEEPROMやSDカード、各種素子などの扱うデータ容量が大きいところで利用されています。
また、内蔵FLASHとの接続にも利用されているため、IO6~IO11を使ったSPIは利用不可です。
VSPI、HSPIの2系統があり、デフォルトでは以下のピンが設定されています。
GPIO VSPI SPI
18 VSPICLK SCK
19 VSPIQ MISO
23 VSPID MOSI
5 VSPICS0 SS
21 VSPIHD
22 VSPIWP
GPIO HSPI SPI
14 HSPICLK SCK
12 HSPIQ MISO
13 HSPID MOSI
15 HSPICS0 SS
4 HSPIHD
2 HSPIWP
ArduinoIDEでは、SPIClass.begin() は引数を持っており、任意のピンに変更ができます。
void begin(int8_t sck=SCK, int8_t miso=MISO, int8_t mosi=MOSI, int8_t ss=-1);
●Bluetooth
Bluetoothを使用するには、様々なライブラリが提供されており簡単に通信をすることが可能です。
◆BluetoothSerialライブラリ
シリアル通信をBluetooth通信に置き換える仕組みで、通常のUART通信と同じように記述できます。
ホスト側では、ESP32とペアリングをすると仮想シリアルポートが作成されます。
#include "BluetoothSerial.h"
BluetoothSerial SerialBT; //インスタンス化
void setup() {
SerialBT.begin("ESP32Dev"); //第一引数はデバイス名を指定
}
//マスタとしてスレーブに接続する場合
uint8_t MACaddr[6] = {0x40, 0xf5, 0x20, 0x53, 0x12, 0x34}; //接続先スレーブのMACアドレス
void setup() {
SerialBT.begin("ESP32Dev_master" ,true); //第二引数はマスターとして使用する場合にtrue
if(SerialBT.connect(MACaddr)) { //Bluetooth接続
Serial.println("connected");
} else {
while(!SerialBT.connected(10000)) {
Serial.println("No connect");
}
}
if (SerialBT.disconnect()) { //Bluetooth切断
Serial.println("Disconnected Succesfully!");
}
SerialBT.connect(); //Bluetooth再接続
}
◆BLEライブラリ
BLEライブラリーは非常にサイズが大きため、書き込み時のメモリサイズに気を付ける必要があります。
BLE通信は、セントラルとペリフェラルの間で行います。
セントラル:接続の主体となるクライアント側(PCやスマートフォンなど)
ペリフェラル:セントラルの要求を受けるサーバ側(BLEデバイスなど)
手順がかなり複雑なため、サンプルスケッチの BLE_scan、BLE_server などを参考に作成します。
//BLEタグ(ビーコン)受信検索サンプル
#include "BLEDevice.h"
#define DEF_BLE_ADDR "05:B3:EC:xx:xx:xx"
void setup() {
Serial.begin(115200);
BLEDevice::init(""); // BLEモジュールの初期化
pBLEScan = BLEDevice::getScan(); // スキャンオブジェクトを取得
pBLEScan->setActiveScan(false); // パッシブスキャンに設定
}
void loop() {
BLEScanResults foundDevices = pBLEScan->start(10); // 10秒間スキャン
int count = foundDevices.getCount(); // 受信したデバイス数を取得
for(int i = 0; i < count; i++) { // 検出した個数分ループ
BLEAdvertisedDeviced bleDev = foundDevices.getDevice(i);
BLEAddress bleAddr = bleDev.getAddress(); // BLEのMACアドレス取得
std::string bleName = bleDev.getName(); // BLEの名称取得
if(DEF_BLE_ADDR == bleAddr.toString()) { // MACアドレス確認
Serial.printf(("name=[%s]; addr=[%s]", bleName.c_str(), bleAddr.toString().c_str());
Serial.println
}
}
}
●WiFi
様々なライブラリを使うことで多くの機能を実現できます。スケッチ例にあるサンプルで確認できます。
WiFi.begin(ssid, password); //特定のAPへ接続
wifiMulti.run(); //複数のAPを指定できる
WiFiScan(); //アクセスポイントをスキャンする
WiFi.disconnect(true); // WiFi切断 true:Wi-Fi機能OFF false:APへ接続しない
WiFi.mode(WIFI_OFF);
Serial.print("Wifi Connecting");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD); //WiFi接続
if(WiFi.status() == WL_CONNECTED) {
Serial.printf("Connected, IP address: ");
Serial.println(WiFi.localIP());
Flag = true;
break;
} else {
Serial.print('.');
delay(500);
}
●ホールセンサ(磁気センサー) hallRead()
ESP32に内蔵されている磁力センサーです。ESP32に磁石を近づけると値が小さくなるセンサーです。
ホールセンサの出力は、内蔵LNAに接続されている、つまりGPIO36,37(SENSOR_VP,SENSOR_VN)につながっているため、
他の回路とは基本的に排他利用となっています。
void setup() {
Serial.begin(115200);
}
void loop() {
int v = hallRead();
Serial.println(v, DEC);
delay(200);
}
●タッチ入力 touchRead()
静電容量を利用したタッチセンサーです。ピンに一瞬電荷をチャージして、直後にピンの電荷を確認することでタッチの確認をしています。
タッチセンサーとADCは別の回路のため、無線を利用している場合でもADC2に接続されているピンを利用することができます。
タッチセンサとして使える入力を以下に示します。
GPIO 定数
4 T0
0 T1 ←注意
2 T2 ←注意
15 T3 ←注意
13 T4
12 T5
14 T6
27 T7
33 T8 ←注意
32 T9 ←注意
例によってGPIO0,2はブート設定で使われることがあったり、GPIO15はデバッグログの設定ピンだったり、
GPIO32,33はクリスタル用(ESPr 32だと基板裏面に配置)であったりするため、利用するピンには気をつけなれけばいけません。
touchRead(T0) とすることで値が帰ってきます。この値は、ピンに触っているときとそうでないときで大きく異なるので、これを利用してタッチ判定ができます。
●内部温度センサー temperatureRead()
ESP32の内部温度のセンサーです。外気温ではなく内部温度のため高負荷でESP32を利用した場合には上昇していきます。
●Deep Sleepモード
ESP32の動作モードは、アクティブモード、モデムスリープモード、ライトスリープモード、ディープスリープモード、ハイバネーションモード、休止モードがあり
ArduinoIDEで簡単に扱えて効果が大きい停止モードがDeep Sleepになります。
Deep Sleepからもとの状態に戻す(ウェイクアップ)させるには次の方法があります。
・タイマーによるウェイクアップ
esp_deep_sleep(time); //直ちにDeep Sleepに移行しマイクロ秒後にウェイクアップ
esp_sleep_enable_timer_wakeup(time); //スリープ時間をマイクロ秒単位で指定
esp_deep_sleep_start(); //Deep Sleepへ移行し上記で設定した時間後にウェイクアップ
・外部ウェイクアップ
ext0とext1の2種類があります。
esp_sleep_enable_etx0_wakeup(GPIO_NUM_x, level) //指定のGPIOピンが 0:Lowでウェイクアップ、1:Highでウェイクアップ
esp_sleep_enable_etx1_wakeup(bitmask, mode) //複数のRTC GPIOを使用してウェイクアップ
・タッチピンを使ったウェイクアップ
・ULPコプロセッサを使ったウェイクアップ
#include "esp_deep_sleep.h"
void setup() {
// put your setup code here, to run once:
Serial.begin(115200, SERIAL_8N1);
Serial.println("Start");
esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
esp_deep_sleep_pd_config(ESP_PD_DOMAIN_MAX, ESP_PD_OPTION_OFF);
}
void loop() {
// put your main code here, to run repeatedly:
delay(1000);
Serial.println("good night!");
esp_deep_sleep_enable_timer_wakeup(10 * 1000 * 1000); // wakeup(restart) after 10secs
esp_deep_sleep_start();
Serial.println("zzz"); // ここは実行されない
}
●ULPコプロセッサ
低消費電力用にもう一つプロセッサを載せており、これをULPコプロセッサと呼びます。
ただ、ArduinoIDEから利用する分には制約があり、プログラミングもアセンブラで行う必要があります。
●Dual Core(マルチタスク)
デュアルコアを搭載しており、マルチタスクで高速処理が可能です。
ただし、digitalWriteなどのGPIOを制御する場合はほとんど速度は変わりません。
void タスク名(void *pvParameters){
while(1){
任意のプログラム
}
}
void setup(){
xTaskCreatePinnedToCore(タスク名,"タスク名",スタックメモリサイズ,NULL,タスク優先順位,タスクハンドルポインタ,Core ID);
}
void loop(){
}
●SPIFFS(SPI Flash File System)によるファイル操作
ESP32-DevKitC(ESP-WROOM-32)には4MByteのフラッシュメモリが内蔵されていてSPIで接続されています。
このフラッシュメモリをファイルシステムとしてストレージのように利用する事ができます。
SPIFFSは数MByteまで利用できますので、ファイルなどの比較的大きなデータでも保存できます。
一度書き込んだファイルはスケッチを書き換えても消えません。
また、EEPROMも同じフラッシュメモリに保存されます。
設定値など小さなデータはEEPROMを利用する方がよいでしょう。サイズは4KB。
アップロードツールにて、Arudino IDEからファイルを書き込みすることができます。
#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 は便利ですが、秒単位でログを取るような用途には向いていません (フラッシュメモリなので書き換え回数に上限があります)。
●タイマー
ESP-WROOM-32には、64ビットタイマーモジュールが2個あり、それぞれのタイマーモジュールは2個のタイマーを持っています。このため、合計4個のタイマーを利用することができます。
// タイマー設定
#define TimerPeriod 100000 // 割り込み周期(us)100ms
hw_timer_t * timer = NULL;
// タイマー割込みルーチン
void IRAM_ATTR OnTimer() { // IRAM上に格納
++TimerCnt; // 100ms毎にカウントアップ
}
void setup() {
// タイマー
timer = timerBegin(0, 80, true); // タイマー番号、分周比(1us)
timerAttachInterrupt(timer, &OnTimer, true); // 割込み発生時のルーチン指定
timerAlarmWrite(timer, TimerPeriod, true); // 割り込み周期、繰り返し実行(falseの場合は1回のみ)
timerAlarmEnable(timer); // タイマー起動(停止はtimerAlarmDisable())
}
●リセット
ESP.reset(); //ハードリセット(いくつかのレジスタを古い状態のままになる)
ESP.restart(); //再起動(上記よりもクリーンな起動ができる)
●リブートを繰り返し動作しない場合の対処
フラッシュメモリを消去し再度スケッチを書き込みすることで復帰する場合があります。
症状はシリアルモニターで115200bpsに設定した後、ESP32を起動しブートログにて確認をする。
下記のコマンドを実行する。
esptool.exe --chip esp32 --port COM1 --baud 921600 erase_flash
●ビルトイン BASIC
ESP32-WROOM-32 にはビルトイン BASIC が仕込まれています。
ビルトインBASICを起動するには、GPIO12を10kΩ抵抗でプルアップします。
1.GPIO12 と 3V3 を10kΩ抵抗で繋ぐ。
2.USBでPCと接続し、シリアルモニタを115200 bpsで開く。
3.以下のようなメッセージが繰り返し出る ので Enter を入力するとBASIC が起動する。。
(GPIO15をプルダウンしている場合には”OK”のみが繰り返し表示される)
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
>
>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
A$ のような文字列変数は使えません。A-Z の一文字変数 (整数型) のみです。配列変数は実装されていません。
PRINT 文に書式は実装されていません。INPUT 文にプロンプト文は実装されていません。
Arduino 言語にある analogRead() / analogWrite() に相当するステートメント / 関数はありません。
LEDを26ピンにセットしてLチカ
Ctrl+Cでプログラムをストップできる。
>10 iodir 26,1
>20 ioset 26,0
>30 delay 500
>40 ioset 26,1
>50 delay 500
>60 goto 20
>list
10 IODIR 26,1
20 IOSET 26,0
30 DELAY 500
40 IOSET 26,1
50 DELAY 500
60 GOTO 20
OK
>run
break!
OK
>