Programming LOLIN32 on macOS

Getting started using macOS to program the ESP32 with the WEMOS LOLIN32 dev board

Initial Steps
  • Download the Silicon Labs USB driver
    • So you can talk to the board over USB
  • Download and install Arduino IDE
    • To write, compile and upload your code
  • Install the "Arduino core" for ESP32

Problem: You've installed Arduino IDE and the espressif toolkit from Github, but your Arduino IDE won't connect to your LOLIN32 board. Something about esptool and the error: "could not open port COM1" on macOS 10.12. What the heck is COM1 and why isn't it there?

Reason: If you look in the Arduino menu under "Tools -> Port", it's probably missing the USB driver.

Alternatively, check in Terminal by typing ls /dev. You should see a driver for the USB-to-UART device. Likely it's not there!

Fix: Download the Silicon Labs drivers over at CP210x USB to UART Bridge VCP Drivers.

Background

At the time of writing the definitive tools for building Arduino-language code for the LOLIN32 are the espressif tools on Github.

Following that project README you're left with 2 basic steps:

  1. Install Arduino IDE
  2. Install espressif toolkit

Arduino IDE allows you to code and compile for normal Arduino boards, and so in combination with the espressif toolkit you should also be able to build and upload to the ESP32.

Gotcha: There's no port listed for the LOLIN32!

no Serial port for ESP32 LOLIN32

Only /dev/cu.Bluetooth-Incoming-Port is listed. If we try to build, the esptool.py scripts seem to work, the gears are turning but nothing happens and eventually Python complains there's no COM1 port or at least it can't open it.

raceback (most recent call last):  
  File "esptool.py", line 2349, in <module>
  File "esptool.py", line 2342, in _main
  File "esptool.py", line 2072, in main
  File "esptool.py", line 166, in __init__
esptool.py v2.0-beta3  
  File "serial/__init__.py", line 88, in serial_for_url
  File "serial/serialposix.py", line 268, in open
serial.serialutil.SerialException: [Errno 2] could not open port /dev/cu.SLAB_USBtoUART: [Errno 2] No such file or directory: '/dev/cu.SLAB_USBtoUART'  
Failed to execute script esptool  
An error occurred while uploading the sketch  

Your Arduino IDE can make a binary program suitable for the ESP32, but without the driver it doesn't see a suitable port on which to actually send out the binary program.

Troubleshooting: On linux maybe you'd go straight to lsusb to find out if the board even works at all, if it shows up as a USB device. A similar tool on Mac, a tool to expose your USB IO is ioreg -p IOUSB.

The output of ioreg will show you which UART bridge is going to allow programming your board. With the board plugged in you'll see something like this in the list of USB devices:

    +-o CP2104 USB to UART Bridge Controller@14100000  <class AppleUSBDevice, id 0x100001cf0, registered, matched, activ$

There's the device, now how can we talk to it?

Looking for a driver for the CP2104 will lead you to the Silicon Labs download link for the CP210x driver.

For the curious mind, I made files before.txt and after.txt from the output of ls /dev, just to see if the driver installation actually does put anything in the system's /dev/..., regardless of whether it shows up in Arduino IDE.

Indeed it does:

$ ls /dev > after.txt
$ diff -u ~/Desktop/before.txt ~/Desktop/after.txt
@@ -176,6 +181,7 @@
 systrace
 tty
 tty.Bluetooth-Incoming-Port
+tty.SLAB_USBtoUART
 ttyp0
 ttyp1
 ttyp2

Haha there it is! Now let's start up Arduino IDE and try to blink that LED.

Straight out of the box when I got mine, when the LOLIN32 was powered on, the LED was in a sort of floating state. Not fully lit but also not fully "off".

Running this code, I've got the bright 1-second blink we've all grown to love so much an the LED doesn't float.

Apparently worth noting the LED pin is connected to the LED which leads to power, and not to ground. So, the LED lights when the pin is "low" which might be the opposite of what you expect coming from whatever Arduino / Teensy projects you've done.

const int pinLED = 5;

void setup() {  
  // put your setup code here, to run once:
  pinMode(pinLED, OUTPUT);
}

void loop() {  
  // put your main code here, to run repeatedly:
  digitalWrite(pinLED, HIGH); // off
  delay(1000);
  digitalWrite(pinLED, LOW); // on
  delay(1000);
}