A handful of simple examples for the ESP-32.
This repo contains number of simple examples for the ESP-32, including:
- General Purpose Input Output (GPIO, aka "digital pins"), using functions and direct register access,
- Analog to Digital converter (ADC), for light sensor or soil moisture sensor,
- Arduino compatibility,
- Dallas One Wire temperature sensor,
- Push button w/ interrupt.
These examples are described in detail below.
This repository contains companion code to a talk I gave about Microcontrollers. The talk, and these examples, are based around the SparkFun ESP-32 Thing, but any ESP32 dev board should work, with some changing of pins.
The layout of this repository is based on the ESP IDF Template.
- ESP-32 hardware, in particular the SparkFun ESP-32 Thing,
- ESP-IDF repo (see details below),
- Some familiarity with command line tools,
- A microusb cable,
- Some examples require additional sensors, described therein.
IMPORTANT: both this repository and the ESP-IDF repository have submodules, so must be cloned with --recursive
.
Install and configure the ESP-IDF (the SDK for ESP32 development), including downloading the GCC compiler and possibly installing Xcode, and either MacPorts or Homebrew. Please see detailed installation instructions there, but in summary, for Mac:
mkdir esp32
cd esp32
git clone --recursive https://github.com/espressif/esp-idf
# Double check that the below compiler version is the most recent mentioned in ESP-IDF setup instructions:
curl -O https://dl.espressif.com/dl/xtensa-esp32-elf-osx-1.22.0-61-gab8375a-5.2.0.tar.gz
tar xzf xtensa-esp32-elf-osx-1.22.0-61-gab8375a-5.2.0.tar.gz
export PATH=`pwd`/xtensa-esp32-elf/bin:${PATH}
export IDF_PATH=`pwd`/esp-idf
git clone --recursive https://github.com/cmason1978/esp32-examples
cd esp32-examples
Plug the ESP32 board into your USB port, and run:
ls /dev/tty.*
You should see a device name like /dev/tty.usbserial-DN0281FC
(the letters at the end will be different). This is the "device" file used for talking to the board over the USB serial port. If you don't see anything like this, go to troubleshooting below. If you have more than one, try unplugging and seeing which disappears. Note that, in some cases, the name of the device will change if you plug it into a different USB port.
Next, type:
make menuconfig
This will show a graphical configuration screen like this:
Use the up and down arrow keys to navigate menus at the middle of the screen and the left and right arrow keys to navigate the buttons along the bottom. Press enter to select.
Under "Serial flasher config", change the "Default serial port" to the /dev/tty...
path you discovered above. Change the "Flash size" to 4MB (for SparkFun board).
Choose "Exit" repeatedly and save the configuration.
Now run:
make flash
This compiles both the ESP IDF libraries and the example main file locally (into the build
directory) and then downloads this to the flash memory on the device over USB. It will take a little while, both to compile, and to flash. If you have a multi-core machine you can try adding eg -j 4
to speed up compilation.
After this completes the blue LED on your board should be flashing twice per second.
Now run:
make monitor
This will connect over the serial port and reboot the device, and you should see a bunch of debugging output ending with "Hello, world"
...
I (943) cpu_start: Pro cpu up.
I (955) cpu_start: Starting app cpu, entry point is 0x400809bc
I (0) cpu_start: App cpu up.
I (986) cpu_start: Pro cpu start user code
I (1235) phy: phy_version: 258, Nov 29 2016, 15:51:07, 1, 0
I (2258) cpu_start: Starting scheduler on PRO CPU.
Hello, world.
I (1292) cpu_start: Starting scheduler on APP CPU.
Hello, world.
Hello, world.
Hello, world.
Hello, world.
Type Ctrl-] to break out of the terminal.
If you successfully flash the device at the default baud rate (115200), you can speed up the flash process significantly by choosing one of the faster baud rates in make menuconfig
> Serial flasher config > Default baud rate. I occasionally get errors at 2MBaud, but rerunning the flash command will usually succeed.
See below for troubleshooting suggestions.
More documentation to come, check out the main
directory for all examples.
The template IDF project is set up to only run a single program. We have a number of different examples here. By default the main/main_gpio.c
example will run, which blinks the LED and writes.
To choose which example to run, edit the main/component.mk
file and change which one of the COMPONENT_OBJS
lines is commented in.
main/main_gpio.c
– blinks the LED 2/sec and prints "Hello, world!" to serial console. Demonstrates use of gpio functions.
main_gpio_raw.c
– Demonstrates use of direct register access to control the LED.
main_crash.c
– Demonstrates use of GDB debugger.
When your program crashes, by default you'll see something like this:
Guru Meditation Error of type LoadProhibited occurred on core 0. Exception was unhandled.
Register dump:
PC : 0x400e6919 PS : 0x00060330 A0 : 0x800d06dd A1 : 0x3ffb7c60
A2 : 0x00000001 A3 : 0x00000000 A4 : 0x00060023 A5 : 0x3ffb7d24
A6 : 0x00000000 A7 : 0x00000001 A8 : 0x800e6919 A9 : 0x3ffb7c40
A10 : 0x0000000a A11 : 0x3ffb1bec A12 : 0x00060023 A13 : 0x3ffb91c0
A14 : 0x00000003 A15 : 0x00060023 SAR : 0x0000001b EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xfffffffc
Backtrace: 0x400e6919:0x3ffb7c60 0x400d06dd:0x3ffb7c90
This is a register dump and execution traceback. This is produced by FreeRTOS whenever a task crashes. The "backtrace" line allows you to figure out where it crashed. There are pairs of addresses separated by colons; pass the first address of the pair to addr2line
:
xtensa-esp32-elf-addr2line -e build/app-template.elf 0x400e6919
/Users/cmason/code/esp32/esp32-examples/main/./main_crash.c:21 (discriminator 1)
You may need to walk up the stack in order to find your code (but see below for an easier way using GDB).
By default a crash reboot the device, which is useful in a real device but is annoying when debugging. This may happen in a loop quickly (see [this troubleshooting answer](#My-program-is-crashing-in-a loop-and-I-can-t-get-the-device-to-flash) if you have trouble breaking out of this loop).
However, you can change this behavior and even connect a debugger!
First enable the GDB debug stub by: make menuconfig
> Component config > ESP32-specific config > Panic handler behavior, and choose "Invoke GDBStub".
Now when your program crashes, after the backtrace you'll see:
Entering gdb stub now.
$T0b#e6
Exit out of the monitor by pressing Ctrl-] and then connect gdb by running:
xtensa-esp32-elf-gdb ./build/app-template.elf -b 115200 -ex 'target remote /dev/cu.usbserial-DN0281FC'
Substitute your device name here, and note cu
and not tty
(or you'll hang when connecting with GDB).
For example:
cmason@fire:~/code/esp32/esp32-examples> xtensa-esp32-elf-gdb ./build/app-template.elf -b 115200 -ex 'target remote /dev/cu.usbserial-DN0281FC'
GNU gdb (crosstool-NG crosstool-ng-1.22.0-61-gab8375a) 7.10
Copyright (C) 2015 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-build_apple-darwin16.0.0 --target=xtensa-esp32-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./build/app-template.elf...done.
Remote debugging using /dev/cu.usbserial-DN0281FC
app_main () at /Users/cmason/code/esp32/esp32-examples/main/./main_crash.c:21
21 volatile uint32_t foo = *(uint32_t*)0;
(gdb)
You're now at the GDB prompt. GDB commands include
bt
will give a "back trace" of where the error occured
(gdb) bt
#0 app_main () at /Users/cmason/code/esp32/esp32-examples/main/./main_crash.c:21
#1 0x400d06dd in main_task (args=0x0)
at /Users/cmason/code/esp32/esp-idf/components/esp32/./cpu_start.c:256
You can inspect memory and print variables:
(gdb) p foo
$1 = 0
(gdb) p level
$1 = 1
Type quit
to exit.
main_adc.c
– Use the analog to digital (ADC), for instance with a light sensor.
Hook up ALS-PT19 ambient light sensor as shown below:
Note, the light sensor is not particularly sensitive. Try using a flashlight. You should see the value printed on the make monitor
console vary depending on how much of the light beam impacts the sensor.
- Read docs for the ESP IDF. These are still under development.
- Visit ESP32 Forum. Good place to ask about undocumented or under documented things.
- For low level details of the chip, see the datasheet and the technical reference manual.
- Learn about FreeRTOS, the real time operating system used on ESP32.
- Learn more about electronics. I recommend Practical Electronics for Inventors.
- Attempt your own project! I'd love to hear what you work on!
Try installing the FTDI VCP drivers, eg this one for recent macs.
I think this is due to bad drivers, but might also be a hardware/cable problem. First try a different USB cable.
Next, double check that you can indeed talk to the device, for instance by running make monitor
or screen /dev/tty... 115200
. If you see weird unprintable characters, or you can't connect, try installing the FTDI driver as described above.
Also, double check that you don't have old USB serial drivers (for instance by doing ls -1 /Library/Extensions | grep -i '(usb)|(prolific)'
).
Retry flashing, or reduce the baud rate.
Missing the pyserial module:
pip install pyserial
Your IDF_PATH
environment variable isn't set to the path to the ESP-IDF repository. Double check this path.
This happens after updating the ESP-IDF if new options are added. Accept the defaults by pressing ENTER (not necessarily answering Yes).
Disable secure boot in menuconfig.
Clone of esp-idf not recursive. Can fix this by doing:
I think this is due to a change in the SDK.
Try running:
make clean
make flash
The wrong device port is specified.
Run make menuconfig
again and edit the "Serial flasher config > Default serial port.
-Or- edit the sdkconfig
file and change the value of CONFIG_ESPTOOLPY_PORT
.
The version of pyserial is too old. Try upgrading:
This repository wasn't cloned recursively (using --recursive
). You can fix this by running, in this directory:
git submodule update --init
Remove that file. I think this is mismatch between arduino and the ESP-IDF, but I haven't had time to debug yet.
Try holding down the bootloader button attached to pin 0 (labeled "0" on the ESP32 thing) while plugging the device into USB. This should get you into the ROM bootloader, allowing you to flash.