Espressif Docs Readthedocs Hosted Com Arduino Esp32 en Latest
Espressif Docs Readthedocs Hosted Com Arduino Esp32 en Latest
Release 2.0.6
Espressif
1 Getting Started 3
2 Libraries 33
3 Guides 177
4 Tutorials 191
7 Troubleshooting 229
i
ii
Arduino-ESP32, Release 2.0.6
Here you will find all the relevant information about the project.
Note: This is a work in progress documentation and we will appreciate your help! We are looking for contributors!
CONTENTS: 1
Arduino-ESP32, Release 2.0.6
2 CONTENTS:
CHAPTER
ONE
GETTING STARTED
Welcome to the Arduino ESP32 support documentation! Here you will find important information on how to use the
project.
Note: Before continuing, we must be clear that this project is supported by Espressif Systems and the community.
Everyone is more than welcome to contribute back to this project.
ESP32 is a single 2.4 GHz Wi-Fi-and-Bluetooth SoC (System On a Chip) designed by Espressif Systems.
ESP32 is designed for mobile, wearable electronics, and Internet-of-Things (IoT) applications. It features all the state-
of-the-art characteristics of low-power chips, including fine-grained clock gating, multiple power modes,and dynamic
power scaling. For instance, in a low-power IoT sensor hub application scenario, ESP32 is woken-up periodically and
only when a specified condition is detected. Low-duty cycle is used to minimize the amount of energy that the chip
expends.
The output of the power amplifier is also adjustable, thus contributing to an optimal trade-off between communication
range, data rate and power consumption.
The ESP32 series is available as a chip or module.
3
Arduino-ESP32, Release 2.0.6
This documentation is built on the ESP32 and we are not going to cover the common Arduino API. To see the Arduino
reference documentation, please consider reading the official documentation.
Arduino Official Documentation: Arduino Reference.
Here is the list of supported IDE for Arduino ESP32 support integration.
See Installing Guides for more details on how to install the Arduino ESP32 support.
1.7 Support
This is an open project and it’s supported by the community. Fell free to ask for help in one of the community channels.
1.8 Community
The Arduino community is huge! You can find a lot of useful content on the Internet. Here are some community
channels where you may find information and ask for some help, if needed.
• ESP32 Forum: Official Espressif Forum.
• ESP32 Forum - Arduino: Official Espressif Forum for Arduino related discussions.
• ESP32 Forum - Hardware: Official Espressif Forum for Hardware related discussions.
• Gitter
• Espressif MCUs (Discord)
• ESP32 on Reddit
Here are the first steps to get the Arduino ESP32 support running.
To install Arduino-ESP32, please see the dedicated section on the Installation guide. We recommend you install it
using the boards manager.
1.10.1 Installing
1.7. Support 5
Arduino-ESP32, Release 2.0.6
Before Installing
We recommend you install the support using your favorite IDE, but other options are available depending on your
operating system. To install Arduino-ESP32 support, you can use one of the following options.
This is the way to install Arduino-ESP32 directly from the Arduino IDE.
Note: For overview of SoC’s support, take a look on Supported Soc’s table where you can find if the particular chip
is under stable or development release.
https://espressif.github.io/arduino-esp32/package_esp32_index.json
https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json
Note: Starting with the Arduino IDE version 1.6.4, Arduino allows installation of third-party platform packages using
Boards Manager. We have packages available for Windows, macOS, and Linux.
To start the installation process using the Boards Managaer, follow these steps:
• Install the current upstream Arduino IDE at the 1.8 level or later. The current version is at the arduino.cc website.
• Start Arduino and open the Preferences window.
• Enter one of the release links above into Additional Board Manager URLs field. You can add multiple URLs,
separating them with commas.
• Open Boards Manager from Tools > Board menu and install esp32 platform (and do not forget to select your
ESP32 board from Tools > Board menu after installation).
• Restart Arduino IDE.
PlatformIO is a professional collaborative platform for embedded development. It has out-of-the-box support for ESP32
SoCs and allows working with Arduino ESP32 as well as ESP-IDF from Espressif without changing your development
environment. PlatformIO includes lots of instruments for the most common development tasks such as debugging, unit
testing, and static code analysis.
A detailed overview of the PlatformIO ecosystem and its philosophy can be found in the official documentation.
PlatformIO can be used in two flavors:
• PlatformIO IDE is a toolset for embedded C/C++ development available on Windows, macOS and Linux plat-
forms
• PlatformIO Core (CLI) is a command-line tool that consists of a multi-platform build system, platform and library
managers and other integration components. It can be used with a variety of code development environments
and allows integration with cloud platforms and web services
To install PlatformIO, you can follow this Getting Started, provided at docs.platformio.org.
Note: A detailed overview of supported development boards, examples and frameworks can be found on the official
Espressif32 dev-platform page in the PlatformIO Registry.
The most reliable and easiest way to get started is to use the latest stable version of the ESP32 development platform
that passed all tests/verifications and can be used in production.
Create a new project and select one of the available boards. You can change after by changing the platformio.ini file.
• For ESP32
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
[env:esp32-s2-saola-1]
platform = espressif32
board = esp32-s2-saola-1
framework = arduino
[env:esp32-c3-devkitm-1]
platform = espressif32
board = esp32-c3-devkitm-1
framework = arduino
To test the latest Arduino ESP32, you need to change your project platformio.ini accordingly. The following configu-
ration uses the upstream version of the Espressif development platform and the latest Arduino core directly from the
Espressif GitHub repository:
[env:esp32-c3-devkitm-1]
platform = https://github.com/platformio/platform-espressif32.git
board = esp32-c3-devkitm-1
framework = arduino
platform_packages =
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master
Warning: Arduino ESP32 core v2.x.x cannot be used on Windows 8.x x86 (32 bits), Windows 7 or earlier. The
Windows 32 bits OS is no longer supported by this toolchain.
The Arduino ESP32 v1.0.6 still works on WIN32. You might want to install python 3.8.x because it is the latest
release supported by Windows 7.
• When `get.exe` finishes, you should see the following files in the directory
Step 5
1. Plug your ESP32 board and wait for the drivers to install (or install manually any that might be required)
2. Start Arduino IDE
3. Select your board in Tools > Board menu
4. Select the COM port that the board is attached to
5. Compile and upload (You might need to hold the boot button while uploading)
1. Start Git GUI and you should see the repository under Open Recent Repository. Click on it!
1. From menu Remote select Fetch from > origin
1. Wait for git to pull any changes and close Git GUI
2. Open [ARDUINO_SKETCHBOOK_DIR]/hardware/espressif/esp32/tools and double-click get.exe
Linux
Debian/Ubuntu
cd ~/Arduino/hardware
mkdir -p espressif && \
cd espressif && \
git clone https://github.com/espressif/arduino-esp32.git esp32 && \
cd esp32/tools && \
python3 get.py
Fedora
Note: Command $ sudo dnf -y install arduino will most likely install an older release.
• Open Terminal and execute the following command (copy -> paste and hit enter):
openSUSE
macOS
Where ~/Documents/Arduino represents your sketch book location as per “Arduino” > “Preferences” > “Sketchbook
location” (in the IDE once started). Adjust the command above accordingly.
• If you get the error below, install through the command line dev tools with xcode-select –install and try the
command above again:
xcode-select --install
• Try python3 instead of python if you get the error: IOError: [Errno socket error] [SSL:
TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590) when running
python get.py
• If you get the following error when running python get.py urllib.error.URLError: <urlopen error SSL: CER-
TIFICATE_VERIFY_FAILED, go to Macintosh HD > Applications > Python3.6 folder (or any other python
version), and run the following scripts: Install Certificates.command and Update Shell Profile.command
• Restart Arduino IDE.
1.10.2 Boards
Development Boards
You will need a development board or a custom board with the ESP32 (see Supported SoC’s) to start playing. There
is a bunch of different types and models widely available on the Internet. You need to choose one that covers all your
requirements.
To help you on this selection, we point out some facts about choosing the proper boards to help you to save money and
time.
One ESP32 to rule them all!
One important information that usually bring about some confusion is regarding the different models of the ESP32 SoC
and modules.
The ESP32 is divided by family:
• ESP32
– Wi-Fi and BLE
• ESP32-S
– Wi-Fi only
• ESP32-C
– Wi-Fi and BLE 5
For each family, we have SoC variants with some differentiation. The differences are more about the embedded flash
and its size and the number of the cores (dual or single).
The modules use the SoC internally, including the external flash, PSRAM (in some models) and other essential elec-
tronic components. Essentially, all modules from the same family use the same SoC.
For example:
The SoC partnumber is the ESP32-D0WD-V3 and it’s the same SoC used inside of the ESP32-WROVER (with
PSRAM) and ESP32-WROOM modules. This means that the same characteristics are present in both modules’ core.
For more detailed information regarding the SoC’s and modules, see the Espressif Product Selector.
Now that you know that the module can be different but the heart is the same, you can choose your development board.
Before buying: Keep in mind that for some “must have” features when choosing the best board for your needs:
• Embedded USB-to-Serial
– This is very convenient for programming and monitoring the logs with the terminal via USB.
• Breadboard friendly
– If you are prototyping, this will be very useful to connect your board directly on the breadboard.
• open-source/open-hardware
– Check if the schematics are available for download. This helps a lot on prototyping.
• Support
– Some of the manufacturers offer a very good level of support, with examples and demo projects.
Espressif
ESP32-DevKitC-1
The ESP32-DevKitC-1 development board is one of Espressif’s official boards. This board is based on the ESP32-
WROVER-E module, with the ESP32 as the core.
Specifications
Header Block
Note: Not all of the chip pins are exposed to the pin headers.
J1
J3
Pin Layout
Strapping Pins
Some of the GPIO’s have important features during the booting process. Here is the list of the strapping pins on the
ESP32.
Some of the GPIO’s are used for the external flash and PSRAM. These GPIO’s cannot be used:
Other GPIO’s are INPUT ONLY and cannot be used as output pin:
GPIO Function
IO34 GPIO34, ADC1_CH6, VDET_1
IO35 GPIO35, ADC1_CH7, VDET_2
IO36 GPIO36, ADC1_CH0, S_VP
IO39 GPIO39, ADC1_CH3, S_VN
Resources
• ESP32 (Datasheet)
• ESP32-WROVER-E (Datasheet)
• ESP32-DevKitC (Schematic)
ESP32-S2-Saola-1
The ESP32-S2-Saola-1 development board is one of Espressif’s official boards. This board is based on the ESP32-S2-
WROVER module, with the ESP32-S2 as the core.
Specifications
– 1 × I2S
– 2 × I2C
– 2 × UART
– RMT (TX/RX)
– LED PWM controller, up to 8 channels
– 1 × full-speed USB OTG
– 1 × temperature sensor
– 1 × DVP 8/16 camera interface, implemented using the hardware resources of I2S
– 1 × LCD interface (8-bit serial RGB/8080/6800), implemented using the hardware resources of SPI2
– 1 × LCD interface (8/16/24-bit parallel), implemented using the hardware resources of I2S
– 1 × TWAI® controller (compatible with ISO 11898-1)
• Onboard PCB antenna or external antenna connector
Header Block
Note: Not all of the chip pins are exposed to the pin headers.
J2
J3
Pin Layout
Strapping Pins
Some of the GPIO’s have important features during the booting process. Here is the list of the strapping pins on the
ESP32-S2.
Some of the GPIO’s are used for the external flash and PSRAM. These GPIO’s cannot be used:
Other GPIO’s are INPUT ONLY and cannot be used as output pin:
GPIO Function
IO46 GPIO46
Resources
• ESP32-S2 (Datasheet)
• ESP32-S2-WROVER (Datasheet)
• ESP32-S2-Saola-1 (Schematics)
ESP32-C3-DevKitM-1
The ESP32-C3-DevKitM-1 development board is one of Espressif’s official boards. This board is based on the ESP32-
C3-MINI-1 module, with the ESP32-C3 as the core.
Specifications
• Small sized 2.4 GHz WiFi (802.11 b/g/n) and Bluetooth® 5 module
• Built around ESP32C3 series of SoCs, RISCV singlecore microprocessor
• 4 MB flash in chip package
• 15 available GPIOs (module)
• Peripherals
– 22 × programmable GPIOs
– Digital interfaces:
– 3 × SPI
– 2 × UART
– 1 × I2C
– 1 × I2S
– Remote control peripheral, with 2 transmit channels and 2 receive channels
– LED PWM controller, with up to 6 channels
– Full-speed USB Serial/JTAG controller
– General DMA controller (GDMA), with 3 transmit channels and 3 receive channels
– 1 × TWAI® controller (compatible with ISO 11898-1)
– Analog interfaces:
∗ 2 × 12-bit SAR ADCs, up to 6 channels
∗ 1 × temperature sensor
– Timers:
∗ 2 × 54-bit general-purpose timers
∗ 3 × watchdog timers
∗ 1 × 52-bit system timer
• Onboard PCB antenna or external antenna connector
Header Block
Note: Not all of the chip pins are exposed to the pin headers.
J1
J3
Pin Layout
Strapping Pins
Some of the GPIO’s have important features during the booting process. Here is the list of the strapping pins on the
ESP32-C3.
Resources
• ESP32-C3 (Datasheet)
• ESP32-C3-MINI-1 (Datasheet)
Third Party
Note: All the information must be provided by the vendor. If your favorite board is not here, consider creating an
issue on GitHub and directly link/mention the vendor in the issue description.
LOLIN
•
•
Generic Vendor
Specifications
Header Block
Header1
Pin Layout
Datasheet
• ESP32 (Datasheet)
• ESP32-S2 (Datasheet)
• ESP32-C3 (Datasheet)
• ESP32-S3 (Datasheet)
Note: Create one file per board or one file with multiple boards. Do not add board information/description
on this file.
Datasheet
• ESP32 (Datasheet)
• ESP32-S2 (Datasheet)
• ESP32-C3 (Datasheet)
• ESP32-S3 (Datasheet)
Resources
1.11 Examples
After installing the toolchain into your environment, you will be able to see all the dedicated examples for the ESP32.
These examples are located in the examples menu or inside each library folder.
https://github.com/espressif/arduino-esp32/tree/master/libraries
There is also a list of examples managed outside of Espressif, so check them out.
1.12 Datasheet
• ESP32 (Datasheet)
• ESP32-S2 (Datasheet)
• ESP32-C3 (Datasheet)
• ESP32-S3 (Datasheet)
1.11. Examples 31
Arduino-ESP32, Release 2.0.6
1.13 Resources
TWO
LIBRARIES
Currently, the Arduino ESP32 supports the following peripherals with Arduino APIs.
33
Arduino-ESP32, Release 2.0.6
2.1.1 Notes
(*) SPI Ethernet is supported by all ESP32 families and RMII only for ESP32.
Note: Some peripherals are not available for all ESP32 families. To see more details about it, see the corresponding
SoC at Product Selector page.
34 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
2.2 Datasheet
• ESP32 (Datasheet)
• ESP32-S2 (Datasheet)
• ESP32-C3 (Datasheet)
• ESP32-S3 (Datasheet)
2.3 APIs
The Arduino ESP32 offers some unique APIs, described in this section:
2.3.1 ADC
About
ADC (analog to digital converter) is a very common peripheral used to convert an analog signal such as voltage to a
digital form so that it can be read and processed by a microcontroller.
ADCs are very useful in control and monitoring applications since most sensors (e.g., temperature, pressure, force)
produce analogue output voltages.
Note: Each SoC or module has a different number of ADC’s with a different number of channels and pins availible.
Refer to datasheet of each board for more info.
analogRead
This function is used to get the ADC raw value for a given pin/ADC channel.
2.2. Datasheet 35
Arduino-ESP32, Release 2.0.6
analogReadMillivolts
This function is used to get ADC value for a given pin/ADC channel in millivolts.
analogReadResolution
This function is used to set the resolution of analogRead return value. Default is 12 bits (range from 0 to 4096) for
all chips except ESP32S3 where default is 13 bits (range from 0 to 8192). When different resolution is set, the values
read will be shifted to match the given resolution.
Range is 1 - 16 .The default value will be used, if this function is not used.
Note: For the ESP32, the resolution is between 9 to12 and it will change the ADC hardware resolution. Else value
will be shifted.
analogSetClockDiv
This function is used to set the divider for the ADC clock.
Range is 1 - 255. Default value is 1.
analogSetAttenuation
36 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
ESP32-S2
ESP32-C3
ESP32-S3
analogSetPinAttenuation
This function is used to set the attenuation for a specific pin/ADC channel. For more information refer to analogSetAt-
tenuation.
adcAttachPin
This function is used to attach the pin to ADC (it will also clear any other analog mode that could be on)
This function will return true if configuration is successful. Else returns false.
2.3. APIs 37
Arduino-ESP32, Release 2.0.6
analogSetWidth
This function is used to set the hardware sample bits and read resolution. Default is 12bit (0 - 4095). Range is 9 - 12.
analogSetVRefPin
This function is used to set pin to use for ADC calibration if the esp is not already calibrated (pins 25, 26 or 27).
hallRead
This function is used to get the ADC value of the HALL sensor conneted to pins 36(SVP) and 39(SVN).
int hallRead();
Example Applications
void setup() {
// initialize serial communication at 115200 bits per second:
Serial.begin(115200);
void loop() {
// read the analog / millivolts value for pin 2:
int analogValue = analogRead(2);
int analogVolts = analogReadMilliVolts(2);
38 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
2.3.2 BLE
About
Note: This is a work in progress project and this section is still missing. If you want to contribute, please see the
Contributions Guide.
Examples
BLE Scan
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/
˓→ master/cpp_utils/tests/BLE%20Tests/SampleScan.cpp
Ported to Arduino ESP32 by Evandro Copercini
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop() {
// put your main code here, to run repeatedly:
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
(continues on next page)
2.3. APIs 39
Arduino-ESP32, Release 2.0.6
BLE UART
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/
˓→master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Create a BLE server that, once we receive a connection, will send periodic␣
˓→notifications.
The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving␣
˓→data with "WRITE"
In this example rxValue is the data received (only accessible inside that function).
And txValue is the data to be sent, in this example just a byte incremented every␣
˓→second.
*/
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
40 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++)
Serial.print(rxValue[i]);
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
Serial.begin(115200);
2.3. APIs 41
Arduino-ESP32, Release 2.0.6
pRxCharacteristic->setCallbacks(new MyCallbacks());
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
void loop() {
if (deviceConnected) {
pTxCharacteristic->setValue(&txValue, 1);
pTxCharacteristic->notify();
txValue++;
delay(10); // bluetooth stack will go into congestion, if too many␣
˓→packets are sent
// disconnecting
if (!deviceConnected && oldDeviceConnected) {
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
Serial.println("start advertising");
oldDeviceConnected = deviceConnected;
}
// connecting
if (deviceConnected && !oldDeviceConnected) {
// do stuff here on connecting
oldDeviceConnected = deviceConnected;
}
}
42 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
2.3.3 Bluetooth
About
Note: This is a work in progress project and this section is still missing. If you want to contribute, please see the
Contributions Guide.
Examples
Serial To Serial BT
//This example code is in the Public Domain (or CC0 licensed, at your option.)
//By Evandro Copercini - 2018
//
//This example creates a bridge between Serial and Classical Bluetooth (SPP)
//and also demonstrate that SerialBT have the same functionalities of a normal Serial
#include "BluetoothSerial.h"
//#define USE_PIN // Uncomment this to use PIN during pairing. The pin is specified on␣
˓→the line below
#if !defined(CONFIG_BT_SPP_ENABLED)
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32␣
˓→chip.
#endif
BluetoothSerial SerialBT;
void setup() {
Serial.begin(115200);
SerialBT.begin(device_name); //Bluetooth device name
Serial.printf("The device with name \"%s\" is started.\nNow you can pair it with␣
˓→Bluetooth!\n", device_name.c_str());
//Serial.printf("The device with name \"%s\" and MAC address %s is started.\nNow you␣
˓→can pair it with Bluetooth!\n", device_name.c_str(), SerialBT.getMacString()); // Use␣
#ifdef USE_PIN
SerialBT.setPin(pin);
Serial.println("Using PIN");
(continues on next page)
2.3. APIs 43
Arduino-ESP32, Release 2.0.6
void loop() {
if (Serial.available()) {
SerialBT.write(Serial.read());
}
if (SerialBT.available()) {
Serial.write(SerialBT.read());
}
delay(20);
}
#include <BluetoothSerial.h>
#if !defined(CONFIG_BT_SPP_ENABLED)
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32␣
˓→chip.
#endif
BluetoothSerial SerialBT;
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP32test"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
if (btScanAsync) {
Serial.print("Starting discoverAsync...");
if (SerialBT.discoverAsync(btAdvertisedDeviceFound)) {
(continues on next page)
44 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
if (btScanSync) {
Serial.println("Starting discover...");
BTScanResults *pResults = SerialBT.discover(BT_DISCOVER_TIME);
if (pResults)
pResults->dump(&Serial);
else
Serial.println("Error on BT Scan, no result!");
}
}
void loop() {
delay(100);
}
2.3.4 DAC
About
DAC (digital to analog converter) is a very common peripheral used to convert a digital signal to an analog form.
ESP32 and ESP32-S2 have two 8-bit DAC channels. The DAC driver allows these channels to be set to arbitrary
voltages.
DACs can be used for generating a specific (and dynamic) reference voltage for external sensors, controlling transistors,
etc.
2.3. APIs 45
Arduino-ESP32, Release 2.0.6
dacWrite
This function is used to set the DAC value for a given pin/DAC channel.
dacDisable
About
Note: This is a work in progress project and this section is still missing. If you want to contribute, please see the
Contributions Guide.
Examples
ExternalWakeUp
/*
Deep Sleep with External Wake Up
=====================================
This code displays how to use deep sleep with
an external trigger as a wake up source and how
to store data in RTC memory to use it over reboots
Hardware Connections
======================
Push Button to GPIO 33 pulled down with a 10K Ohm
resistor
NOTE:
(continues on next page)
46 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/
/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using␣
˓→RTC_IO"); break;
}
}
void setup(){
Serial.begin(115200);
delay(1000); //Take some time to open up the Serial Monitor
/*
First we configure the wake up source
We set our ESP32 to wake up for an external trigger.
There are two types for ESP32, ext0 and ext1 .
ext0 uses RTC_IO to wakeup thus requires RTC peripherals
to be on while ext1 uses RTC Controller so doesnt need
(continues on next page)
2.3. APIs 47
Arduino-ESP32, Release 2.0.6
void loop(){
//This is not going to be called
}
Timer Wake Up
/*
Simple Deep Sleep with Timer Wake Up
=====================================
ESP32 offers a deep sleep mode for effective power
saving as power is an important factor for IoT
applications. In this mode CPUs, most of the RAM,
and all the digital peripherals which are clocked
from APB_CLK are powered off. The only parts of
the chip which can still be powered on are:
RTC controller, RTC peripherals ,and RTC memories
Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/
/*
Method to print the reason by which ESP32
has been awaken from sleep
(continues on next page)
48 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using␣
˓→RTC_IO"); break;
}
}
void setup(){
Serial.begin(115200);
delay(1000); //Take some time to open up the Serial Monitor
/*
First we configure the wake up source
We set our ESP32 to wake up every 5 seconds
*/
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
" Seconds");
/*
Next we decide what all peripherals to shut down/keep on
By default, ESP32 will automatically power down the peripherals
not needed by the wakeup source, but if you want to be a poweruser
this is for you. Read in detail at the API docs
http://esp-idf.readthedocs.io/en/latest/api-reference/system/deep_sleep.html
Left the line commented as an example of how to configure peripherals.
The line below turns off all RTC peripherals in deep sleep.
*/
//esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
//Serial.println("Configured all RTC Peripherals to be powered down in sleep");
/*
(continues on next page)
2.3. APIs 49
Arduino-ESP32, Release 2.0.6
void loop(){
//This is not going to be called
}
2.3.6 ESP-NOW
ESP-NOW is a fast, connectionless communication technology featuring a short packet transmission. ESP-NOW is
ideal for smart lights, remote control devices, sensors and other applications.
Note: This is a work in progress project and this section is still missing. If you want to contribute, please see the
Contributions Guide.
Examples
ESP-NOW Master
/**
ESPNOW - Basic communication - Master
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32
Description: This sketch consists of the code for the Master module.
Resources: (A bit outdated)
a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
b. http://www.esploradores.com/practica-6-conexion-esp-now/
Flow: Master
Step 1 : ESPNow Init on Master and set it in STA mode
Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID␣
˓→of slave for an easy setup)
50 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
Flow: Slave
Step 1 : ESPNow Init on Slave
Step 2 : Update the SSID of Slave with a prefix of `slave`
Step 3 : Set Slave in AP mode
Step 4 : Register for receive callback and wait for data
Step 5 : Once data arrives, print it in the serial monitor
Note: Master and Slave have been defined to easily understand the setup.
Based on the ESPNOW API, there is no concept of Master and Slave.
Any devices can act as master or salve.
*/
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h> // only for esp_wifi_set_channel()
Serial.println("");
if (scanResults == 0) {
Serial.println("No WiFi devices in AP Mode found");
} else {
Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
for (int i = 0; i < scanResults; ++i) {
(continues on next page)
2.3. APIs 51
Arduino-ESP32, Release 2.0.6
if (PRINTSCANRESULTS) {
Serial.print(i + 1);
Serial.print(": ");
Serial.print(SSID);
Serial.print(" (");
Serial.print(RSSI);
Serial.print(")");
Serial.println("");
}
delay(10);
// Check if the current device starts with `Slave`
if (SSID.indexOf("Slave") == 0) {
// SSID of interest
Serial.println("Found a Slave.");
Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" [");␣
˓→Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI);␣
˓→Serial.print(")"); Serial.println("");
slaveFound = 1;
// we are planning to have only one slave in this example;
// Hence, break after we find one, to be a bit efficient
break;
}
}
}
if (slaveFound) {
Serial.println("Slave Found, processing..");
} else {
Serial.println("Slave Not Found, trying again.");
}
// clean up ram
WiFi.scanDelete();
}
52 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
void deletePeer() {
esp_err_t delStatus = esp_now_del_peer(slave.peer_addr);
(continues on next page)
2.3. APIs 53
Arduino-ESP32, Release 2.0.6
uint8_t data = 0;
// send data
void sendData() {
data++;
const uint8_t *peer_addr = slave.peer_addr;
Serial.print("Sending: "); Serial.println(data);
esp_err_t result = esp_now_send(peer_addr, &data, sizeof(data));
Serial.print("Send Status: ");
if (result == ESP_OK) {
Serial.println("Success");
} else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW not Init.");
} else if (result == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
} else if (result == ESP_ERR_ESPNOW_INTERNAL) {
Serial.println("Internal Error");
} else if (result == ESP_ERR_ESPNOW_NO_MEM) {
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
} else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
Serial.println("Peer not found.");
} else {
Serial.println("Not sure what happened");
}
}
54 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
void loop() {
// In the loop we scan for slave
ScanForSlave();
// If Slave is found, it would be populate in `slave` variable
// We will check if `slave` is defined and then we proceed further
if (slave.channel == CHANNEL) { // check if slave channel is defined
// `slave` is defined
// Add slave as peer if it has not been added already
bool isPaired = manageSlave();
if (isPaired) {
// pair success or already paired
// Send data to device
sendData();
} else {
// slave pair failed
Serial.println("Slave pair failed!");
}
}
else {
// No slave found to process
}
2.3. APIs 55
Arduino-ESP32, Release 2.0.6
ESP-NOW Slave
/**
ESPNOW - Basic communication - Slave
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32
Description: This sketch consists of the code for the Slave module.
Resources: (A bit outdated)
a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
b. http://www.esploradores.com/practica-6-conexion-esp-now/
Flow: Master
Step 1 : ESPNow Init on Master and set it in STA mode
Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID␣
˓→of slave for an easy setup)
Flow: Slave
Step 1 : ESPNow Init on Slave
Step 2 : Update the SSID of Slave with a prefix of `slave`
Step 3 : Set Slave in AP mode
Step 4 : Register for receive callback and wait for data
Step 5 : Once data arrives, print it in the serial monitor
Note: Master and Slave have been defined to easily understand the setup.
Based on the ESPNOW API, there is no concept of Master and Slave.
Any devices can act as master or salve.
*/
#include <esp_now.h>
#include <WiFi.h>
#define CHANNEL 1
56 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
// config AP SSID
void configDeviceAP() {
const char *SSID = "Slave_1";
bool result = WiFi.softAP(SSID, "Slave_1_Password", CHANNEL, 0);
if (!result) {
Serial.println("AP Config failed.");
} else {
Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID));
Serial.print("AP CHANNEL "); Serial.println(WiFi.channel());
}
}
void setup() {
Serial.begin(115200);
Serial.println("ESPNow/Basic/Slave Example");
//Set device in AP mode to begin with
WiFi.mode(WIFI_AP);
// configure device AP mode
configDeviceAP();
// This is the mac address of the Slave in AP Mode
Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress());
// Init ESPNow with a fallback logic
InitESPNow();
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info.
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
// Chill
}
2.3. APIs 57
Arduino-ESP32, Release 2.0.6
Resources
2.3.7 Ethernet
About
Note: This is a work in progress project and this section is still missing. If you want to contribute, please see the
Contributions Guide.
Examples
LAN8720
/*
This sketch shows the Ethernet event usage
*/
#include <ETH.h>
58 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
WiFiClient client;
if (!client.connect(host, port)) {
Serial.println("connection failed");
return;
}
client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
while (client.connected() && !client.available());
while (client.available()) {
Serial.write(client.read());
}
Serial.println("closing connection\n");
client.stop();
}
void setup()
{
Serial.begin(115200);
WiFi.onEvent(WiFiEvent);
ETH.begin();
}
void loop()
{
if (eth_connected) {
testClient("google.com", 80);
}
delay(10000);
}
2.3. APIs 59
Arduino-ESP32, Release 2.0.6
TLK110
/*
This sketch shows the Ethernet event usage
*/
#include <ETH.h>
#define ETH_ADDR 31
#define ETH_POWER_PIN 17
#define ETH_MDC_PIN 23
#define ETH_MDIO_PIN 18
#define ETH_TYPE ETH_PHY_TLK110
60 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
WiFiClient client;
if (!client.connect(host, port)) {
Serial.println("connection failed");
return;
}
client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
while (client.connected() && !client.available());
while (client.available()) {
Serial.write(client.read());
}
Serial.println("closing connection\n");
client.stop();
}
void setup()
{
Serial.begin(115200);
WiFi.onEvent(WiFiEvent);
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE);
}
void loop()
{
if (eth_connected) {
testClient("google.com", 80);
}
delay(10000);
}
2.3.8 GPIO
About
One of the most used and versatile peripheral in a microcontroller is the GPIO. The GPIO is commonly used to write
and read the pin state.
GPIO stands to General Purpose Input Output, and is responsible to control or read the state of a specific pin in the
digital world. For example, this peripheral is widely used to create the LED blinking or to read a simple button.
Note: There are some GPIOs with special restrictions, and not all GPIOs are accessible through the developemnt
2.3. APIs 61
Arduino-ESP32, Release 2.0.6
board. For more information about it, see the corresponding board pin layout information.
GPIOs Modes
GPIO API
pinMode
The pinMode function is used to define the GPIO operation mode for a specific pin.
The ESP32 SoC families supports the internal pullup and pulldown throught a 45kR resistor, that can be enabled when
configuring the GPIO mode as INPUT mode. If the pullup or pulldown mode is not defined, the pin will stay in the high
impedance mode.
62 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
digitalWrite
The function digitalWrite sets the state of the selected GPIO to HIGH or LOW. This function is only used if the
pinMode was configured as OUTPUT.
digitalRead
To read the state of a given pin configured as INPUT, the function digitalRead is used.
Interrupts
attachInterrupt
The function attachInterrupt is used to attach the interrupt to the defined pin.
2.3. APIs 63
Arduino-ESP32, Release 2.0.6
attachInterruptArg
The function attachInterruptArg is used to attach the interrupt to the defined pin using arguments.
detachInterrupt
To detach the interruption from a specific pin, use the detachInterrupt function giving the GPIO to be detached.
detachInterrupt(uint8_t pin);
Example Code
#define LED 12
#define BUTTON 2
uint8_t stateLED = 0;
void setup() {
pinMode(LED, OUTPUT);
pinMode(BUTTON,INPUT_PULLUP);
}
void loop() {
if(!digitalRead(BUTTON)){
stateLED = stateLED^1;
digitalWrite(LED,stateLED);
}
}
64 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
GPIO Interrupt
#include <Arduino.h>
struct Button {
const uint8_t PIN;
uint32_t numberKeyPresses;
bool pressed;
};
void setup() {
Serial.begin(115200);
pinMode(button1.PIN, INPUT_PULLUP);
attachInterruptArg(button1.PIN, isr, &button1, FALLING);
pinMode(button2.PIN, INPUT_PULLUP);
attachInterrupt(button2.PIN, isr, FALLING);
}
void loop() {
if (button1.pressed) {
Serial.printf("Button 1 has been pressed %u times\n", button1.numberKeyPresses);
button1.pressed = false;
}
if (button2.pressed) {
Serial.printf("Button 2 has been pressed %u times\n", button2.numberKeyPresses);
button2.pressed = false;
}
static uint32_t lastMillis = 0;
if (millis() - lastMillis > 10000) {
lastMillis = millis();
detachInterrupt(button1.PIN);
}
}
2.3. APIs 65
Arduino-ESP32, Release 2.0.6
About
Note: This is a work in progress project and this section is still missing. If you want to contribute, please see the
Contributions Guide.
Example
Hall Sensor
//Simple sketch to access the internal hall effect detector on the esp32.
//values can be quite low.
//Brian Degger / @sctv
int val = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
val = hallRead();
// print the results to the serial monitor:
//Serial.print("sensor = ");
Serial.println(val);//to graph
}
2.3.10 I2C
About
I2C (Inter-Integrated Circuit) / TWI (Two-wire Interface) is a widely used serial communication to connect devices in
a short distance. This is one of the most common peripherals used to connect sensors, EEPROMs, RTC, ADC, DAC,
displays, OLED, and many other devices and microcontrollers.
This serial communication is considered as a low-speed bus, and multiple devices can be connected on the same two-
wires bus, each with a unique 7-bits address (up to 128 devices). These two wires are called SDA (serial data line) and
SCL (serial clock line).
Note: The SDA and SCL lines require pull-up resistors. See the device datasheet for more details about the resistors’
values and the operating voltage.
66 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
I2C Modes
2.3. APIs 67
Arduino-ESP32, Release 2.0.6
The ESP32 I2C library is based on the Arduino Wire Library and implements a few more APIs, described in this
documentation.
Here are the common functions used for master and slave modes.
begin
This function is used to start the peripheral using the default configuration.
bool begin();
This function will return true if the peripheral was initialized correctly.
setPins
Note: Call this function before begin to change the pins from the default ones.
• sdaPin sets the GPIO to be used as the I2C peripheral data line.
• sclPin sets the GPIO to be used as the I2C peripheral clock line.
The default pins may vary from board to board. On the Generic ESP32 the default I2C pins are:
• sdaPin GPIO21
• sclPin GPIO22
This function will return true if the peripheral was configured correctly.
setClock
Use this function to set the bus clock. The default value will be used if this function is not used.
68 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
getClock
uint32_t getClock();
setTimeOut
Set the bus timeout given in milliseconds. The default value is 50ms.
getTimeOut
uint16_t getTimeOut();
write
size_t write(uint8_t);
or
The return will be the size of the data added to the buffer.
end
This function will finish the communication and release all the allocated resources. After calling end you need to use
begin again in order to initialize the I2C driver again.
bool end();
2.3. APIs 69
Arduino-ESP32, Release 2.0.6
Basic Usage
To start using I2C master mode on the Arduino, the first step is to include the Wire.h header to the sketch.
#include "Wire.h"
Wire.begin();
By using begin without any arguments, all the settings will be done by using the default values. To set the values by
your own, see the function description. This function is described here: i2c begin
After calling begin, we can start the transmission by calling beginTransmission and passing the I2C slave address:
Wire.beginTransmission(I2C_DEV_ADDR);
Wire.write(x);
You can pass different data types using write function. This function is described here: i2c write
Note: The write function does not write directly to the slave device but adds to the I2C buffer. To do so, you need to
use the endTransmission function to send the buffered bytes to the slave device.
Wire.endTransmission(true);
After calling endTransmission, the data stored in the I2C buffer will be transmitted to the slave device.
Now you can request a reading from the slave device. The requestFrom will ask for a readout to the selected device
by giving the address and the size.
Wire.requestFrom(I2C_DEV_ADDR, SIZE);
Wire.readBytes(temp, error);
Here are the I2C master APIs. These function are intended to be used only for master mode.
70 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
begin
In master mode, the begin function can be used by passing the pins and bus frequency. Use this function only for the
master mode.
Alternatively, you can use the begin function without any argument to use all default values.
This function will return true if the peripheral was initialized correctly.
beginTransmission
This function is used to star a communication process with the slave device. Call this function by passing the slave
address before writing the message to the buffer.
endTransmission
After writing to the buffer using i2c write, use the function endTransmission to send the message to the slave device
address defined on the beginTransmission function.
• sendStop enables (true) or disables (false) the stop signal (only used in master mode).
Calling the this function without sendStop is equivalent to sendStop = true.
uint8_t endTransmission(void);
requestFrom
2.3. APIs 71
Arduino-ESP32, Release 2.0.6
#include "Wire.h"
uint32_t i = 0;
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Wire.begin();
}
void loop() {
delay(5000);
Basic Usage
To start using I2C as slave mode on the Arduino, the first step is to include the Wire.h header to the scketch.
#include "Wire.h"
Before calling begin we must create two callback functions to handle the communication with the master device.
Wire.onReceive(onReceive);
and
72 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
Wire.onRequest(onRequest);
The onReceive will handle the request from the master device uppon a slave read request and the onRequest will
handle the answer to the master.
Now, we can start the peripheral configuration by calling begin function with the device address.
Wire.begin((uint8_t)I2C_DEV_ADDR);
By using begin without any arguments, all the settings will be done by using the default values. To set the values by
your own, see the function description. This function is described here: i2c begin
For ESP32 only!
Use the function slaveWrite in order to pre-write to the slave response buffer. This is used only for the ESP32 in
order to add the slave capability on the chip and keep compatability with Arduino.
Here are the I2C slave APIs. These function are intended to be used only for slave mode.
begin
In slave mode, the begin function must be used by passing the slave address. You can also define the pins and the
bus frequency.
This function will return true if the peripheral was initialized correctly.
onReceive
The onReceive function is used to define the callback for the data received from the master.
onRequest
The onRequest function is used to define the callback for the data to be send to the master.
2.3. APIs 73
Arduino-ESP32, Release 2.0.6
slaveWrite
The slaveWrite function writes on the slave response buffer before receiving the response message. This function is
only used for adding the slave compatability for the ESP32.
Warning: This function is only required for the ESP32. You don’t need to use for ESP32-S2 and ESP32-C3.
#include "Wire.h"
uint32_t i = 0;
void onRequest(){
Wire.print(i++);
Wire.print(" Packets.");
Serial.println("onRequest");
}
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Wire.onReceive(onReceive);
Wire.onRequest(onRequest);
Wire.begin((uint8_t)I2C_DEV_ADDR);
#if CONFIG_IDF_TARGET_ESP32
char message[64];
snprintf(message, 64, "%u Packets.", i++);
Wire.slaveWrite((uint8_t *)message, strlen(message));
#endif
}
void loop() {
74 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
2.3.11 I2S
About
I2S - Inter-IC Sound, correctly written I2 S pronounced “eye-squared-ess”, alternative notation is IIS. I2 S is an electrical
serial bus interface standard used for connecting digital audio devices together.
It is used to communicate PCM (Pulse-Code Modulation) audio data between integrated circuits in an electronic device.
The I2 S bus separates clock and serial data signals, resulting in simpler receivers than those required for asynchronous
communications systems that need to recover the clock from the data stream.
Despite the similar name, I2 S is unrelated and incompatible with the bidirectional I2 C (IIC) bus.
The I2 S bus consists of at least three lines:
Note: All lines can be attached to almost any pin and this change can occur even during operation.
I2S Modes
Note: Officially supported operation mode is only I2S_PHILIPS_MODE. Other modes are implemented, but we cannot
guarantee flawless execution and behavior.
2.3. APIs 75
Arduino-ESP32, Release 2.0.6
In Master mode (default) the device is generating clock signal sckPin and word select signal on fsPin.
In Slave mode the device listens on attached pins for the clock signal and word select - i.e. unless externally driven the
pins will remain LOW.
How to enter either mode is described in the function section.
Operation Modes
Setting the operation mode is done with function begin (see API section)
• I2S_PHILIPS_MODE
– Currently the only official* PIN_I2S_SCK
• PIN_I2S_FS
• PIN_I2S_SD
• PIN_I2S_SD_OUT only need to send one channel data but the data will be copied for another channel automati-
cally, then both channels will transmit same data.
• ADC_DAC_MODE The output will be an analog signal on pins 25 (L or R?) and 26 (L or R?). Input will be received
on pin _inSdPin. The data are sampled in 12 bits and stored in a 16 bits, with the 4 most significant bits
set to zero.
• PDM_STEREO_MODE Pulse-density-modulation is similar to PWM, but instead, the pulses have constant width.
The signal is modulated with the number of ones or zeroes in sequence.
• PDM_MONO_MODE Single-channel version of PDM mode described above.
The Simplex mode is the default after driver initialization. Simplex mode uses the shared data pin sdPin or constant
PIN_I2S_SD for both output and input, but can only read or write. This is the same behavior as in original Arduino
library.
The Duplex mode uses two separate data pins:
• Output pin outSdPin for function parameter, or constant PIN_I2S_SD_OUT
• Input pin inSdPin for function parameter, or constant PIN_I2S_SD_IN
In this mode, the driver is able to read and write simultaneously on each line and is suitable for applications like
walkie-talkie or phone.
Switching between these modes is performed simply by calling setDuplex() or setSimplex() (see APi section for details
and more functions).
76 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
The ESP32 I2S library is based on the Arduino I2S Library and implements a few more APIs, described in this docu-
mentation.
Before initialization, choose which pins you want to use. In DAC mode you can use only pins 25 and 26 for the output.
Before usage choose which pins you want to use. In DAC mode you can use only pins 25 and 26 as output.
Parameters:
• [in] mode one of above mentioned operation mode, for example I2S_PHILIPS_MODE.
• [in] sampleRate is the sampling rate in Hz. Currently officially supported value is only 16000 - other than this
value will print warning, but continue to operate, however the resulting audio quality may suffer and the app may
crash.
• [in] bitsPerSample is the number of bits in a channel sample.
Currently, the supported value is only 16 - other than this value will print a warning, but continues to operate, however,
the resulting audio quality may suffer and the application may crash.
For ADC_DAC_MODE the only possible value will remain 16.
This function will return true on success or fail in case of failure.
When failed, an error message will be printed if subscribed.
Performs initialization before use - creates buffers, task handling underlying driver messages, configuring and starting
the driver operation.
This version initializes I2S in SLAVE mode (see previous entry for MASTER mode).
Parameters:
• [in] mode one of above mentioned modes for example I2S_PHILIPS_MODE.
• [in] bitsPerSample is the umber of bits in a channel sample. Currently, the only supported value is only 16 -
other than this value will print warning, but continue to operate, however the resulting audio quality may suffer
and the app may crash.
For ADC_DAC_MODE the only possible value will remain 16.
This function will return true on success or fail in case of failure.
When failed, an error message will be printed if subscribed.
2.3. APIs 77
Arduino-ESP32, Release 2.0.6
end
Performs safe deinitialization - free buffers, destroy task, end driver operation, etc.
void end()
Pin setup
Note: Shared data pin can be equal to any other data pin, but must not be equal to clock pin nor frame sync pin! Input
and Output pins must not be equal, but one of them can be equal to shared data pin!
By default, the pin numbers are defined in constants in the header file. You can redefine any of those constants before
including I2S.h. This way the driver will use these new default values and you will not need to specify pins in your
code. The constants and their default values are:
• PIN_I2S_SCK 14
• PIN_I2S_FS 25
• PIN_I2S_SD 26
• PIN_I2S_SD_OUT 26
• PIN_I2S_SD_IN 35
The second option to change pins is using the following functions. These functions can be called on either on initialized
or uninitialized object.
If called on the initialized object (after calling begin) the pins will change during operation. If called on the uninitial-
ized object (before calling begin, or after calling end) the new pin setup will be used on next initialization.
setSckPin
78 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
setFsPin
setDataPin
setDataInPin
setDataOutPin
setAllPins
Set all pins using given values in parameters. This is simply a wrapper of four functions mentioned above.
int setAllPins(int sckPin, int fsPin, int sdPin, int outSdPin, int inSdPin)
Set all pins to default i.e. take values from constants mentioned above. This simply calls the the function with the
following constants.
• PIN_I2S_SCK 14
• PIN_I2S_FS 25
• PIN_I2S_SD 26
• PIN_I2S_SD_OUT 26
• PIN_I2S_SD_IN 35
int setAllPins()
2.3. APIs 79
Arduino-ESP32, Release 2.0.6
getSckPin
int getSckPin()
getFsPin
int getFsPin()
getDataPin
int getDataPin()
getDataInPin
int getDataInPin()
getDataOutPin
int getDataOutPin()
onTransmit
void onTransmit(void(*)(void))
onReceive
void onReceive(void(*)(void))
80 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
setBufferSize
getBufferSize
Get current buffer sizes in sample words (see description for setBufferSize).
int getBufferSize()
Duplex vs Simplex
Original Arduino I2S library supports only simplex mode (only transmit or only receive at a time). For compatibility,
we kept this behavior, but ESP natively supports duplex mode (receive and transmit simultaneously on separate pins).
By default this library is initialized in simplex mode as it would in Arduino, switching input and output on sdPin
(constant PIN_I2S_SD default pin 26).
setDuplex
int setDuplex()
input: inSdPin (constant PIN_I2S_SD_IN, default 35) output: outSdPin (constant PIN_I2S_SD, default 26)
2.3. APIs 81
Arduino-ESP32, Release 2.0.6
setSimplex
(Default mode)
Switch to simplex mode using shared data pin sdPin (constant PIN_I2S_SD, default 26).
int setSimplex()
isDuplex
int isDuplex()
Data stream
available
int available()
read
This function is non-blocking, i.e. if the requested number of bytes is not available, it will return as much as possible
without waiting.
Hint: use available() before calling this function.
Parameters:
[out] void* buffer buffer into which will be copied data read from internal buffer. WARNING: this buffer must be
allocated before use!
[in] size_t size number of bytes required to be read.
Returns number of successfully bytes read. Returns false` in case of reading error.
Read one sample.
int read()
82 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
peek
Read one sample from the internal buffer and returns it.
int peek()
Repeated peeks will be returned in the same sample until read is called.
flush
void flush()
write
size_t write(uint8_t)
Single-sample writes are blocking - waiting until there is free space in the internal buffer to be written into.
Returns number of successfully written bytes, in this case, 1. Returns 0 on error.
Write single sample.
size_t write(int32_t)
Single-sample writes are blocking - waiting until there is free space in the internal buffer to be written into.
Returns number of successfully written bytes. Returns 0 on error.
Expected return number is bitsPerSample/8.
Write buffer of supplied size;
Parameters:
[in] const void *buffer buffer to be written [in] size_t size size of buffer in bytes
Returns number of successfully written bytes. Returns 0 in case of error. The expected return number is equal to size.
write
This is a wrapper of the previous function performing typecast from uint8_t*` to void*.
2.3. APIs 83
Arduino-ESP32, Release 2.0.6
availableForWrite
int availableForWrite()
write_blocking
Core function implementing blocking write, i.e. waits until all requested data are written.
WARNING: If too many bytes are requested, this can cause WatchDog Trigger Reset!
Returns number of successfully written bytes. Returns 0 on error.
write_nonblocking
Core function implementing non-blocking write, i.e. writes as much as possible and exits.
Sample code
#include <I2S.h>
const int buff_size = 128;
int available, read;
uint8_t buffer[buff_size];
84 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
About
ESP Insights is a remote diagnostics solution that allows users to remotely monitor the health of ESP devices in the
field.
Developers normally prefer debugging issues by physically probing them using gdb or observing the logs. This surely
helps debug issues, but there are often cases wherein issues are seen only in specific environments under specific
conditions. Even things like casings and placement of the product can affect the behaviour. A few examples are
• Wi-Fi disconnections for a smart switch concealed in a wall.
• Smart speakers crashing during some specific usage pattern.
• Appliance frequently rebooting due to power supply issues.
Additional information about ESP Insights can be found here.
Insights.begin
bool begin(const char *auth_key, const char *node_id = NULL, uint32_t log_type =␣
˓→0xFFFFFFFF, bool alloc_ext_ram = false);
Insights.send
Read insights data from buffers and send it to the cloud. Call to this function is asynchronous, it may take some time
to send the data.
bool sendData()
2.3. APIs 85
Arduino-ESP32, Release 2.0.6
Insights.end
void end();
Insights.disable
void disable();
Insights.metrics.addX
Register a metric of type X, where X is one of: Bool, Int, Uint, Float, String, IPv4 or MAC
bool addX(const char *tag, const char *key, const char *label, const char *path);
Insights.metrics.remove
86 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
Insights.metrics.removeAll
bool removeAll();
Insights.metrics.setX
Add metrics of type X to storage, where X is one of: Bool, Int, Uint, Float, String, IPv4 or MAC
Insights.metrics.dumpHeap
Dumps the heap metrics and prints them to the console. This API collects and reports metrics value at any give point
in time.
bool dumpHeap();
Insights.metrics.dumpWiFi
Dumps the wifi metrics and prints them to the console. This API can be used to collect wifi metrics at any given point
in time.
bool dumpWiFi();
2.3. APIs 87
Arduino-ESP32, Release 2.0.6
Insights.metrics.setHeapPeriod
Reset the periodic interval By default, heap metrics are collected every 30 seconds, this function can be used to change
the interval. If the interval is set to 0, heap metrics collection disabled.
Insights.metrics.setWiFiPeriod
Reset the periodic interval By default, wifi metrics are collected every 30 seconds, this function can be used to change
the interval. If the interval is set to 0, wifi metrics collection disabled.
Insights.variables.addX
Register a variable of type X, where X is one of: Bool, Int, Uint, Float, String, IPv4 or MAC
bool addX(const char *tag, const char *key, const char *label, const char *path);
Insights.variables.remove
88 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
Insights.variables.removeAll
bool unregisterAll();
Insights.variables.setX
Add variable of type X to storage, where X is one of: Bool, Int, Uint, Float, String, IPv4 or MAC
Example
#include "Insights.h"
#include "WiFi.h"
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSPHRASE);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
if(!Insights.begin(insights_auth_key)){
return;
}
Serial.println("=========================================");
(continues on next page)
2.3. APIs 89
Arduino-ESP32, Release 2.0.6
void loop()
{
delay(1000);
}
About
The LED control (LEDC) peripheral is primarly designed to control the intensity of LEDs, although it can also be used
to generate PWM signals for other purposes.
ESP32 SoCs has from 6 to 16 channels (variates on socs, see table below) which can generate independent waveforms,
that can be used for example to drive RGB LED devices.
ledcSetup
This function is used to setup the LEDC channel frequency and resolution.
90 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
ledcWrite
ledcRead
This function is used to get configured duty for the LEDC channel.
ledcReadFreq
This function is used to get configured frequency for the LEDC channel.
ledcWriteTone
This function is used to setup the LEDC channel to 50 % PWM tone on selected frequency.
ledcWriteNote
2.3. APIs 91
Arduino-ESP32, Release 2.0.6
ledcAttachPin
ledcDetachPin
ledcChangeFrequency
analogWrite
This function is used to write an analog value (PWM wave) on the pin. It is compatible with Arduinos analogWrite
function.
92 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
analogWriteResolution
analogWriteFrequency
Example Applications
/*
LEDC Software Fade
// fade LED PIN (replace with LED_BUILTIN constant for built-in LED)
#define LED_PIN 5
2.3. APIs 93
Arduino-ESP32, Release 2.0.6
void setup() {
// Setup timer and attach timer to a led pin
ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT);
ledcAttachPin(LED_PIN, LEDC_CHANNEL_0);
}
void loop() {
// set the brightness on LEDC channel 0
ledcAnalogWrite(LEDC_CHANNEL_0, brightness);
/*
ledcWrite_RGB.ino
Runs through the full 255 color spectrum for an rgb led
Demonstrate ledcWrite functionality for driving leds with PWM on ESP32
const boolean invert = true; // set true if common anode, false if common cathode
94 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
// Initialize channels
// channels 0-15, resolution 1-16 bits, freq limits depend on resolution
// ledcSetup(uint8_t channel, uint32_t freq, uint8_t resolution_bits);
ledcSetup(1, 12000, 8); // 12 kHz PWM, 8-bit resolution
ledcSetup(2, 12000, 8);
ledcSetup(3, 12000, 8);
}
// If it doesn't fully turn off and is common anode try using 256.
ledcWrite(1, 255);
ledcWrite(2, 255);
ledcWrite(3, 255);
delay(2000);
Serial.println("Send all LEDs a 0 and wait 2 seconds.");
ledcWrite(1, 0);
ledcWrite(2, 0);
ledcWrite(3, 0);
delay(2000);
for (color = 0; color < 255; color++) { // Slew through the color spectrum
2.3. APIs 95
Arduino-ESP32, Release 2.0.6
uint8_t complement = 0;
uint16_t prev = (brightness * ( 255 - segmentOffset)) / 256;
uint16_t next = (brightness * segmentOffset) / 256;
if(invert)
{
brightness = 255 - brightness;
complement = 255;
prev = 255 - prev;
next = 255 - next;
}
switch(segment ) {
case 0: // red
R = brightness;
G = next;
B = complement;
break;
case 1: // yellow
R = prev;
G = brightness;
B = complement;
break;
case 2: // green
R = complement;
G = brightness;
B = next;
break;
case 3: // cyan
R = complement;
G = prev;
B = brightness;
break;
case 4: // blue
R = next;
G = complement;
B = brightness;
break;
case 5: // magenta
default:
R = brightness;
(continues on next page)
96 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
2.3.14 Preferences
About
The Preferences library is unique to arduino-esp32. It should be considered as the replacement for the Arduino EEP-
ROM library.
It uses a portion of the on-board non-volatile memory (NVS) of the ESP32 to store data. This data is retained across
restarts and loss of power events to the system.
Preferences works best for storing many small values, rather than a few large values. If large amounts of data are to be
stored, consider using a file system library such as LitteFS.
The Preferences library is usable by all ESP32 variants.
Header File
#include <Preferences.h>
Overview
2.3. APIs 97
Arduino-ESP32, Release 2.0.6
String values can be stored and retrieved either as an Arduino String or as a null terminated char array (c-string).
Bytes type is used for storing and retrieving an arbitrary number of bytes in a namespace.
begin
Open non-volatile storage with a given namespace name from an NVS partition.
Parameters
• name (Required)
– Namespace name. Maximum length is 15 characters.
• readOnly (Optional)
– false will open the namespace in read-write mode.
– true will open the namespace in read-only mode.
– if omitted, the namespace is opened in read-write mode.
• partition_label (Optional)
– name of the NVS partition in which to open the namespace.
– if omitted, the namespace is opened in the “nvs” partition.
Returns
• true if the namespace was opened successfully; false otherwise.
Notes
98 Chapter 2. Libraries
Arduino-ESP32, Release 2.0.6
• If the namespace does not exist within the partition, it is first created.
• Attempting to write a key value to a namespace open in read-only mode will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
end
void end()
Parameters
• None
Returns
• Nothing
Note
• After closing a namespace, methods used to access it will fail.
clear
Delete all keys and values from the currently opened namespace.
bool clear()
Parameters
• None
Returns
• true if all keys and values were deleted; false otherwise.
Note
• the namespace name still exists afterward.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
remove
Parameters
• key (Required)
– the name of the key to be deleted.
Returns
• true if key-value pair was deleted; false otherwise.
Note
2.3. APIs 99
Arduino-ESP32, Release 2.0.6
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
putChar, putUChar
Parameters
• key (Required)
– if the key does not exist in the currently opened namespace it is first created.
• value (Required)
– must match the data type of the method.
Returns
• 1 (the number of bytes stored for these data types) if the call is successful; 0 otherwise.
Notes
• Attempting to store a value without a namespace being open in read-write mode will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
putShort, putUShort
Parameters
• key (Required)
– if the key does not exist in the currently opened namespace it is first created.
• value (Required)
– must match the data type of the method.
Returns
• 2 (the number of bytes stored for these data types) if the call is successful; 0 otherwise.
Notes
• Attempting to store a value without a namespace being open in read-write mode will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
putInt, putUInt
putLong, putULong
Parameters
• key (Required)
– if the key does not exist in the currently opened namespace it is first created.
• value (Required)
– must match the data type of the method.
Returns
• 4 (the number of bytes stored for these data types) if the call is successful; 0 otherwise.
Notes
• Attempting to store a value without a namespace being open in read-write mode will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
putLong64, putULong64
putFloat, putDouble
Parameters
• key (Required)
– if the key does not exist in the currently opened namespace it is first created.
• value (Required)
– must match the data type of the method.
Returns
• 8 (the number of bytes stored for these data types) if the call is successful; 0 otherwise.
Notes
• Attempting to store a value without a namespace being open in read-write mode will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
putBool
Parameters
• key (Required)
– if the key does not exist in the currently opened namespace it is first created.
• value (Required)
– must match the data type of the method.
Returns
• true if successful; false otherwise.
Notes
• Attempting to store a value without a namespace being open in read-write mode will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
putString
Store a variable length value against a given key in the currently open namespace.
Parameters
• key (Required)
– if the key does not exist in the currently opened namespace it is first created.
• value (Required)
– if const char*, a null-terminated (c-string) character array.
– if String, a valid Arduino String type.
Returns
• if successful: the number of bytes stored; 0 otherwise.
Notes
• Attempting to store a value without a namespace being open in read-write mode will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
putBytes
Store a variable number of bytes against a given key in the currently open namespace.
Parameters
• key (Required)
– if the key does not exist in the currently opened namespace it is first created.
• value (Required)
– pointer to an array or buffer containing the bytes to be stored.
• len (Required)
– the number of bytes from value to be stored.
Returns
• if successful: the number of bytes stored; 0 otherwise.
Notes
• Attempting to store a value without a namespace being open in read-write mode will fail.
• This method operates on the bytes used by the underlying data type, not the number of elements
of a given data type. The data type of value is not retained by the Preferences library afterward.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
getChar, getUChar
Retrieve a value stored against a given key in the currently open namespace.
Parameters
• key (Required)
• defaultValue (Optional)
– must match the data type of the method if provided.
Returns
• the value stored against key if the call is successful.
• defaultValue, if it is provided; 0 otherwise.
Notes
• Attempting to retrieve a key without a namespace being available will fail.
• Attempting to retrieve value from a non existant key will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
getShort, getUShort
Retrieve a value stored against a given key in the currently open namespace.
Except for the data type returned, behaves exactly like getChar.
getInt, getUInt
Retrieve a value stored against a given key in the currently open namespace.
Except for the data type returned, behaves exactly like getChar.
getLong, getULong
Retrieve a value stored against a given key in the currently open namespace.
Except for the data type returned, behaves exactly like getChar.
getLong64, getULong64
Retrieve a value stored against a given key in the currently open namespace.
Except for the data type returned, behaves exactly like getChar.
getFloat
Retrieve a value stored against a given key in the currently open namespace.
Except for the data type returned and the value of defaultValue, behaves exactly like getChar.
getDouble
Retrieve a value stored against a given key in the currently open namespace.
Except for the data type returned and the value of defaultValue, behaves exactly like getChar.
getBool
Retrieve a value stored against a given key in the currently open namespace.
Except for the data type returned, behaves exactly like getChar.
getString
Copy a string of char stored against a given key in the currently open namespace to a buffer.
Parameters
• key (Required)
• value (Required)
– a buffer of a size large enough to hold len bytes
• len (Required)
– the number of type char` to be written to the buffer pointed to by value
Returns
• if successful; the number of bytes equal to len is written to the buffer pointed to by value, and
the method returns 1.
• if the method fails, nothing is written to the buffer pointed to by value and the method returns
0.
Notes
• len must equal the number of bytes stored against the key or the call will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
getString
Retrieve an Arduino String value stored against a given key in the currently open namespace.
Parameters
• key (Required)
• defaultValue (Optional)
Returns
• the value stored against key if the call if successful
• if the method fails: it returns defaultValue, if provided; "" (an empty String) otherwise.
Notes
• defaultValue must be of type String.
getBytes
Copy a series of bytes stored against a given key in the currently open namespace to a buffer.
Parameters
• key (Required)
• buf (Required)
– a buffer of a size large enough to hold len bytes.
• len (Required)
– the number of bytes to be written to the buffer pointed to by buf
Returns
• if successful, the number of bytes equal to len is written to buffer buf, and the method returns
len.
• if the method fails, nothing is written to the buffer and the method returns 0.
Notes
• len must equal the number of bytes stored against the key or the call will fail.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
getBytesLength
Get the number of bytes stored in the value against a key of type Bytes in the currently open namespace.
Parameters
• key (Required)
Returns
• if successful: the number of bytes in the value stored against key; 0 otherwise.
Notes
• This method will fail if key is not of type Bytes.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
getType
Get the Preferences data type of a given key within the currently open namespace.
Parameters
• key (Required)
Returns
• an int value as per Table 2 below.
• a value of 10 (PT_INVALID) if the call fails.
Notes
• The return values are enumerated in Preferences.h. Table 2 includes the enumerated values
for information.
• A return value can map to more than one Prefs Type.
• The method will fail if: the namespace is not open; the key does not exist; the provided key
exceeds 15 characters.
freeEntries
Get the number of free entries available in the key table of the currently open namespace.
size_t freeEntries()
Parameters
• none
Returns
• if successful: the number of free entries available in the key table of the currently open names-
pace; 0 otherwise.
Notes
• keys storing values of type Bool, Char, UChar, Short, UShort, Int, UInt, Long, ULong,
Long64, ULong64 use one entry in the key table.
• keys storing values of type Float and Double use three entries in the key table.
• Arduino or c-string String types use a minimum of two key table entries with the number of
entries increasing with the length of the string.
• keys storing values of type Bytes use a minimum of three key table entries with the number of
entries increasing with the number of bytes stored.
• A message providing the reason for a failed call is sent to the arduino-esp32 log_e facility.
About
About
RMaker.initNode
This initializes the ESP RainMaker agent, wifi and creates the node.
You can also set the configuration of the node using the following API
RMaker.setTimeSync(bool val)
NOTE: If you want to set the configuration for the node then these configuration API must be called before
RMaker.initNode().
RMaker.start
esp_err_t start();
RMaker.stop
It stops the ESP RainMaker agent which was started using RMaker.start().
esp_err_t stop()
RMaker.deinitNode
It deinitializes the ESP RainMaker agent and the node created using RMaker.initNode().
RMaker.enableOTA
It enables OTA as per the ESP RainMaker Specification. For more details refer ESP RainMaker documentation. check
here.
RMaker.enableSchedule
This API enables the scheduling service for the node. For more information, check here.
esp_err_t enableSchedule();
RMaker.enableScenes
This API enables the Scenes service for the node. It should be called after RMaker.initNode() and before RMaker.start().
For more information, check here.
esp_err_t enableScenes()
RMaker.enableSystemService
This API enables the System service for the node. It should be called after RMaker.initNode() and before RMaker.start().
For more information, check here.
RMaker.setTimeZone
This API set’s the timezone as a user friendly location string. Check here for a list of valid values.
NOTE : default value is “Asia/Shanghai”.
This API comes into picture only when working with scheduling.
my_node.getNodeID
It returns the unique node_id assigned to the node. This node_id is usually the MAC address of the board.
char * getNodeID()
my_node.getNodeInfo
node_info_t * getNodeInfo();
my_node.addNodeAttr
my_node.addDevice
my_node.removeDevice
Device class expose API’s for virtual devices on the node. Parameterized constructor is defined which creates the
virtual device on the node. Using Device class object you can create your own device.
NOTE : my_device is the object of Device class
Device my_device("Switch");
Device my_device("Switch1", NULL, NULL);
Switch switch1;
Switch switch2("switch2", NULL, true);
• NULL : Private data for the device, which will be used in callback.
• true : Default value for the primary param, in case of switch it is power.
NOTE: No parameter are compulsory for standard devices. However if you are creating two objects of same standard
class then in that case you will have to set the device name, if not then both device will have same name which is set
by default, hence device will not get create. Device name should be unique for each device.
my_device.getDeviceName
my_device.addDeviceAttr
It adds attribute to the device. Device attributes are reported only once after a boot-up as part of the node configuration.
Eg. Serial Number
my_device.deleteDevice
esp_err_t deleteDevice();
my_device.addXParam
my_device.assignPrimaryParam
It assigns a parameter (already added using addXParam() or addParam()) as a primary parameter, which can be used
by clients (phone apps specifically) to give prominence to it.
my_device.getParamByName
• param_name : It is the name of the parameter which was added using addXparam() or addParam().
This function will return object of the parameter.
my_device.addParam
It allows user to add custom parameter to the device created using Param class.
my_device.updateAndReportParam
It updates the parameter assosicated with particular device on ESP RainMaker cloud.
my_device.addCb
It registers read and write callback for the device which will be invoked as per requests received from the cloud (or
other paths as may be added in future).
• write_cb [Function with signature] func_name(Device *device, Param *param, const param_val_t val, void
*priv_data, write_ctx_t *ctx);
• read_cb [Function with signature] func_name(Device *device, Param *param, void *priv_data, read_ctx_t
*ctx);
Parameters
param_val_t val
Value can be accessed as below
1. bool : val.val.b
2. integer : val.val.i
3. float : val.val.f
4. char * : val.val.s
Param class expose API’s for creating custom parameters for the devices and report and update values associated with
parameter to the ESP RainMaker cloud. Parameterized constructor is defined which creates custom parameter.
NOTE : my_param is the object of Param class.
Param my_param(const char *param_name, const char *param_type, param_val_t val, uint8_t␣
˓→properties);
Param my_param(const char *param_name, const char *param_type, param_val_t val, uint8_t␣
˓→properties);
NOTE : Parameter created using Param class should be added to the device using my_device.addParam(my_param);
my_param.addUIType
Add a UI type to the parameter. This will be used by the Phone apps (or other clients) to render appropriate UI for the
given parameter. Please refer the RainMaker documentation here for supported UI Types.
my_param.addBounds
Add bounds for an integer/float parameter. This can be used to add bounds (min/max values) for a given integer/float
parameter. Eg. brightness will have bounds as 0 and 100 if it is a percentage.
my_param.updateAndReport
It updates the parameter and report it to ESP RainMaker cloud. This is called in callback.
printQR
RMakerFactoryReset
RMakerFactoryReset(int seconds);
• seconds : Time in seconds after which the chip should reboot after doing a factory reset.
RMakerWiFiReset
RMakerWiFiReset(int seconds);
• seconds : Time in seconds after which the chip should reboot after doing a Wi-Fi reset.
About
Note: This is a work in progress project and this section is still missing. If you want to contribute, please see the
Contributions Guide.
Example
Reset Reason
/*
* Print last reset reason of ESP32
* =================================
*
* Use either of the methods print_reset_reason
* or verbose_print_reset_reason to display the
* cause for the last reset of this device.
*
* Public Domain License.
*
* Author:
* Evandro Luis Copercini - 2017
*/
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
delay(2000);
void loop() {
// put your main code here, to run repeatedly:
/*
Example Serial Log:
====================
*/
2.3.18 RMT
About
Note: This is a work in progress project and this section is still missing. If you want to contribute, please see the
Contributions Guide.
Remote Control Transceiver (RMT) peripheral was designed to act as an infrared transceiver.
Example
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "Arduino.h"
#include "esp32-hal.h"
// The effect seen in ESP32C3, ESP32S2 and ESP32S3 is like a Blink of RGB LED
#if CONFIG_IDF_TARGET_ESP32S2
#define BUILTIN_RGBLED_PIN 18
#elif CONFIG_IDF_TARGET_ESP32S3
#define BUILTIN_RGBLED_PIN 48
#elif CONFIG_IDF_TARGET_ESP32C3
#define BUILTIN_RGBLED_PIN 8
#else
#define BUILTIN_RGBLED_PIN 21 // ESP32 has no builtin RGB LED
#endif
//
// Note: This example uses Neopixel LED board, 32 LEDs chained one
// after another, each RGB LED has its 24 bit value
// for color configuration (8b for each color)
//
// Bits encoded as pulses as follows:
//
// "0":
// +-------+ +--
// | | |
// | | |
// | | |
// ---| |--------------|
// + + +
// | 0.4us | 0.85 0us |
//
// "1":
// +-------------+ +--
// | | |
// | | |
// | | |
// | | |
// ---+ +-------+
// | 0.8us | 0.4us |
void setup()
{
Serial.begin(115200);
void loop()
{
// Init data with only one led ON
int led, col, bit;
int i=0;
for (led=0; led<NR_OF_LEDS; led++) {
for (col=0; col<3; col++ ) {
for (bit=0; bit<8; bit++){
if ( (color[col] & (1<<(7-bit))) && (led == led_index) ) {
led_data[i].level0 = 1;
led_data[i].duration0 = 8;
led_data[i].level1 = 0;
led_data[i].duration1 = 4;
} else {
led_data[i].level0 = 1;
led_data[i].duration0 = 4;
led_data[i].level1 = 0;
led_data[i].duration1 = 8;
}
i++;
}
}
}
// make the led travel in the pannel
if ((++led_index)>=NR_OF_LEDS) {
led_index = 0;
}
2.3.19 SDIO
About
2.3.20 SD MMC
About
Note: This is a work in progress project and this section is still missing. If you want to contribute, please see the
Contributions Guide.
Example
SDMMC Test
/*
* Connect the SD card to the following pins:
*
* SD Card | ESP32
* D2 12
* D3 13
* CMD 15
* VSS GND
* VDD 3.3V
* CLK 14
* VSS GND
* D0 2 (add 1K pull up after flashing)
* D1 4
*/
#include "FS.h"
#include "SD_MMC.h"
size_t i;
start = millis();
for(i=0; i<2048; i++){
file.write(buf, 512);
}
end = millis() - start;
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
file.close();
}
void setup(){
Serial.begin(115200);
if(!SD_MMC.begin()){
Serial.println("Card Mount Failed");
(continues on next page)
if(cardType == CARD_NONE){
Serial.println("No SD_MMC card attached");
return;
}
void loop(){
2.3.21 SigmaDelta
About
ESP32 provides a second-order sigma delta modulation module and 8 (4 for ESP32-C3) independent modulation chan-
nels. The channels are capable to output 1-bit signals (output index: 100 ~ 107) with sigma delta modulation.
sigmaDeltaSetup
This function is used to setup the SigmaDelta channel frequency and resolution.
sigmaDeltaWrite
sigmaDeltaRead
This function is used to get configured duty for the SigmaDelta channel.
sigmaDeltaDetachPin
Example Applications
void setup()
{
//setup on pin 18, channel 0 with frequency 312500 Hz
sigmaDeltaSetup(18,0, 312500);
//initialize channel 0 to off
sigmaDeltaWrite(0, 0);
}
void loop()
{
//slowly ramp-up the value
//will overflow at 256
static uint8_t i = 0;
sigmaDeltaWrite(0, i++);
delay(100);
}
2.3.22 SPI
About
For some APIs, the reference to be used is the same as the Arduino Core.
SPI Reference
SPI Description
Example
/* The ESP32 has four SPi buses, however as of right now only two of
* them are available to use, HSPI and VSPI. Simply using the SPI API
* as illustrated in Arduino examples will use VSPI, leaving HSPI unused.
*
* However if we simply intialise two instance of the SPI class for both
* of these buses both can be used. However when just using these the Arduino
* way only will actually be outputting at a time.
*
* Logic analyser capture is in the same folder as this example as
* "multiple_bus_output.png"
*
* created 30/04/2018 by Alistair Symonds
*/
#include <SPI.h>
#ifdef ALTERNATE_PINS
#define VSPI_MISO 2
#define VSPI_MOSI 4
#define VSPI_SCLK 0
#define VSPI_SS 33
#define HSPI_MISO 26
#define HSPI_MOSI 27
#define HSPI_SCLK 25
#define HSPI_SS 32
#else
#define VSPI_MISO MISO
#define VSPI_MOSI MOSI
#define VSPI_SCLK SCK
#define VSPI_SS SS
#define HSPI_MISO 12
#define HSPI_MOSI 13
#define HSPI_SCLK 14
#define HSPI_SS 15
#endif
void setup() {
//initialise two instances of the SPIClass attached to VSPI and HSPI respectively
vspi = new SPIClass(VSPI);
hspi = new SPIClass(HSPI);
#ifndef ALTERNATE_PINS
//initialise vspi with default pins
//SCLK = 18, MISO = 19, MOSI = 23, SS = 5
vspi->begin();
#else
//alternatively route through GPIO pins of your choice
vspi->begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS); //SCLK, MISO, MOSI, SS
#endif
#ifndef ALTERNATE_PINS
//initialise hspi with default pins
//SCLK = 14, MISO = 12, MOSI = 13, SS = 15
hspi->begin();
#else
//alternatively route through GPIO pins
hspi->begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS); //SCLK, MISO, MOSI, SS
#endif
// the loop function runs over and over again until power down or reset
void loop() {
//use the SPI buses
spiCommand(vspi, 0b01010101); // junk data to illustrate usage
spiCommand(hspi, 0b11001100);
delay(100);
}
2.3.23 Timer
About
The ESP32 SoCs contains from 2 to 4 hardware timers. They are all 64-bit (54-bit for ESP32-C3) generic timers based
on 16-bit pre-scalers and 64-bit (54-bit for ESP32-C3) up / down counters which are capable of being auto-reloaded.
timerBegin
This function is used to configure the timer. After successful setup the timer will automatically start.
timerEnd
timerGetConfig
timerSetConfig
timerAttachInterrupt
timerDetachInterrupt
timerStart
timerStop
timerRestart
timerWrite
timerSetDivider
timerSetCountUp
timerSetAutoReload
timerStarted
timerRead
timerReadMicros
timerReadMilis
timerReadSeconds
timerGetDivider
timerGetCountUp
timerGetAutoReload
timerAlarmEnable
timerAlarmDisable
timerAlarmWrite
This function is used to configure alarm value and autoreload of the timer.
timerAlarmEnabled
timerAlarmRead
timerAlarmReadMicros
timerAlarmReadSeconds
Example Applications
/*
Repeat timer example
This example shows how to use hardware timer in ESP32. The timer calls onTimer
function every second. The timer can be stopped with button attached to PIN 0
(IO0).
void setup() {
Serial.begin(115200);
// Start an alarm
timerAlarmEnable(timer);
}
void loop() {
// If Timer has fired
if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE){
uint32_t isrCount = 0, isrTime = 0;
// Read the interrupt count and time
portENTER_CRITICAL(&timerMux);
isrCount = isrCounter;
isrTime = lastIsrAt;
portEXIT_CRITICAL(&timerMux);
// Print it
Serial.print("onTimer no. ");
Serial.print(isrCount);
Serial.print(" at ");
Serial.print(isrTime);
Serial.println(" ms");
}
// If button is pressed
if (digitalRead(BTN_STOP_ALARM) == LOW) {
// If timer is still running
if (timer) {
// Stop and free timer
timerEnd(timer);
timer = NULL;
}
}
}
#include "esp_system.h"
void setup() {
Serial.begin(115200);
Serial.println();
(continues on next page)
void loop() {
Serial.println("running main loop");
2.3.24 TOUCH
About
Touch sensor is a peripheral, that has an internal oscilator circuit and it measures charge/discharge frequency over a
fixed period of time on respective GPIO pins. Therefore these touch sensors are also known as capacitive sensors. For
example, if you touch any of these pins, finger electrical charge will change this number of cycles, by changing the RC
circuit attached to the touch sensor. The TouchRead() will return the number of cycles (charges/discharges) in a certain
time (meas). The change of this count will be used to validate if a touch has happened or not. These pins can be easily
integrated into capacitive pads, and replace mechanical buttons.
Note: Touch peripheral is not present in every SoC. Refer to datasheet of each chip for more info.
touchRead
This function gets the touch sensor data. Each touch sensor has a counter to count the number of charge/discharge
cycles. When the pad is ‘touched’, the value in the counter will change because of the larger equivalent capacitance.
The change of the data determines if the pad has been touched or not.
touchSetCycles
This function is used to set cycles that measurement operation takes. The result from touchRead, threshold and detection
accuracy depend on these values. The defaults are setting touchRead to take ~0.5ms.
• measure Sets the time that it takes to measure touch sensor value
• sleep Sets waiting time before next measure cycle
touchAttachInterrupt
This function is used to attach interrupt to the touch pad. The function will be called if a touch sensor value falls below
the given threshold for ESP32 or rises above the given threshold for ESP32-S2/S3. To determine a proper threshold
value between touched and untouched state, use touchRead() function.
touchAttachInterruptArg
This function is used to attach interrupt to the touch pad. In the function called by ISR you have the given arguments
available.
touchDetachInterrupt
touchSleepWakeUpEnable
This function is used to setup touch pad as the wake up source from the deep sleep.
Note: ESP32-S2 and ESP32-S3 only support one sleep wake up touch pad.
touchInterruptSetThresholdDirection
This function is used to tell the driver if it shall activate the interrupt if the sensor is lower or higher than the threshold
value. Default is lower.
touchInterruptGetLastStatus
This function is used get the lastest ISR status for the touch pad.
This function returns true if the touch pad has been and continues pressed or false otherwise.
Example Applications
void setup()
{
(continues on next page)
void loop()
{
Serial.println(touchRead(T1)); // get value using T1
delay(1000);
}
/*
This is an example how to use Touch Intrrerupts
The bigger the threshold, the more sensible is the touch
*/
void gotTouch1(){
touch1detected = true;
}
void gotTouch2(){
touch2detected = true;
}
void setup() {
Serial.begin(115200);
delay(1000); // give me time to bring up serial monitor
Serial.println("ESP32 Touch Interrupt Test");
touchAttachInterrupt(T2, gotTouch1, threshold);
touchAttachInterrupt(T3, gotTouch2, threshold);
}
void loop(){
if(touch1detected){
touch1detected = false;
Serial.println("Touch 1 detected");
}
if(touch2detected){
touch2detected = false;
Serial.println("Touch 2 detected");
}
}
Note: This feature is only supported on ESP chips that have USB peripheral, like the ESP32-S2 and ESP32-S3. Some
chips, like the ESP32-C3 include native CDC+JTAG peripheral that is not covered here.
About
The Universal Serial Bus is a widely used peripheral to exchange data between devices. USB was introduced on the
ESP32, supporting both device and host mode.
To learn about the USB, see the USB.org for developers.
USB as Device
In the device mode, the ESP32 acts as an USB device, like a mouse or keyboard to be connected to a host device, like
your computer or smartphone.
USB as Host
The USB host mode, you can connect devices on the ESP32, like external modems, mouse and keyboards.
API Description
USB CDC
About
USB Communications Device Class API. This class is used to enable communication between the host and the device.
This class is often used to enable serial communication and can be used to flash the firmware on the ESP32 without
the external USB to Serial chip.
APIs
onEvent
setRxBufferSize
setTxTimeoutMs
This function is used to define the time to reach the timeout for the TX.
begin
This function is used to start the peripheral using the default CDC configuration.
Where:
• baud is the baud rate.
end
This function will finish the peripheral as CDC and release all the allocated resources. After calling end you need to
use begin again in order to initialize the USB CDC driver again.
void end();
available
int available(void);
availableForWrite
int availableForWrite(void);
peek
int peek(void);
read
Where:
• buffer is the pointer to the buffer to be read.
• size is the number of bytes to be read.
write
Where:
• buffer is the pointer to the buffer to be written.
• size is the number of bytes to be written.
flush
void flush(void);
baudRate
uint32_t baudRate();
setDebugOutput
This function will enable the debug output, usually from the UART0, to the USB CDC.
void setDebugOutput(bool);
enableReboot
This function enables the device to reboot by the DTR as RTS signals.
rebootEnabled
bool rebootEnabled(void);
Example Code
USBSerial
#if ARDUINO_USB_MODE
#warning This sketch should be used when USB is in OTG mode
void setup(){}
void loop(){}
#else
#include "USB.h"
#if ARDUINO_USB_CDC_ON_BOOT
#define HWSerial Serial0
(continues on next page)
if(event_base == ARDUINO_USB_EVENTS){
arduino_usb_event_data_t * data = (arduino_usb_event_data_t*)event_data;
switch (event_id){
case ARDUINO_USB_STARTED_EVENT:
HWSerial.println("USB PLUGGED");
break;
case ARDUINO_USB_STOPPED_EVENT:
HWSerial.println("USB UNPLUGGED");
break;
case ARDUINO_USB_SUSPEND_EVENT:
HWSerial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_
˓→wakeup_en);
break;
case ARDUINO_USB_RESUME_EVENT:
HWSerial.println("USB RESUMED");
break;
default:
break;
}
} else if(event_base == ARDUINO_USB_CDC_EVENTS){
arduino_usb_cdc_event_data_t * data = (arduino_usb_cdc_event_data_t*)event_data;
switch (event_id){
case ARDUINO_USB_CDC_CONNECTED_EVENT:
HWSerial.println("CDC CONNECTED");
break;
case ARDUINO_USB_CDC_DISCONNECTED_EVENT:
HWSerial.println("CDC DISCONNECTED");
break;
case ARDUINO_USB_CDC_LINE_STATE_EVENT:
HWSerial.printf("CDC LINE STATE: dtr: %u, rts: %u\n", data->line_state.dtr, data-
˓→>line_state.rts);
break;
case ARDUINO_USB_CDC_LINE_CODING_EVENT:
HWSerial.printf("CDC LINE CODING: bit_rate: %u, data_bits: %u, stop_bits: %u,␣
˓→parity: %u\n", data->line_coding.bit_rate, data->line_coding.data_bits, data->line_
˓→coding.stop_bits, data->line_coding.parity);
break;
case ARDUINO_USB_CDC_RX_EVENT:
HWSerial.printf("CDC RX [%u]:", data->rx.len);
{
uint8_t buf[data->rx.len];
size_t len = USBSerial.read(buf, data->rx.len);
HWSerial.write(buf, len);
(continues on next page)
default:
break;
}
}
}
void setup() {
HWSerial.begin(115200);
HWSerial.setDebugOutput(true);
USB.onEvent(usbEventCallback);
USBSerial.onEvent(usbEventCallback);
USBSerial.begin();
USB.begin();
}
void loop() {
while(HWSerial.available()){
size_t l = HWSerial.available();
uint8_t b[l];
l = HWSerial.read(b, l);
USBSerial.write(b, l);
}
}
#endif /* ARDUINO_USB_MODE */
USB MSC
About
USB Mass Storage Class API. This class makes the device accessible as a mass storage device and allows you to transfer
data between the host and the device.
One of the examples for this mode is to flash the device by dropping the firmware binary like a flash memory device
when connecting the ESP32 to the host computer.
APIs
begin
This function is used to start the peripheral using the default MSC configuration.
Where:
• block_count set the disk sector count.
• block_size set the disk sector size.
This function will return true if the configuration was successful.
end
This function will finish the peripheral as MSC and release all the allocated resources. After calling end you need to
use begin again in order to initialize the USB MSC driver again.
void end();
vendorID
productID
productRevision
mediaPresent
onStartStop
onRead
onWrite
Example Code
FirmwareMSC
#if ARDUINO_USB_MODE
#warning This sketch should be used when USB is in OTG mode
void setup(){}
void loop(){}
#else
#include "USB.h"
#include "FirmwareMSC.h"
#if !ARDUINO_USB_MSC_ON_BOOT
FirmwareMSC MSC_Update;
#endif
#if ARDUINO_USB_CDC_ON_BOOT
#define HWSerial Serial0
#define USBSerial Serial
#else
#define HWSerial Serial
(continues on next page)
if(event_base == ARDUINO_USB_EVENTS){
arduino_usb_event_data_t * data = (arduino_usb_event_data_t*)event_data;
switch (event_id){
case ARDUINO_USB_STARTED_EVENT:
HWSerial.println("USB PLUGGED");
break;
case ARDUINO_USB_STOPPED_EVENT:
HWSerial.println("USB UNPLUGGED");
break;
case ARDUINO_USB_SUSPEND_EVENT:
HWSerial.printf("USB SUSPENDED: remote_wakeup_en: %u\n", data->suspend.remote_
˓→wakeup_en);
break;
case ARDUINO_USB_RESUME_EVENT:
HWSerial.println("USB RESUMED");
break;
default:
break;
}
} else if(event_base == ARDUINO_FIRMWARE_MSC_EVENTS){
arduino_firmware_msc_event_data_t * data = (arduino_firmware_msc_event_data_t*)event_
˓→data;
switch (event_id){
case ARDUINO_FIRMWARE_MSC_START_EVENT:
HWSerial.println("MSC Update Start");
break;
case ARDUINO_FIRMWARE_MSC_WRITE_EVENT:
//HWSerial.printf("MSC Update Write %u bytes at offset %u\n", data->write.size,␣
˓→data->write.offset);
HWSerial.print(".");
break;
case ARDUINO_FIRMWARE_MSC_END_EVENT:
HWSerial.printf("\nMSC Update End: %u bytes\n", data->end.size);
break;
case ARDUINO_FIRMWARE_MSC_ERROR_EVENT:
HWSerial.printf("MSC Update ERROR! Progress: %u bytes\n", data->error.size);
break;
case ARDUINO_FIRMWARE_MSC_POWER_EVENT:
HWSerial.printf("MSC Update Power: power: %u, start: %u, eject: %u", data->power.
˓→power_condition, data->power.start, data->power.load_eject);
break;
default:
break;
}
}
(continues on next page)
void setup() {
HWSerial.begin(115200);
HWSerial.setDebugOutput(true);
USB.onEvent(usbEventCallback);
MSC_Update.onEvent(usbEventCallback);
MSC_Update.begin();
USBSerial.begin();
USB.begin();
}
void loop() {
// put your main code here, to run repeatedly
}
#endif /* ARDUINO_USB_MODE */
USB Common
onEvent
VID
Set the Vendor ID. This 16 bits identification is used to identify the company that develops the product.
Note: You can’t define your own VID. If you need your own VID, you need to buy one. See https://www.usb.org/
getting-vendor-id for more details.
uint16_t VID(void);
Returns the Vendor ID. The default value for the VID is: 0x303A.
PID
Set the Product ID. This 16 bits identification is used to identify the product.
uint16_t PID(void);
firmwareVersion
uint16_t firmwareVersion(void);
Return the 16 bits unsigned value. The default value is: 0x100.
usbVersion
uint16_t usbVersion(void);
Return the USB version. The default value is: 0x200 (USB 2.0).
usbPower
Note: This configuration does not change the physical power output. This is only used for the USB device information.
uint16_t usbPower(void);
Return the current in mA. The default value is: 0x500 (500mA).
usbClass
uint8_t usbClass(void);
usbSubClass
uint8_t usbSubClass(void);
usbProtocol
uint8_t usbProtocol(void);
usbAttributes
uint8_t usbAttributes(void);
webUSB
bool webUSB(void);
productName
manufacturerName
serialNumber
webUSBURL
enableDFU
bool enableDFU();
begin
This function is used to start the peripheral using the default configuration.
bool begin();
Example Code
There are a collection of USB device examples on the project GitHub, including Firmware MSC update, USB CDC,
HID and composite device.
About
The Wi-Fi API provides support for the 802.11b/g/n protocol driver. This API includes:
• Station mode (STA mode or Wi-Fi client mode). ESP32 connects to an access point
• AP mode (aka Soft-AP mode or Access Point mode). Devices connect to the ESP32
• Security modes (WPA2, WPA3 etc.)
• Scanning for access points
Working as AP
In this mode, the ESP32 is configured as an Access Point (AP) and it’s capable of receiving incoming connections from
other devices (stations) by providing a Wi-Fi network.
This mode can be used for serving an HTTP or HTTPS server inside the ESP32, for example.
Working as STA
The STA mode is used to connect the ESP32 to a Wi-Fi network, provided by an Access Point.
This is the mode to be used if you want to connect your project to the Internet.
API Description
Common API
Here are the common APIs that are used for both modes, AP and STA.
useStaticBuffers
This function is used to set the memory allocation mode for the Wi-Fi buffers.
setDualAntennaConfig
Configures the Dual antenna functionallity. This function should be used only on the ESP32-WROOM-DA module
or any other ESP32 with RF switch.
• gpio_ant1 Configure the GPIO number for the antenna 1 connected to the RF switch (default GPIO2 on ESP32-
WROOM-DA)
• gpio_ant2 Configure the GPIO number for the antenna 2 connected to the RF switch (default GPIO25 on ESP32-
WROOM-DA)
• rx_mode Set the RX antenna mode. See wifi_rx_ant_t for the options.
• tx_mode Set the TX antenna mode. See wifi_tx_ant_t for the options.
Return true if the configuration was successful.
For the rx_mode you can use the following configuration:
• WIFI_RX_ANT0 Selects the antenna 1 for all RX activity.
• WIFI_RX_ANT1 Selects the antenna 2 for all RX activity.
• WIFI_RX_ANT_AUTO Selects the antenna for RX automatically.
For the tx_mode you can use the following configuration:
• WIFI_TX_ANT0 Selects the antenna 1 for all TX activity.
• WIFI_TX_ANT1 Selects the antenna 2 for all TX activity.
• WIFI_TX_ANT_AUTO Selects the antenna for TX automatically.
WiFiAP
The WiFiAP is used to configure and manage the Wi-Fi as an Access Point. This is where you can find the related
functions for the AP.
Basic Usage
WiFi.softAP(ssid, password);
AP Configuration
softAP
bool softAP(const char* ssid, const char* passphrase = NULL, int channel = 1, int ssid_
˓→hidden = 0, int max_connection = 4, bool ftm_responder = false);
Where:
• ssid sets the Wi-Fi network SSID.
• passphrase sets the Wi-Fi network password. If the network is open, set as NULL.
• channel configures the Wi-Fi channel.
• ssid_hidden sets the network as hidden.
• max_connection sets the maximum number of simultaneous connections. The default is 4.
• ftm_responder sets the Wi-Fi FTM responder feature. Only for ESP32-S2 and ESP32-C3 SoC!
Return true if the configuration was successful.
softAPConfig
Function used to configure the IP as static (fixed) as well as the gateway and subnet.
Where:
• local_ip sets the local IP address.
• gateway sets the gateway IP.
• subnet sets the subnet mask.
The function will return true if the configuration is successful.
AP Connection
softAPdisconnect
Where:
• wifioff sets the Wi-Fi off if true.
The function will return true if the configuration is successful.
softAPgetStationNum
uint8_t softAPgetStationNum();
softAPIP
IPAddress softAPIP();
softAPBroadcastIP
IPAddress softAPBroadcastIP();
softAPNetworkID
IPAddress softAPNetworkID();
softAPSubnetCIDR
uint8_t softAPSubnetCIDR();
softAPSubnetMask
IPAddress softAPSubnetMask();
softAPenableIpV6
bool softAPenableIpV6();
softAPIPv6
IPv6Address softAPIPv6();
softAPgetHostname
softAPsetHostname
Where:
• hostname sets the device hostname.
The function will return true if the configuration is successful.
softAPmacAddress
Where:
• mac sets the new MAC address.
Function to get the AP MAC address.
String softAPmacAddress(void);
softAPSSID
WiFiSTA
The WiFiSTA is used to configure and manage the Wi-Fi as Station. The related functions for the STA are here.
Basic Usage
The following code shows the basic usage of the WifiSTA functionality.
WiFi.begin(ssid, password);
Where the ssid and password are from the network you want to connect the ESP32.
To check if the connection is successful, you can use:
After a successful connection, you can print the IP address given by the network.
Please see the full example of the WiFiSTA in: sta example.
STA Configuration
begin
wl_status_t begin(const char* ssid, const char *passphrase = NULL, int32_t channel = 0,␣
˓→const uint8_t* bssid = NULL, bool connect = true);
Where:
• ssid sets the AP SSID.
• passphrase sets the AP password. Set as NULL for open networks.
• channel sets the Wi-Fi channel.
• uint8_t* bssid sets the AP BSSID.
• connect sets true to connect to the configured network automatically.
wl_status_t begin(char* ssid, char *passphrase = NULL, int32_t channel = 0, const uint8_
˓→t* bssid = NULL, bool connect = true);
Where:
• ssid sets the AP SSID.
• passphrase sets the AP password. Set as NULL for open networks.
• channel sets the Wi-Fi channel.
• bssid sets the AP BSSID.
• connect sets true to connect to the configured network automatically.
Function to start the connection after being configured.
wl_status_t begin();
config
Function config is used to configure Wi-Fi. After configuring, you can call function begin to start the Wi-Fi process.
Where:
• local_ip sets the local IP.
• gateway sets the gateway IP.
• subnet sets the subnet mask.
• dns1 sets the DNS.
• dns2 sets the DNS alternative option.
The function will return true if the configuration is successful.
The IPAddress format is defined by 4 bytes as described here:
Example:
See the WiFiClientStaticIP.ino for more details on how to use this feature.
STA Connection
reconnect
bool reconnect();
disconnect
Where:
• wifioff use true to turn the Wi-Fi radio off.
• eraseap use true to erase the AP configuration from the NVS memory.
The function will return true if the configuration is successful.
isConnected
bool isConnected();
setAutoConnect
Function is deprecated.
getAutoConnect
Function is deprecated.
setAutoReconnect
Where:
• autoConnect is set to true to enable this option.
getAutoReconnect
bool getAutoReconnect();
setMinSecurity
Where:
• minSecurity is the minimum security for AP to be considered connectable. Default is WIFI_AUTH_WPA2_PSK.
WiFiMulti
The WiFiMulti allows you to add more than one option for the AP connection while running as a station.
To add the AP, use the following function. You can add multiple AP’s and this library will handle the connection.
To see how to use the WiFiMulti, take a look at the WiFiMulti.ino example available.
WiFiScan
To perform the Wi-Fi scan for networks, you can use the following functions:
Start scan WiFi networks available.
int16_t scanNetworks(bool async = false, bool show_hidden = false, bool passive = false,␣
˓→uint32_t max_ms_per_chan = 300, uint8_t channel = 0);
int16_t scanComplete();
void scanDelete();
To see how to use the WiFiScan, take a look at the WiFiScan.ino example available.
Examples
Wi-Fi AP Example
/*
WiFiAccessPoint.ino creates a WiFi access point and provides a web server on it.
Steps:
1. Connect to the access point "yourAp"
2. Point your web browser to http://192.168.4.1/H to turn the LED on or http://192.168.
˓→4.1/L to turn it off
OR
Run raw TCP "GET /H" and "GET /L" on PuTTY terminal with 192.168.4.1 as IP address␣
˓→and 80 as port
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#define LED_BUILTIN 2 // Set the GPIO pin where you connected your test LED or comment␣
˓→this line out if your dev board has a built-in LED
WiFiServer server(80);
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
Serial.println();
Serial.println("Configuring access point...");
// You can remove the password parameter if you want the AP to be open.
// a valid password must have more than 7 characters
if (!WiFi.softAP(ssid, password)) {
log_e("Soft AP creation failed.");
while(1);
}
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin();
Serial.println("Server started");
(continues on next page)
void loop() {
WiFiClient client = server.available(); // listen for incoming clients
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /H")) {
digitalWrite(LED_BUILTIN, HIGH); // GET /H turns the LED on
}
if (currentLine.endsWith("GET /L")) {
digitalWrite(LED_BUILTIN, LOW); // GET /L turns the LED off
}
}
}
// close the connection:
client.stop();
Serial.println("Client Disconnected.");
(continues on next page)
/*
Go to thingspeak.com and create an account if you don't have one already.
After logging in, click on the "New Channel" button to create a new channel for your␣
˓→data. This is where your data will be stored and displayed.
Fill in the Name, Description, and other fields for your channel as desired, then␣
˓→click the "Save Channel" button.
Take note of the "Write API Key" located in the "API keys" tab, this is the key you␣
˓→will use to send data to your channel.
Replace the channelID from tab "Channel Settings" and privateKey with "Read API Keys
˓→" from "API Keys" tab.
Replace the host variable with the thingspeak server hostname "api.thingspeak.com"
Upload the sketch to your ESP32 board and make sure that the board is connected to␣
˓→the internet. The ESP32 should now send data to your Thingspeak channel at the␣
Go to the channel view page on thingspeak and check the "Field1" for the new␣
˓→incoming data.
You can use the data visualization and analysis tools provided by Thingspeak to␣
˓→display and process your data in various ways.
*/
#include <WiFi.h>
void setup()
{
(continues on next page)
Serial.println();
Serial.println("******************************************************");
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
// Read all the lines of the reply from server and print them to Serial
while(client->available()) {
String line = client->readStringUntil('\r');
Serial.print(line);
}
Serial.printf("\nClosing connection\n\n");
}
void loop(){
WiFiClient client;
String footer = String(" HTTP/1.1\r\n") + "Host: " + String(host) + "\r\n" +
˓→"Connection: close\r\n\r\n";
// WRITE ------------------------------------------------------------------------------
˓→ --------------
if (!client.connect(host, httpPort)) {
return;
}
(continues on next page)
// READ -------------------------------------------------------------------------------
˓→ -------------
if (!client.connect(host, httpPort)) {
return;
}
client.print(readRequest);
readResponse(&client);
// ------------------------------------------------------------------------------------
˓→ -------------
++field1;
delay(10000);
}
References
THREE
GUIDES
There are 2 primary approaches and both of them involve editing file configs/defconfig.common. Edit the file
directly and then build. Later you can git restore configs/defconfig.common to go back. Copy the file cp
configs/defconfig.common configs/defconfig.debug and edit the debug version.
vim configs/defconfig.common or vim configs/defconfig.debug
Edit line 44 containing by default CONFIG_LOG_DEFAULT_LEVEL_ERROR=y to one of the following lines depending
on your desired log level:
CONFIG_LOG_DEFAULT_LEVEL_NONE=y # No output
CONFIG_LOG_DEFAULT_LEVEL_ERROR=y # Errors - default
CONFIG_LOG_DEFAULT_LEVEL_WARN=y # Warnings
CONFIG_LOG_DEFAULT_LEVEL_INFO=y # Info
CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y # Debug
CONFIG_LOG_DEFAULT_LEVEL_VERBOSE=y # Verbose
Then simply build the libs for all SoCs or one specific SoC. Note that building for all SoCs takes a lot of time, so if you
are working only with specific SoC(s), build only for those.
Note: If you have copied the defconfig file and the debug settings are in file configs/defconfig.debug add flag
debug to compilation command. Example : ./build.sh debug
• Option 1: Build for all SoCs: ./build.sh
• Option 2: Build for one SoC: ./build.sh -t <soc>. The exact text to choose the SoC:
– esp32
– esp32s2
– esp32c3
– esp32s3
– Example: ./build.sh -t esp32
– A wrong format or non-existing SoC will result in the error sed: can’t read sdkconfig: No such file or
directory
177
Arduino-ESP32, Release 2.0.6
3.2.1 Introduction
This is a guideline for the Arduino ESP32 project documentation. The idea for this guideline is to show how to start
collaborating on the project.
The guideline works to give you the directions and to keep the documentation more concise, helping users to better
understand the structure.
This documentation is based on the Sphinx with reStructuredText and hosted by ReadTheDocs.
If you want to get started with Sphinx, see the official documentation:
• Documentation Index
• Basics
• Directives
First Steps
Before starting your collaboration, you need to get the documentation source code from the Arduino-ESP32 project.
• Step 1 - Fork the Arduino-ESP32 to your GitHub account.
• Step 2 - Check out the recently created fork.
• Step 3 - Create a new branch for the changes/addition to the docs.
• Step 4 - Write!
Requirements
To properly work with the documentation, you need to install some packages in your system.
If you are using the Visual Studio Code, you can install some extensions to help you while writing documentation.
reStructuredText Pack
We also recommend you install to grammar check extension to help you to review English grammar.
Grammarly
Building
To build the documentation and generate the HTLM files, you can use the following command inside the docs folder.
After a successful build, you can check the files inside the build/html folder.
make html
This step is essential to ensure that there are no syntax errors and also to see the final result.
If everything is ok, you will see some output logs similar to this one:
3.2.5 Sections
The Arduino ESP32 is structured in some sections to make it easier to maintain. Here is a brief description of this
structure.
API
In this section, you will include all the documentation about drivers, libraries, and any other related to the core.
In this section, we do not add general information. For more general information, we have sections for other related
parts, like the FAQ, library builder, troubleshooting, etc.
Boards
Here is the place to add any special guide on the development boards, pin layout, schematics, and any other relevant
content.
Common
In this folder, you can add all common information used in several different places. This helps to make documentation
easily maintainable.
Guides
This is the place to add the guides for common applications, IDEs configuration, and any other information that can be
used as a guideline.
Tutorials
If you want to add a specific tutorial related to the Arduino core for ESP32, this is the place. The intention is not to
create a blog or a demo area, but this can be used to add some complex description or to add some more information
about APIs.
All the files used on the documentation must be stored in the _static folder. Be sure that the content used is not with
any copyright restriction.
Here are some guidelines to help you. We also recommend copying a sample file from the same category you are
creating.
This will help you to follow the structure as well as to get inspired.
Basic Structure
To help you create a new section from scratch, we recommend you include this structure in your content if it applies.
• About - Brief description of the document.
– Description of the peripheral, driver, protocol, including all different modes and configurations.
• API - Description of each public function, macros, and structs.
• Basic Usage
• Example Application
About Section
In this section, you need to add a brief description of the API. If you are describing a peripheral API, you should explain
a little bit about the peripheral and the working modes, if it’s applicable.
API Functions
To add a new function description, you must know that the users only have access to the public functions.
Here is an example of how to add the function description from I2C API:
setPins
^^^^^^^
.. note:: Call this function before ``begin`` to change the pins from the default ones.
.. code-block:: arduino
* ``sdaPin`` sets the GPIO to be used as the I2C peripheral data line.
* ``sclPin`` sets the GPIO to be used as the I2C peripheral clock line.
The default pins may vary from board to board. On the *Generic ESP32* the default I2C␣
˓→pins are:
* ``sdaPin`` **GPIO21**
* ``sclPin`` **GPIO22**
This function will return ``true`` if the peripheral was configured correctly.
Be sure to include a very comprehensive description, add all the parameters in and out, and describe the desired output.
If the function uses a specific structure, you can also describe the structure in the same function block or add a specific
section if the structure is shared with other functions.
Basic Usage
Some APIs are more complex to use or require more steps in order to configure or initialize. If the API is not straightfor-
ward in terms of usability, please consider adding a how-to-use section describing all the steps to get the API configured.
Here is an example:
Basic Usage
^^^^^^^^^^^
To start using I2C as slave mode on the Arduino, the first step is to include the ``Wire.
˓→h`` header to the sketch.
.. code-block:: arduino
#include "Wire.h"
Before calling ``begin``, you must create two callback functions to handle the␣
˓→communication with the master device.
.. code-block:: arduino
Wire.onReceive(onReceive);
and
.. code-block:: arduino
Wire.onRequest(onRequest);
The ``onReceive`` will handle the request from the ``master`` device upon a slave read␣
˓→request and the ``onRequest`` will handle the answer to the master.
Now, we can start the peripheral configuration by calling ``begin`` function with the␣
˓→device address.
.. code-block:: arduino
Wire.begin((uint8_t)I2C_DEV_ADDR);
By using ``begin`` without any arguments, all the settings will be done by using the␣
˓→default values. To set the values on your own, see the function description. This␣
Example Application
It is very important to include at least one application example or a code snippet to help people using the API.
If the API does not have any application example, you can embed the code directly. However, if the example is available,
you must include it as a literal block.
.. literalinclude:: ../../../libraries/WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino
:language: arduino
Heading Levels
Code Block
.. code-block:: arduino
bool begin(); //Code example
Links
• Second option:
Images
To include images in the docs, first, add all the files into the _static folder with a filename that makes sense for the
topic.
After that, you can use the following structure to include the image in the docs.
.. figure:: ../_static/arduino_i2c_master.png
:align: center
:width: 720
:figclass: align-center
Support
If you need support on the documentation, you can ask a question in the discussion here.
If you want to contribute with code on the Arduino ESP32 core, be sure to follow the ESP-IDF Documenting Code as
a reference.
3.3.1 Introduction
This guide is a walkthrough of the Arduino IDE configuration menu for the ESP32 System on Chip (SoC’s). In this
guide, you will see the most relevant configuration to get your project optimized and working.
Since some boards and SoC’s may vary in terms of hardware configuration, be sure you know all the board character-
istics that you are using, like flash memory size, SoC variant (ESP32 family), PSRAM, etc.
Note: To help you identify the characteristics, you can see the Espressif Product Selector.
The Arduino IDE is widely used for ESP32 on Arduino development and offers a wide variety of configurations.
To properly configure your project build and flash, some settings must be done in order to get it compiled and flashed
without any issues. Some boards are natively supported and almost no configuration is required. However, if your is
not yet supported or you have a custom board, you need to configure the environment by yourself.
For more details or to add a new board, see the boards.txt file.
Most of the options are available for every ESP32 family. Some options will be available only for specific targets, like
the USB configuration.
Board
This option is the target board and must be selected in order to get all the default configuration settings. Once you select
the correct board, you will see that some configurations will be automatically selected, but be aware that some boards
can have multiple versions (i.e different flash sizes).
To select the board, go to Tools -> Board -> ESP32 Arduino and select the target board.
If your board is not present on this list, you can select the generic ESP32-XX Dev Module.
Currently, we have one generic development module for each of the supported targets.
If the board selected belongs to another SoC family, you will see the following information at the build output:
A fatal error occurred: This chip is ESP32 not ESP32-S2. Wrong --chip
argument?
Upload Speed
To select the flashing speed, change the Tools -> Upload Speed. This value will be used for flashing the code to
the device.
Note: If you have issues while flashing the device at high speed, try to decrease this value. This could be due to the
external serial-to-USB chip limitations.
CPU Frequency
On this option, you can select the CPU clock frequency. This option is critical and must be selected according to the
high-frequency crystal present on the board and the radio usage (Wi-Fi and Bluetooth).
In some applications, reducing the CPU clock frequency is recommended in order to reduce power consumption.
If you don’t know why you should change this frequency, leave the default option.
Flash Frequency
Use this function to select the flash memory frequency. The frequency will be dependent on the memory model.
• 40MHz
• 80MHz
If you don’t know if your memory supports 80Mhz, you can try to upload the sketch using the 80MHz option and
watch the log output via the serial monitor.
Note: In some boards/SoC, the flash frequency is automatically selected according to the flash mode. In some cases
(i.e ESP32-S3), the flash frequency is up to 120MHz.
Flash Mode
This option is used to select the SPI communication mode with the flash memory.
Depending on the application, this mode can be changed in order to increase the flash communication speed.
• QIO - Quad I/O Fast Read
– Four SPI pins are used to write to the flash and to read from the flash.
• DIO - Dual I/O Fast Read
– Two SPI pins are used to write to the flash and to read from the flash.
• QOUT - Quad Output Fast Read
– Four SPI pins are used to read the flash data.
• DOUT - Dual Output Fast Read
– Two SPI pins are used to read flash data.
• OPI - Octal I/O
– Eight SPI pins are used to write and to read from the flash.
If you don’t know how the board flash is physically connected or the flash memory model, try the QIO at 80MHz first.
Flash Size
This option is used to select the flash size. The flash size should be selected according to the flash model used on your
board.
• 2MB (16Mb)
• 4MB (32Mb)
• 8MB (64Mb)
• 16MB (128Mb)
If you choose the wrong size, you may have issues when selecting the partition scheme.
Embedded Flash
Note: Check the manufacturer part number of your SoC/module to see the right version.
Example: ESP32-S3FH4R2
This particular ESP32-S3 variant comes with 4MB Flash and 2MB PSRAM.
Options for Embedded Flash
• Fx4 4MB Flash (QIO)
• Fx8 8MB Flash (QIO)
• V 1.8V SPI
The x stands for the temperature range specification.
• H High Temperature (-40 to 85ºC)
• N Low Temeprature (-40 to 65ºC)
For more details, please see the corresponding datasheet at Espressif Product Selector.
Partition Scheme
This option is used to select the partition model according to the flash size and the resources needed, like storage area
and OTA (Over The Air updates).
Note: Be careful selecting the right partition according to the flash size. If you select the wrong partition, the system
will crash.
This option is used to select the Arduino core debugging level to be printed to the serial debug.
• None - Prints nothing.
• Error - Only at error level.
• Warning - Only at warning level and above.
• Info - Only at info level and above.
• Debug - Only at debug level and above.
• Verbose - Prints everything.
PSRAM
The PSRAM is an internal or external extended RAM present on some boards, modules or SoC.
This option can be used to Enable or Disable PSRAM. In some SoCs, you can select the PSRAM mode as the
following.
• QSPI PSRAM - Quad PSRAM
• OPI PSRAM - Octal PSRAM
Embedded PSRAM
Arduino Runs On
This function is used to select the core that runs the Arduino core. This is only valid if the target SoC has 2 cores.
When you have some heavy task running, you might want to run this task on a different core than the Arduino tasks.
For this reason, you have this configuration to select the right core.
Events Run On
This function is also used to select the core that runs the Arduino events. This is only valid if the target SoC has 2 cores.
This option selects the flash memory region to be erased before uploading the new sketch.
• Disabled - Upload the sketch without erasing all flash contents. (Default)
• Enabled - Erase all flash contents before uploading the sketch.
Port
This option is used to select the serial port to be used on the flashing and monitor.
Some ESP32 families have a USB peripheral. This peripheral can be used for flashing and debugging.
To see the supported list for each SoC, see this section: Libraries.
The USB option will be available only if the correct target is selected.
The USB Communications Device Class, or USB CDC, is a class used for basic communication to be used as a regular
serial controller (like RS-232).
This class is used for flashing the device without any other external device attached to the SoC.
This option can be used to Enable or Disable this function at the boot. If this option is Enabled, once the device is
connected via USB, one new serial port will appear in the list of the serial ports. Use this new serial port for flashing
the device.
This option can be used as well for debugging via the Serial Monitor using CDC instead of the UART0.
To use the UART as serial output, you can use Serial0.print("Hello World!"); instead of Serial.
print("Hello World!"); which will be printed using USB CDC.
The USB Mass Storage Class, or USB MSC, is a class used for storage devices, like a USB flash drive.
This option can be used to Enable or Disable this function at the boot. If this option is Enabled, once the device is
connected via USB, one new storage device will appear in the system as a storage drive. Use this new storage drive to
write and read files or to drop a new firmware binary to flash the device.
The USB Device Firmware Upgrade is a class used for flashing the device through USB.
This option can be used to Enable or Disable this function at the boot. If this option is Enabled, once the device is
connected via USB, the device will appear as a USB DFU capable device.
FOUR
TUTORIALS
4.1.1 Introduction
This is the basic tutorial and should be used as template for other tutorials.
4.1.2 Requirements
• Arduino IDE
• ESP32 Board
• Good USB Cable
4.1.3 Steps
4.1.4 Code
Listing 1: Blink.ino
/*
Blink
Turns an LED on for one second, then off for one second, repeatedly.
Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your Arduino
model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
191
Arduino-ESP32, Release 2.0.6
http://www.arduino.cc/en/Tutorial/Blink
*/
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
If the log output from the serial monitor is relevant, please add here:
4.1.6 Resources
4.2.1 Introduction
This is the interactive blink tutorial using Wokwi. For this tutorial, you don’t need the ESP32 board or the Arduino
toolchain.
Note: If you don’t want to use this tutorial with the simulation, you can copy and paste the Example Code from Wokwi
editor and use it on the Arduino IDE or PlatformIO.
This tutorial is the most basic for any get started. In this tutorial, we will show how to set a GPIO pin as an output to
drive a LED to blink each 1 second.
In order to make this simple blink tutorial, you’ll need to do the following steps.
1. Define the GPIO for the LED.
#define LED 2
This #define LED 2 will be used to set the GPIO2 as the LED output pin.
2. Setup.
Inside the setup() function, we need to add all things we want to run once during the startup. Here we’ll add the
pinMode function to set the pin as output.
void setup() {
pinMode(LED, OUTPUT);
}
The first argument is the GPIO number, already defined and the second is the mode, here defined as an output.
3. Main Loop.
After the setup, the code runs the loop function infinitely. Here we will handle the GPIO in order to get the LED
blinking.
void loop() {
digitalWrite(LED, HIGH);
delay(100);
digitalWrite(LED, LOW);
delay(100);
}
4.2.4 Simulation
This simulator is provided by Wokwi and you can test the blink code and play with some modifications to learn more
about this example.
Change the parameters, like the delay period, to test the code right on your browser. You can add more LEDs, change
the GPIO, and more.
#define LED 2
void setup() {
pinMode(LED, OUTPUT);
}
void loop() {
digitalWrite(LED, HIGH);
delay(100);
digitalWrite(LED, LOW);
delay(100);
}
4.2.6 Resources
4.3.1 Introduction
Since the ESP32-S2 introduction, Espressif has been working on USB peripheral support for some of the SoC families,
including the ESP32-C3 and the ESP32-S3.
This new peripheral allows a lot of new possibilities, including flashing the firmware directly to the SoC without any
external USB-to-Serial converter.
In this tutorial, you will be guided on how to use the embedded USB to flash the firmware.
The current list of supported SoCs:
It’s important that your board includes the USB connector attached to the embedded USB from the SoC. If your board
doesn’t have the USB connector, you can attach an external one to the USB pins.
These instructions it will only work on the supported devices with the embedded USB peripheral. This tutorial will
not work if you are using an external USB-to-serial converter like FTDI, CP2102, CH340, etc.
For a complete reference to the Arduino IDE tools menu, please see the Tools Menus reference guide.
The USB DFU (Device Firmware Upgrade) is a class specification from the USB standard that adds the ability to
upgrade the device firmware by the USB interface.
Note: DFU is only supported by the ESP32-S2 and ESP32-S3. See the table of supported SoCs.
To use the USB DFU to flash the device, you will need to configure some settings in the Arduino IDE according to the
following steps:
1. Enter into Download Mode manually
This step is done only for the first time you flash the firmware in this mode. To enter into the download mode, you need
to press and hold BOOT button and press and release the RESET button.
To check if this procedure was done correctly, now you will see the new USB device listed in the available ports. Select
this new device in the Port option.
2. Configure the USB DFU
In the next step you can set the USB DFU as default on BOOT and for flashing.
Go to the Tools menu in the Arduino IDE and set the following options:
For ESP32-S2
• USB DFU On Boot -> Enable
• Upload Mode -> Internal USB
For ESP32-S3
• USB Mode -> USB-OTG (TinyUSB)
• USB DFU On Boot -> Enabled
Setp 3 - Flash
Now you can upload your sketch to the device. After flashing, you need to manually reset the device.
Note: On the USB DFU, you can’t use the USB for the serial output for the logging, just for flashing. To enable the
serial output, use the CDC option instead. If you want to use the USB DFU for just upgrading the firmware using the
manual download mode, this will work just fine, however, for developing please consider using USB CDC.
The USB CDC (Communications Device Class) allows you to communicate to the device like in a serial interface. This
mode can be used on the supported targets to flash and monitor the device in a similar way on devices that uses the
external serial interfaces.
To use the USB CDC, you need to configure your device in the Tools menu:
1. Enter into Download Mode manually
Similar to the DFU mode, you will need to enter into download mode manually. To enter into the download mode, you
need to press and hold BOOT button and press and release the RESET button.
To check if this procedure was done correctly, now you will see the new USB device listed in the available ports. Select
this new device in the Port option.
2. Configure the USB CDC
For ESP32-S2
• USB CDC On Boot -> Enabled
• Upload Mode -> Internal USB
For ESP32-C3
• USB CDC On Boot -> Enabled
For ESP32-S3
• USB CDC On Boot -> Enabled
• Upload Mode -> UART0 / Hardware CDC
3. Flash and Monitor
You can now upload your sketch to the device. After flashing for the first time, you need to manually reset the device.
This procedure enables the flashing and monitoring thought the internal USB and does not requires you to manually
enter into the download mode or to do the manual reset after flashing.
To monitor the device, you need to select the USB port and open the Monitor tool selecting the correct baud rate (usually
115200) according to the Serial.begin() defined in your code.
4.3.4 Hardware
If you are developing a custom hardware using the compatible SoC, and want to remove the external USB-to-Serial
chip, this feature will complete substitute the needs of the external chip. See the SoC datasheet for more details about
this peripheral.
4.4.1 Introduction
This is a basic introduction to how the peripherals work in the ESP32. This tutorial can be used to understand how to
define the peripheral usage and its corresponding pins.
In some microcontrollers’ architecture, the peripherals are attached to specific pins and cannot be redefined to another
one.
For example:
The XYZ MCU defines that the I2C peripheral SDA signal is the IO5 on the physical pin 10 and the SCL is on the IO6
and physical pin 11.
This means that, in your hardware project, you NEED to use these pins as the I2C and this cannot be changed due to
the internal architecture. In this case, you must be very careful during the hardware design to not make any mistake by
switching the SDA and SCL connections. Firmware will not help you if you do so.
The ESP32 architecture includes the capability of configuring some peripherals to any of the GPIOs pins, managed by
the IO MUX GPIO. Essentially, this capability means that we can route the internal peripheral into a different physical
pin using the IO MUX and the GPIO Matrix.
It means that in the scenario of the XYZ MCU, in the ESP32 we can use any of the GPIOs to route the SDA (input/output)
and the SCL (output).
To use this functionality, we must be aware of some precautions:
• Some of the GPIOs are INPUT only.
• Some peripherals have output signals and must be used on GPIO’s capable to be configured as OUTPUT.
• Some peripherals, mostly the high speed ones, ADC, DAC, Touch, and JTAG use dedicated GPIOs pins.
Warning: Before assigning the peripheral pins in your design, double check if the pins you’re using are appropriate.
The input-only pins cannot be used for peripherals that require output or input/output signals.
The greatest advantage of this functionality is the fact that we don’t need to be fully dependent on the physical pin,
since we can change according to our needs. This can facilitate the hardware design routing or in some cases, fix some
4.4.3 Peripherals
Here is the basic peripherals list present on the ESP32. The peripheral list may vary from each ESP32 SoC family. To
see all peripherals available on the ESP32-S2 and ESP32-C3, check each of the datasheets.
Peripheral Table
Type Function
ADC Dedicated GPIOs
DAC Dedicated GPIOs
Touch Sensor Dedicated GPIOs
JTAG Dedicated GPIOs
SD/SDIO/MMC HostController Dedicated GPIOs
Motor PWM Any GPIO
SDIO/SPI SlaveController Dedicated GPIOs
UART Any GPIO[1]
I2C Any GPIO
I2S Any GPIO
LED PWM Any GPIO
RMT Any GPIO
GPIO Any GPIO
Parallel QSPI Dedicated GPIOs
EMAC Dedicated GPIOs
Pulse Counter Any GPIO
TWAI Any GPIO
USB Dedicated GPIOs
In the Arduino Uno, we have the I2C pins defined by hardware, A4 is the SDA and A5 the SCL. In this case, we do not
need to set these pins in the Wire.begin(); function, because they are already into the Wire library.
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
}
Now, for the ESP32, the default pins for the I2C are SDA (GPIO21) and SCL (GPIO22). We can use a different pin as
alternative for the default ones if you need to change the pins. To change the pins, we must call the Wire.setPins(int
sda, int scl); function before calling Wire.begin();.
4.4.5 Datasheet
• ESP32 (Datasheet)
• ESP32-S2 (Datasheet)
• ESP32-C3 (Datasheet)
• ESP32-S3 (Datasheet)
4.4.6 Resources
4.5.1 Introduction
Partition table is used to define the flash memory organization and the different kind of data will be stored on each
partition.
You can use one of the available partition table scheme or create your own. You can see all the different schemes on
the tools/partitions folder or by the Arduino IDE tools menu Tools -> Partition Scheme.
The partition table is created by a .CSV (Comma-separeted Values) file with the following structure:
Where:
1. Name
Is the partition name and must be a unique name. This name is not relevant for the system and the
size must be at maximum of 16-chars (no special chars).
2. Type
This is the type of the partition. This value can be data or app.
• app type is used to define the partition that will store the application.
• data type can be used to define the partition that stores general data, not the application.
3. SubType
The SubType defines the usage of the app and data partitions.
data
ota
The ota subtype is used to store the OTA information. This partition is used only when the
OTA is used to select the initialization partition, otherwise no need to add it to your custom
partition table. The size of this partition should be a fixed size of 8kB (0x2000 bytes).
nvs
The nvs partition subtype is used to define the partition to store general data, like the WiFi
data, device PHY calibration data and any other data to be stored on the non-volatile memory.
This kind of partition is suitable for small custom configuration data, cloud certificates, etc.
Another usage for the NVS is to store sensitive data, since the NVS supports encryption.
It is highly recommended to add at least one nvs partition, labeled with the name nvs, in
your custom partition tables with size of at least 12kB (0x3000 bytes). If needed, you can
increase the size of the nvs partition. The recommended size for this partition is from 12kb to
64kb. Although larger NVS partitions can be defined, we recommend using FAT or SPIFFS
filesystem for storage of larger amounts of data.
coredump
The coredump partition subtype is used to store the core dump on the flash. The core dump
is used to analyze critical errors like crash and panic. This function must be enabled in the
project configuration menu and set the data destination to flash. The recommended size for
this partition is 64kB (0x10000).
nvs_keys
The nvs_keys partition subtype is used to store the keys when the NVS encryption is used.
The size for this partition is 4kB (0x1000).
fat
The fat partition subtype defines the FAT filesystem usage, and it is suitable for larger data
and if this data is often updated and changed. The FAT FS can be used with wear leveling
feature to increase the erase/modification cycles per memory sector and encryption for sen-
sitive data storage, like cloud certificates or any other data that may be protected. To use
FAT FS with wear leveling see the example.
spiffs
The spiffs partition subtype defines the SPI flash filesystem usage, and it is also suitable for
larger files and it also performs the wear leveling and file system consistency check. The
SPIFFS do not support flash encryption.
app
factory
The factory partition subtype is the default application. The bootloader will set this partition
as the default application initialization if no OTA partition is found, or the OTA partitions
are empty. If the OTA partition is used, the ota_0 can be used as the default application and
the factory can be removed from the partition table to save memory space.
ota_0 to ota_15
The ota_x partition subtype is used for the Over-the air update. The OTA feature requires
at least two ota_x partition (usually ota_0 and ota_1) and it also requires the ota partition to
keep the OTA information data. Up to 16 OTA partitions can be defined but only two are
needed for basic OTA feature.
test
The test partition subtype is used for factory test procedures.
4. Offset
The offset defines the partition start address. The offset is defined by the sum of the offset and the size
of the earlier partition.
Note: Offset must be multiple of 4kB (0x1000) and for app partitions it must be aligned by 64kB (0x10000). If left
blank, the offset will be automatically calculated based on the end of the previous partition, including any necessary
alignment, however, the offset for the first partition must be always set as 0x9000 and for the first application partition
0x10000.
5. Size
Size defines the amount of memory to be allocated on the partition. The size can be formatted as
decimal, hex numbers (0x prefix), or using unit prefix K (kilo) or M (mega) i.e: 4096 = 4K = 0x1000.
6. Flags
The last column in the CSV file is the flags and it is currently used to define if the partition will be
encrypted by the flash encryption feature.
For example, the most common partition is the default_8MB.csv (see tools/partitions folder for some examples):
To create your own partition table, you can create the partitions.csv file in the same folder you created your
sketch. The build system will automatically pick the partition table file and use it instead of the predefined ones.
Here is an example you can use for a custom partition table:
This partition will use about 12MB of the 16MB flash. The offset will be automatically calculated after the first
application partition and the units are in K and M.
A alternative is to create the new partition table as a new file in the tools/partitions folder and edit the boards.txt file to
add your custom partition table.
4.5.3 Examples
2MB no OTA
4MB no OTA
4.5.4 Reference
This documentation was based on the How to use custom partition tables on ESP32 article.
4.6 Preferences
4.6.1 Introduction
The Preferences library is unique to arduino-esp32. It should be considered as the replacement for the Arduino EEP-
ROM library.
It uses a portion of the on-board non-volatile memory (NVS) of the ESP32 to store data. This data is retained across
restarts and loss of power events to the system.
Preferences works best for storing many small values, rather than a few large values. If you need to store large amounts
of data, consider using a file system library such as LitteFS.
The Preferences library is usable by all ESP32 variants.
Preferences data is stored in NVS in sections called a “namespace”. Within each namespace are a set of key-value
pairs. The “key” is the name of the data item and the “value” is, well, the value of that piece of data. Kind of like
variables. The key is the name of the variable and the value is its value. Like variables, a key-value pair has a data
type.
Multiple namespaces are permitted within NVS. The name of each namespace must be unique. The keys within that
namespace are unique to that namespace. Meaning the same key name can be used in multiple namespaces without
conflict.
Namespace and key names are case sensitive.
Each key name must be unique within a namespace.
Namespace and key names are character strings and are limited to a maximum of 15 characters.
Only one namespace can be open (in use) at a time.
String values can be stored and retrieved either as an Arduino String or as a null terminated char array (C-string).
Bytes type is used for storing and retrieving an arbitrary number of bytes in a namespace.
4.6.4 Workflow
Note: From here on when referring in general to a method used to store or retrieve data we’ll use the shorthand “putX”
and “getX” where the “X” is understood to be a Preferences Type; Bool, UInt, Char, and so on from the Preferences
Types table above.
In your sketch, first insert a declaration of a Preferences object by including a line like;
This object is used with the Preferences methods to access the namespace and the key-value pairs it contains.
A namespace is made available for use with the .begin method:
mySketchPrefs.begin("myPrefs", false)
If the namespace does not yet exist, this will create and then open the namespace myPrefs.
If the namespace already exists, this will open the namespace myPrefs.
If the second argument is false the namespace is opened in read-write (RW) mode — values can be stored in to and
retrieved from the namespace. If it is true the namespace is opened in read-only (RO) mode — values can be retrieved
from the namespace but nothing can be stored.
When the ESP32 boots, there is no inherent way to know if this is the very first time it has ever powered on or if it is a
subsequent launch and it has run its sketch before. We can use Preferences to store information that is retained across
reboots that we can read, and based on that, decide if this is a first-time run and take the required actions if so.
We do this by testing for the existence of a certain key within a namespace. If that key exists, it is safe to assume the
key was created during the first-time run of the sketch and so the namespace has already been initialized.
To determine if a key exists, use:
isKey("myTestKey")
This returns true if "myTestKey" exists in the namespace, and false if it does not.
By example, consider this code segment:
Preferences mySketchPrefs;
String doesExist;
mySketchPrefs.begin("myPrefs", false); // open (or create and then open if it does not
// yet exist) the namespace "myPrefs" in RW␣
˓→ mode.
if (doesExist == false) {
/*
If doesExist is false, we will need to create our
namespace key(s) and store a value into them.
*/
// Insert your "first time run" code to create your keys & assign their values below␣
˓→ here.
}
else {
/*
If doesExist is true, the key(s) we need have been created before
and so we can access their values as needed during startup.
*/
// Insert your "we've been here before" startup code below here.
}
To create a key, we use one of the .putX methods, matching "X" to the Preferences Type of the data we wish to store:
myPreferences.putX("myKeyName", value)
If "myKeyName" does not exist in the namespace, it is first created and then value is stored against that keyname. The
namespace must be open in RW mode to do this. Note that value is not optional and must be provided with every
“.putX” statement. Thus every key within a namespace will always hold a valid value.
An example is:
Once a key exists in a namespace and the namespace is open, its value is retrieved using one of the getX methods,
matching "X" to the type of data stored against that key.
myPreferences.getX("myKeyName")
Like so:
This will retrieve the float value from the namespace key "pi" and assign it to the float type variable myFloat.
Summary
#include <Preferences.h>
Preferences stcPrefs;
void setup() {
if (tpInit == false) {
// If tpInit is 'false', the key "nvsInit" does not yet exist therefore this
// must be our first-time run. We need to set up our Preferences namespace keys.␣
˓→So...
// The .begin() method created the "STCPrefs" namespace and since this is our
(continues on next page)
// All done. Last run state (or the factory default) is now restored.
stcPrefs.end(); // Close our preferences␣
˓→namespace.
There are a few other functions useful when working with namespaces.
preferences.clear();
preferences.remove("keyname");
• Deletes the “keyname” and value associated with it from the currently opened namespace.
– The namespace must be open in read-write mode for this to work.
– Tip: use this to remove the “test key” to force a “factory reset” during the next reboot (see the Real World
Example above).
If either of the above are used, the key-value pair will need to be recreated before using it again.
For each namespace, Preferences keeps track of the keys in a key table. There must be an open entry in the table before
a key can be created. This method will return the number of entires available in the table.
freeEntries()
To send to the serial monitor the number of available entries the following could be used.
Preferences mySketchPrefs;
mySketchPrefs.begin("myPrefs", true);
size_t whatsLeft = freeEntries(); // this method works regardless of the mode in␣
˓→which the namespace is opened.
The number of available entries in the key table changes depending on the number of keys in the namespace and also
the dynamic size of certain types of data stored in the namespace. Details are in the Preferences API Reference.
Do note that the number of entries in the key table does not guarantee that there is room in the opened NVS namespace
for all the data to be stored in that namespace. Refer to the espressif Non-volatile storage library documentation for full
details.
Keeping track of the data types stored against a key-value pair is one of the bookkeeping tasks left to you. Should you
want to discover the Preferences data type stored against a given key, use this method:
getType("myKey")
As in:
The value returned is a PreferenceType value that maps to a Preferences Type. Refer to the description in the
Preferences API Reference for details.
Recall that the Preferences library works best for storing many small values, rather than a few large values. Regardless,
it may be desirable to store larger amounts of arbitrary data than what is provided by the basic types in the Preferences
Types table above.
The library provides the following methods to facilitate this.
putBytes("myBytesKey", value, valueLen)
getBytes("myBytesKey", buffer, valueLen)
getBytesLength("myBytesKey")
The put and get Bytes methods store and retrieve the data. The getBytesLength method is used to find the size of
the data stored against the key (which is needed to retrieve Bytes data).
As the names of the methods imply, they operate on variable length bytes of data (often referred to as a “blob”) and not
on individual elements of a certain data type.
Meaning if you store for example an array of type int16_t against a Bytes type key, the value of that key becomes
a series of bytes with no associated data type. Or if you like, all data stored as a blob gets converted to a series of
uint8_t type bytes.
As a result, when using the getBytes method to retrieve the value of the key, what is returned to the buffer is a series
of uint8_t bytes. It is up to you to manage the data types and size of the arrays and buffers when retrieving Bytes
data.
Fortunately this is not as difficult as it may sound as the getBytesLength method and the sizeof operator help with
keeping track of it all.
This is best explained with an example. Here the Bytes methods are used to store and retrieve an array, while ensuring
the data type is preserved.
/*
* An example sketch using the Preferences "Bytes" methods
* to store and retrieve an arbitrary number of bytes in
* a namespace.
*/
#include <Preferences.h>
void setup() {
Preferences mySketchPrefs;
Serial.begin(115200);
delay(250);
Serial.println("Printing myArray...");
for (int i = 0; i < sizeof(myArray) / sizeof(int16_t); i++) {
Serial.print(myArray[i], HEX); Serial.print(", ");
}
Serial.println("\r\n");
Serial.println(
"Storing myArray into the Preferences namespace \"myPrefs\" against the key \
˓→"myPrefsBytes\".");
// Note: in the next statement, to store the entire array, we must use the
// size of the arrray in bytes, not the number of elements in the array.
mySketchPrefs.putBytes( "myPrefsBytes", myArray, sizeof(myArray) );
Serial.print("The size of \"myPrefsBytes\" is (in bytes): ");
Serial.println( mySketchPrefs.getBytesLength("myPrefsBytes") );
Serial.println("");
int16_t myIntBuffer[20] = {}; // No magic about 20. Just making a buffer (array) big␣
˓→ enough.
Serial.println("Retrieving the value of myPrefsBytes into myIntBuffer.");
Serial.println(" - Note the data type of myIntBuffer matches that of myArray");
mySketchPrefs.getBytes("myPrefsBytes", myIntBuffer,
mySketchPrefs.getBytesLength("myPrefsBytes"));
Serial.println("Printing myIntBuffer...");
// In the next statement, sizeof() needs to match the data type of the elements of␣
˓→myArray
Serial.println(
"We can see how the data from myArray is actually stored in the namespace as␣
˓→follows.");
uint8_t myByteBuffer[40] = {}; // No magic about 40. Just making a buffer (array)␣
˓→big enough.
mySketchPrefs.getBytes("myPrefsBytes", myByteBuffer,
mySketchPrefs.getBytesLength("myPrefsBytes"));
(continues on next page)
Serial.println("Printing myByteBuffer...");
for (int i = 0; i < mySketchPrefs.getBytesLength("myPrefsBytes"); i++) {
Serial.print(myByteBuffer[i], HEX); Serial.print(", ");
}
Serial.println("");
void loop() {
;
}
Printing myArray...
1112, 2122, 3132, 4142, 5152, 6162, 7172,
Storing myArray into the Preferences namespace "myPrefs" against the key "myPrefsBytes".
The size of "myPrefsBytes" is (in bytes): 14
We can see how the data from myArray is actually stored in the namespace as follows.
Printing myByteBuffer...
12, 11, 22, 21, 32, 31, 42, 41, 52, 51, 62, 61, 72, 71,
You can copy the sketch and change the data type and values in myArray and follow along with the code and output to
see how the Bytes methods work. The data type of myIntBuffer should be changed to match that of myArray (and
check the “sizeof()’s” where indicated in the comments).
The main takeaway is to remember you’re working with bytes and so attention needs to be paid to store all the data
based on the size of its type and to manage the buffer size and data type for the value retrieved.
As stated earlier, multiple namespaces can exist in the Preferences NVS partition. However, only one namespace at a
time can be open (in use).
If you need to access a different namespace, close the one before opening the other. For example:
Preferences currentNamespace;
currentNamespace.begin("myNamespace", false);
// do stuff...
Here the “currentNamespace” object is reused, but different Preferences objects can be declared and used. Just
remember to keep it all straight as all “putX’s” and “getX’s”, etc. will only operate on the single currently opened
namespace.
Methods in the Preferences library return a status code that can be used to determine if the method completed success-
fully. This is described in the Preferences API Reference.
Assume we have a key named “favourites” that contains a value of a String data type.
After executing the statement:
dessert = mySketchPrefs.getString("favourites");
the variable dessert will contain the value of the string stored against the key "favourites".
But what if something went wrong and the getString call failed to retrieve the key value? How would we be able to
detect the error?
With Preferences, the getX methods listed in Table 2 below will return a default value if an error is encountered.
Thus to detect an error we could compare the value returned against its default return value and if they are equal assume
an error occurred and take the appropriate action.
But what if a method default return value is also a potential legitimate value? How can we then know if an error
occurred?
As it turns out, the complete form of the getX methods for each of the Preferences Types in Table 2 is:
preferences.getX("myKey", myDefault)
In this form the method will return either the value associated with “myKey” or, if an error occurred, return the value
myDefault, where myDefault must be the same data type as the getX.
Returning to the example above:
will assign to the variable dessert the String gravel if an error occurred, or the value stored against the key
favourites if not.
If we predetermine a default value that is outside all legitimate values, we now have a way to test if an error actually
occurred.
In summary, if you need to confirm that a value was retrieved without error from a namespace, use the complete form
of the getX method with a predetermined default “this can only happen if an error” value and compare that against the
value returned by the call. Otherwise, you can omit the default value as the call will return the default for that particular
getX method.
Additional detail is given in the Preferences API Reference.
In the arduino-esp32 implementation of Preferences there is no method to completely remove a namespace. As a result,
over the course of a number of projects, it is possible that the ESP32 NVS Preferences partition becomes cluttered or
full.
To completely erase and reformat the NVS memory used by Preferences, create and run a sketch that contains:
#include <nvs_flash.h>
void setup() {
void loop() {
;
}
Warning: You should download a new sketch to your board immediately after running the above or else it
will reformat the NVS partition every time it is powered up or restarted!
4.6.11 Resources
4.6.12 Contribute
FIVE
ADVANCED UTILITIES
5.1.1 About
Espressif provides a tool to simplify building your own compiled libraries for use in Arduino IDE (or your favorite
IDE).
This tool can be used to change the project or a specific configuration according to your needs.
5.1.2 Installing
To install the Library Builder into your environment, please, follow the instructions below.
• Clone the ESP32 Arduino lib builder:
cd esp32-arduino-lib-builder
• Build:
./build.sh
If everything works, you may see the following message: Successfully created esp32 image.
Dependencies
To build the library you will need to install some dependencies. Maybe you already have installed it, but it is a good
idea to check before building.
• Install all dependencies (Ubuntu):
sudo apt-get install git wget curl libssl-dev libncurses-dev flex bison gperf cmake␣
˓→ninja-build ccache jq
217
Arduino-ESP32, Release 2.0.6
pip install --user setuptools pyserial click cryptography future pyparsing pyelftools
5.1.3 Building
If you have all the dependencies met, it is time to build the libraries.
To build using the default configuration:
./build.sh
Custom Build
There are some options to help you create custom libraries. You can use the following options:
Usage
build.sh [-s] [-A arduino_branch] [-I idf_branch] [-i idf_commit] [-c path] [-t <target>
˓→] [-b <build|menuconfig|idf_libs|copy_bootloader|mem_variant>] [config ...]
Skip Install/Update
./build.sh -s
This option can be used if you already have the ESP-IDF and all components already in your environment.
./build.sh -A <arduino_branch>
./build.sh -I <idf_branch>
./build.sh -i <idf_commit>
Deploy
./build.sh -d
Set the arduino-esp32 folder to copy the result to. ex. ‘$HOME/Arduino/hardware/espressif/esp32’
./build.sh -c <path>
This function is used to copy the compiled libraries to the Arduino folder.
./build.sh -t <target>
This build command will build for the ESP32-S3 target. You can specify other targets.
• esp32
• esp32s2
• esp32c3
• esp32s3
Set the build type. ex. ‘build’ to build the project and prepare for uploading to a board.
Additional Configuration
Specify additional configs to be applied. ex. ‘qio 80m’ to compile for QIO Flash@80MHz. Requires -b
This method is recommended for advanced users. To use this method, you will need to have the ESP-IDF toolchain
installed.
For a simplified method, see Installing using Boards Manager.
If you don’t need any modifications in the default Arduino ESP32 core, we recommend you to install using the Boards
Manager.
Arduino Lib Builder is the tool that integrates ESP-IDF into Arduino. It allows you to customize the default settings
used by Espressif and try them in Arduino IDE.
For more information see Arduino lib builder
5.2.2 Installation
Note: Latest Arduino Core ESP32 version is now compatible with ESP-IDF v4.4. Please consider this compatibility
when using Arduino as a component in ESP-IDF.
Note: If you use Arduino with ESP-IDF often, you can place the arduino folder into global components folder.
If you’re targeting the ESP32-S2 or ESP32-S3 and you want to use USBHID classes such as USBHID,
USBHIDConsumerControl, USBHIDGamepad, USBHIDKeyboard, USBHIDMouse, USBHIDSystemControl, or
USBHIDVendor:
1. Clone these nested repos somewhere:
2. In the project folder, edit CMakeLists.txt and add the following before the project() line:
5.2.3 Configuration
Depending on one of the two following options, in the menuconfig set the appropriate settings.
Go to the section Arduino Configuration --->
1. For usage of app_main() function - Turn off Autostart Arduino setup and loop on boot
2. For usage of setup() and loop() functions - Turn on Autostart Arduino setup and loop on boot
Experienced users can explore other options in the Arduino section.
After the setup you can save and exit:
• Save [S]
• Confirm default filename [Enter]
• Close confirmation window [Enter] or [Space] or [Esc]
• Quit [Q]
//file: main.cpp
#include "Arduino.h"
void setup(){
Serial.begin(115200);
while(!Serial){
; // wait for serial port to connect
}
}
void loop(){
Serial.println("loop");
delay(1000);
}
In main.c or main.cpp you need to implement app_main() and call initArduino(); in it.
Keep in mind that setup() and loop() will not be called in this case. Furthermore the app_main() is single execution
as a normal function so if you need an infinite loop as in Arduino place it there.
// Arduino-like setup()
Serial.begin(115200);
while(!Serial){
; // wait for serial port to connect
}
// Arduino-like loop()
while(true){
Serial.println("loop");
}
// WARNING: if program reaches end of function app_main() the MCU will restart.
}
If you are writing code that does not require Arduino to compile and you want your ESP_LOGx macros to work in
Arduino IDE, you can enable the compatibility by adding the following lines:
#ifdef ARDUINO_ARCH_ESP32
#include "esp32-hal-log.h"
#endif
The Arduino component requires the FreeRTOS tick rate CONFIG_FREERTOS_HZ set to 1000Hz in make menuconfig
-> Component config -> FreeRTOS -> Tick rate.
As commits are made to esp-idf and submodules, the codebases can develop incompatibilities that cause compilation
errors. If you have problems compiling, follow the instructions in Issue #1142 to roll esp-idf back to a different version.
OTAWebUpdate is done with a web browser that can be useful in the following typical scenarios:
• Once the application developed and loading directly from Arduino IDE is inconvenient or not possible
• after deployment if user is unable to expose Firmware for OTA from external update server
• provide updates after deployment to small quantity of modules when setting an update server is not practicable
5.3.1 Requirements
• The ESP and the computer must be connected to the same network
5.3.2 Implementation
Note: If entering “http://ESP32.local” does not work, try replacing “ESP32” with module’s IP address. This
workaround is useful in case the host software installed does not work.
Now click on the Login button and browser will display an upload form
For Uploading the New Firmware, you need to provide the Binary File of your Code.
Exporting Binary file of the Firmware (Code) - Open up the Arduino IDE - Open up the Code, for Exporting up Binary
file - Now go to Sketch > export compiled Binary
• Binary file is exported to the same Directory where your code is present
Once you are comfortable with this procedure, go ahead and modify OTAWebUpdater.ino sketch to print some addi-
tional messages and compile it. Then, export the new binary file and upload it using web browser to see entered changes
on a Serial Monitor.
5.4 makeEspArduino
The makeEspArduino is a generic makefile for any ESP8266/ESP32 Arduino project. Using it instead of the Arduino
IDE makes it easier to do automated and production builds.
SIX
Arduino-esp32 project is based on ESP-IDF. While ESP-IDF supports configuration of various compile-time options
(known as “Kconfig options” or “sdkconfig options”) via a “menuconfig” tool, this feature is not available in Arduino
IDE.
To use the arduino-esp32 core with a modified sdkconfig option, you need to use ESP-IDF to compile Arduino libraries.
Please see Arduino as an ESP-IDF component and Library Builder for the two solutions available.
Note that modifying sdkconfig or sdkconfig.h files found in the arduino-esp32 project tree does not result in
changes to these options. This is because ESP-IDF libraries are included into the arduino-esp32 project tree as pre-
built libraries.
Try enforcing format on fail in your code by adding true in the begin method such as this:
SPIFFS.begin(true);
See the method prototype for reference: bool begin(bool formatOnFail=false, const char *
basePath="/spiffs", uint8_t maxOpenFiles=10, const char * partitionLabel=NULL);
227
Arduino-ESP32, Release 2.0.6
SEVEN
TROUBLESHOOTING
Here are some of the most common issues around the ESP32 development using Arduino.
Note: Please consider contributing if you have found any issues with the solution here.
7.1.1 Installing
7.1.2 Building
You are trying to build your sketch using Ubuntu and this message appears:
Solution
To avoid this error, you can install the python-is-python3 package to create the symbolic links.
If you are not using Ubuntu, you can check if you have the Python correctly installed or the presence of the symbolic
links/environment variables.
229
Arduino-ESP32, Release 2.0.6
7.1.3 Flashing
To be able to upload the sketch via serial interface, the ESP32 must be in the download mode. The download mode
allows you to upload the sketch over the serial port and to get into it, you need to keep the GPIO0 in LOW while a
resetting (EN pin) cycle. If you are trying to upload a new sketch and your board is not responding, there are some
possible reasons.
Possible fatal error message from the Arduino IDE:
A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
Solution
7.1.4 Hardware
If your board is not being detected after connecting to the USB, you can try to:
Solution
7.1.5 Wi-Fi
Please note that WEP/WPA has significant security vulnerabilities and its use is strongly discouraged. The support
may therefore be removed in the future. Please migrate to WPA2 or newer.
Solution
Nevertheless, it may be necessary to connect to insecure networks. To do this, the security requirement of the ESP32
must be lowered to an insecure level by using:
WPA3 support is resource intensive and may not be compiled into the used SDK.
Solution
#ifndef CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE
#warning "No WPA3 support."
#endif
EIGHT
CONTRIBUTIONS GUIDE
Contributions to the Arduino ESP32 (fixing bugs, adding features, adding documentation) are welcome. We accept
contributions via Github Pull Requests.
After you open the Pull Request, there will probably be some discussion in the comments field of the request itself.
Once the Pull Request is ready to merge, it will first be merged into our internal git system for “in-house” automated
testing.
If this process passes, it will be merged into the public GitHub repository.
233
Arduino-ESP32, Release 2.0.6
8.4.1 Checklist
• Check if your example proposal has no similarities to the project (already existing examples)
• Use the Arduino style guide
• Add the header to all source files
• Add the README.md file
• Add inline comments if needed
• Test the example
8.4.2 Header
All the source files must include the header with the example name and license, if applicable. You can change this
header as you wish, but it will be reviewed by the community and may not be accepted.
Ideally, you can add some description about the example, links to the documentation, or the author’s name. Just have
in mind to keep it simple and short.
Header Example
Inline comments are important if the example contains complex algorithms or specific configurations that the user
needs to change.
Brief and clear inline comments are really helpful for the example understanding and it’s fast usage.
Example
See the FTM example as a reference.
and
8.4.5 Testing
Be sure you have tested the example in all the supported targets. If the example works only with specific targets, add
this information in the README.md file on the Supported Targets and in the example code as an inline comment.
Example
and
The example template can be found here and can be used as a reference.
Before a contribution can be accepted, you will need to sign our contributor agreement. You will be prompted for this
automatically as part of the Pull Request process.
NINE
9.1 About
External libraries testing is a compilation test for listed libraries on arduino-esp32 master branch. The test was made for
users, so they can check which libraries are compiling without errors on which SoC. External libraries test is running
periodically (once a week) against master branch and can also run on PR by adding a label lib_test. The test is
running on all supported ESP32 chips.
Note: As the test is just a compilation of example, that does not guarantee that the library/sketch will run without any
problems after flashing it on your device.
To add a library to the CI test you need to add your library to the lib.json. file located in ./github/workflows/.
Note: Please add the libraries to the lib.json in alphabetical order, thanks.
237
Arduino-ESP32, Release 2.0.6
9.2.2 Example of library addition from Arduino Library Manager with ESP32-S2 ex-
cluded:
{
"name": "ArduinoBLE",
"exclude_targets": [
"esp32s2"
],
"sketch_path": [
"~/Arduino/libraries/ArduinoBLE/examples/Central/Scan/Scan.ino"
]
}
9.2.3 Example of library addition from Github URL with required library:
{
"source-url": "https://github.com/me-no-dev/ESPAsyncWebServer.git",
"required-libs": [
{"source-url": "https://github.com/me-no-dev/AsyncTCP.git"}
],
"exclude_targets": [],
"sketch_path": [
"~/Arduino/libraries/ESPAsyncWebServer/examples/CaptivePortal/
˓→CaptivePortal.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/ESP_AsyncFSBrowser/ESP_
˓→AsyncFSBrowser.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/regex_patterns/regex_
˓→patterns.ino",
"~/Arduino/libraries/ESPAsyncWebServer/examples/simple_server/simple_
˓→server.ino"
]
},
9.2.4 Submit a PR
• Open a PR with the changes and someone from Espressif team will add a label lib_test to the PR and CI will
run the test to check, if the addition is fine and the library/example is compiling.
• After merging your PR, the next scheduled test will test your library and add the results to the LI-
BRARIES_TEST.md.
There is a number before each icon, which means the number of examples which were compiled with that result.
• - Compilation was successful.
• - Compilation was successful, but some warnings occurs.
• - Compilation failed.
• N/A - Not tested (target is in exclude_targets list).
If the test run on Pull Request, it will compile all libraries and sketches 2 times (before/after changes in PR) to see, if
the PR is breaking/fixing libraries. In the table the results are in order BEFORE -> AFTER.