Skip to content

IoT Devices Lab Series 2 - Flashing Micropython on the ESP32

Introduction

In this lab, you prepare your IoT development environment, your Development Board, and bootstrap a working Micropython firmware in your ESP32-based MCU Dev Board.

Pre-requisites

Info

This lab guide is written form Mac OS X and Linux. If you have a Windows Machine, go and read the first part of this series to set up a Linux-based IoT Development workstation on a VM on your laptop.

The tutorial assumes you have Python3 installed in your machine, and that you have access to the following materials:

  • A development environment with direct USB access (your laptop)
  • An ESP32-based development board
  • Internet connectivity
  • A USB-A to micro USB cable to connect the dev board to your computer.

Setting up the environment

Clone the following GitLab repository and change to the repository's directory:

git clone https://gitlab.com/sw4iot/iot-esp32-basics
cd iot-esp32-basics

Create a virtual environment and activate it:

python3 -m venv venv
source venv/bin/activate

Install the project requirements:

pip install -r requirements.txt

Connect your ESP32 to your machine using the USB cable and see where it has been connected:

ls /dev/cu.usb*
sudo dmesg | grep ttyUSB
ls /dev/ttyUSB*

You should get something like this:

/dev/cu.usbserial-02J1JMFH
[    3.735591] usb 1-2: cp210x converter now attached to ttyUSB0
/dev/ttyUSB0

Now edit the file env.sh, and make sure that you have assigned the path to the serial port where your MCU is connected to the SERIALPORT variable inside it. You can do it using your favorite editor, or you could try to do it automatically with the following command line:

sed -i.bak -e "s|SERIALPORT=.*|SERIALPORT=$(ls /dev/cu.usb*)|" env.sh
sed -i.bak -e "s|SERIALPORT=.*|SERIALPORT=$(ls /dev/ttyUSB*)|" env.sh

Once this is done, source then file:

source env.sh

This sets up your shell variables so the next programs using USB to serial connection (esptool, minicom, ) pick up the right port in your machine.

    echo $SERIALPORT

Finally, you'll need minicom. Install Homebrew in your Mac if you don't have it already and then proceed to install minicom with it:

brew install minicom
sudo apt install minicom

Info

If you're using the sw4iot VM described in the first part of this series, then minicom is already installed for you.

Obtaining and flashing Micropython

First, let's test flashing your device:

esptool.py flash_id

You should get a flash id:

esptool.py v3.2
Serial port /dev/cu.usbserial-02J1JMFH
Connecting......
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting.....
Detecting chip type... ESP32
Chip is ESP32-D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: ac:67:b2:3c:14:b8
Uploading stub...
Running stub...
Stub running...
Manufacturer: 20
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...

Warning

If you've got a Mac and you're connecting through USB-C to your machine, and instead of the previous output you get something like this:

esptool.py v3.2
Serial port /dev/cu.usbserial-0001
Connecting..............................
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting......................................
A fatal error occurred: Failed to connect to Espressif device: Wrong boot mode detected (0x13)! The chip needs to be in download mode.
For troubleshooting steps visit: https://github.com/espressif/esptool#troubleshooting
this means that you may be impacted by ESP32's Issue #696. Just push and hold the BOOT button while you launch the previous command again and it should work.

Then, download a precompiled Micropython firmware for the ESP32 (you may review the value of $MICROPYTHON_URL environment variable in env.sh and update it to match possible newer versions of the firmware since this repo was updated):

curl --create-dirs -O "$MICROPYTHON_URL" --output-dir firmware

Now, proceed to erase your device:

esptool.py --chip esp32 erase_flash

Warning

If you're impacted by the previous issue, you'll also get the same error when launching the previous command. Try the same workaround mentioned there and you should be able to erase the flash.

And then, finally, flash the Micropython firmware:

FW_PATH=$(ls firmware/esp*)
esptool.py --chip esp32 --baud 460800 write_flash -z 0x1000 $FW_PATH

You should see an output similar to this one:

esptool.py v3.2
Serial port /dev/cu.usbserial-02J1JMFH
Connecting.........
Chip is ESP32-D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: ac:67:b2:3c:14:b8
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash will be erased from 0x00001000 to 0x0017cfff...
Compressed 1555136 bytes to 1022998...
Wrote 1555136 bytes (1022998 compressed) at 0x00001000 in 24.9 seconds (effective 499.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

Connecting to the device

Your device should be successfully flashed by now. Let's test it by getting the Micropython REPL through serial connection.

You may be using several methods to obtain a Micropython REPL. All of them involve a USB to serial connection. We'll describe here two methods of obtaining the REPL and moving forward you may choose any of these.

Using minicom

First, set up minicom connection defaults:

cat <<EOF > $HOME/.minirc.dfl
# Machine-generated file - use "minicom -s" to change parameters.
pu port             $SERIALPORT
pu rtscts           No
EOF

This generates a .minirc.dfl file in your $HOME directory that minicom reads on start, and it contains the minimum setup for successful connectivity to your ESP32 Dev Board.

Info

If you're using the sw4iot VM, this is already done for you and you don't need to change the .minirc.dfl file.

Then, you can start minicom by doing:

minicom

Then, press ENTER once and you should get the Micropython's REPL:

Welcome to minicom 2.8

OPTIONS: I18n
Compiled on Feb 22 2022, 10:02:11.
Port /dev/cu.usbserial-02J1JMFH, 08:51:41

Press Meta-Z for help on special keys


>>>

Tip

If you don't get the Micropython's REPL prompt, try pushing the EN button once in the device.

Try some Micropython in the REPL to see that this all works:

import sys
sys.path

Note

For Linux, you can press Ctrl + A and then X, and then select YES to exit minicom. Ctrl + A and Z will give you all minicom options.

For Mac OS X, you can exit by pressing META + X and selecting YES (the META key may be mapped to ESC in your computer). META + Z will give you all minicom options.

If you don't get the Python REPL, recheck the steps where you flashed the device's firmware and try again).

Using Thonny

If you don't feel so comfortable with the command line, this is the recommended way to access your device.

First, install Thonny:

brew install thonny

If you're using the sw4iot VM, just use the "Thonny" shortcut that should be in your desktop. If not, you can install Thonny by typing:

yes "" | bash <(curl -s https://thonny.org/installer-for-linux)

Open Thonny:

Use Spotlight to find the program and type "Thonny" to open it.

Double click on the "Thonny" shortcut that should be in your desktop or open a shell and type:

$HOME/apps/thonny/bin/thonny

When Thonny opens for the first time, you need to select a couple of things. I recommend sticking to the defaults:

  • Language: English
  • Initial settings: Standard

Click the "Let's go" button and the Thonny IDE should launch.

Now go to the "Run" menu and click on "Select Intepreter...". A new window will pop up, with a tab called "Interpreter" already selected. Click on the drop down menu that is presented and select Micropython (ESP32).

A new set of instructions will appear, after which you'll see another drop down asking you to select a Port or WebREPL. We'll explore what WebREPL means later. For now, you can leave the drop-down as <Try to detect port automatically>.

Click OK and you'll be presented with two panes. In the upper pane you can write Python/Micropython programs. In the lower pane, if your device was flashed correctly with Micropython's firmware, you should get the Micropython's REPL.

Success

You've managed to get Micropython up and running in your ESP32. In next labs, we'll start exploring Micropython a bit more, start playing with sensor and actuators, and learn how to connect our device with the outside world.

Additional information

Got stuck with minicom?

Kill the process occupying the serial term:

lsof | grep <device substring>
killall -9 minicom

Other tools

  • Ampy: Adafruit's MicroPython tool, a command line utility to interact with a CircuitPython or MicroPython board over a serial connection. Use the Alpha version that continues development of the Adafruit tool as Ampy is stopping support for MicroPython and focusing on CircuitPython exclusively.
  • mpremote: Command line tool based in Python with an integrated set of utilities to remotely interact with and automate a MicroPython device over a serial connection. We'll be using this tool in the labs.
  • rshell: This is a simple shell which runs on the host and uses MicroPython's raw-REPL to send python snippets to the Dev Board in order to get filesystem information, and to copy files to and from MicroPython's filesystem.
  • Pymakr: VSCode plugin for Micropython Development, you'll need to install Node.js support in your system for it to work.
  • ESPlorer: Very nice IDE, developed in Java.