2020-04-20
md
Blink on a NodeMCU ESP-12H-Kit

LED connectionsWhile sorting parts, I came across a NodeMCU ESP-12H-Kit ordered some time ago. This is a development board using the single core ESP32-S2 which I had never used. A good excuse to put aside the cleaning chore and take a few minutes off to write a blink sketch. A few minutes turned into a few hours, during which I thought I had a defective board because the serial monitor would not work. Turned out that everything was fine.

The board has a big obvious surface mounted 5050 RGB LED, so I looked for some information about the I/O pins connected to the LED. The result of that search is shown at right. I could not find the ESP-12H-Kit in the long list of supported ESP32 boards in the current version (2.0.2) of the ESP32 package installed in the Arduino IDE. There is a generic ESP32S2 Dev Module so that seemed like a good place to begin. I wrote a simple "Hello world!" type of sketch to get things going.

void setup() { Serial.begin(115200); delay(1000); Serial.println("setup() completed, starting loop()"); } void loop() { delay(500); // wait 1/2 second Serial.println("loop"); }

In retrospect, that was not the best idea, but let's not get ahead of ourselves. I connected the board with a USB data and power cable to a desktop computer and observed that the USB to serial converter, a CH340, was recognized and a serial device was created by the Linux OS.

michel@hp:~$ lsusb ... Bus 003 Device 081: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter ... michel@hp:~$ ls /dev/ttyUS* /dev/ttyUSB0

A compile and upload of the new binary failed when using the default board values.

... esptool.py v3.1 Serial port /dev/ttyUSB0 Connecting..... Chip is ESP32-S2FH32 Features: WiFi, Embedded 4MB Flash, 105C temp rating, ADC and temperature sensor calibration in BLK2 of efuse Crystal is 40MHz MAC: 7c:df:a1:93:be:b8 Uploading stub... Running stub... Stub running... Changing baud rate to 921600 Changed. Configuring flash size... A fatal error occurred: Timed out waiting for packet header A fatal error occurred: Timed out waiting for packet header

Arduino IDE Tools MenuThat was not too surprising, the many development boards that use the CH340 USB-serial adapter around here were never flashed at such a high baud. Setting the upload speed to 115200 baud in the Arduino IDE Tools menu was all that was required to successfully upload the new binary.

... Wrote 3072 bytes (128 compressed) at 0x00008000 in 0.1 seconds (effective 429.6 kbit/s)... Hash of data verified. Leaving...

However when the serial monitor was opened (via the same Tools menu (or by clicking the "loupe" icon at the far right of the IDE toolbar or using the keyboard shortcut), the result was underwhelming. All that would be seen was the beginning of the ESP restart messages.

ESP-ROM:esp32s2-rc4-20191025 Build:Oct 25 2019 rst:0x1 (POWERO

It was rather late and perhaps my brain was even duller than usual, so all I came up with was to connect a USB-serial adapter directly to the UART pins. Note how the four pins required are all grouped together at the bottom left of the board looking at the pin side; very nice. This meant going through the bootloader button dance.

  1. Press the RST (reset) button keeping it closed. It is connected to the EN pin of the ESP32.
  2. Press the DOWN (download) button keeping it closed. It is connected to IO pin 0 of the ESP32.
  3. Release the RST button (with the DOWN button still closed).
  4. Release the DOWN button.

but once done, it was possible to upload the sketch. On resetting the board (with momentary push of the RST button), the loop message displayed every half second in the serial monitor showed that the new firmware was running. By the way, if the dev board falls into a boot loop because of brownouts, connecting a 1A 5V phone charger to the USB connector of the 12H kit will solve the issue, but remember to disconnect the 3.3 volts from the USB-serial adapter.

So I went off to bed, satisfied that the ESP12H-kit worked. As often happens, the "little grey cells" worked their magic during the night and I woke up remembering that the USB connection took care of the bootloader button dance automatically. This is done using the RTS and DTR outputs of the CH340. Thinking that this was the source of the problem, I wrote a proper blink sketch and uploaded it with the direct USB to desktop connection.

// array of GPIO Pins connected to the G R B LEDS int leds[] = {9, 11, 12}; // 9 green // 11 red // 12 blue void setup() { // put your setup code here, to run once: Serial.begin(115200); delay(1000); Serial.println("setup() completed, starting loop()"); } int led = 0; // change this to 1 & 2 to prove different version uploaded int level = 0; // start with LED off int inc = 2; // PWM increment at each step int pin = leds[led]; // initial I/O pin void loop() { level = level + inc; if (level > 255) { level = 255; inc = -inc; } else if (level < 0) { level = 0; inc = -inc; led++; if (led > 2) led = 0; pin = leds[led]; } analogWrite(pin, level); Serial.printf("led: %d, pin: %d, level: %d, inc: %d\n", led, pin, level, inc); delay(8); }

Because this thing actually flashed LEDs, it was immediately obvious that it was working. Had I used this version of the blink sketch the previous evening, the source of the problem might have been more obvious. As soon as the serial monitor was opened, the flashing stopped. It resumed when the serial monitor was closed. A volt meter connected to the EN pin showed that it was brought LOW, thus disabling the ESP32, when the serial monitor was opened. When the serial monitor is closed, the EN pin returns to the normal HIGH value and the ESP32 restart and executes its firmware. With this bit of information, it was easy to find that ejab had raised the issue in the Arduino forum and closed the discussion with the solution: disable the DTR and RST signals when opening the serial port. This is done in the board's definition and it works. As I see it, there are three ways of implementing that solution.

  1. As proposed by ejab, edit the ESP32S2 Dev Module definition in the boards.txt file. Change
    esp32s2.serial.disableDTR=false esp32s2.serial.disableRTS=false

    to

    esp32s2.serial.disableDTR=false esp32s2.serial.disableRTS=false

    The boards.txt file is in the .../arduino-x.x.x/portable/packages/esp32/hardware/esp32/2.0.2/ directory in Linux if a portable installation of the Arduino IDE was done.

  2. Add another board definition to the already very long list of definitions in boards.txt. Here is the definition that I use. It's a copy of the generic ESP32S2 definition but with the above correction and with the 921600 baud removed from the available upload speeds.
    ############################################################## # copied from esp32s2.name=ESP32S2 Dev Module ############################################################## nodemcu-12h-kit.name=NodeMCU ESP-12H-Kit nodemcu-12h-kit.vid.0=0x303a nodemcu-12h-kit.pid.0=0x0002 nodemcu-12h-kit.upload.tool=esptool_py nodemcu-12h-kit.upload.maximum_size=1310720 nodemcu-12h-kit.upload.maximum_data_size=327680 nodemcu-12h-kit.upload.flags= nodemcu-12h-kit.upload.extra_flags= nodemcu-12h-kit.upload.use_1200bps_touch=false nodemcu-12h-kit.upload.wait_for_upload_port=false nodemcu-12h-kit.serial.disableDTR=true nodemcu-12h-kit.serial.disableRTS=true nodemcu-12h-kit.build.tarch=xtensa nodemcu-12h-kit.build.bootloader_addr=0x1000 nodemcu-12h-kit.build.target=esp32s2 nodemcu-12h-kit.build.mcu=esp32s2 nodemcu-12h-kit.build.core=esp32 nodemcu-12h-kit.build.variant=esp32s2 nodemcu-12h-kit.build.board=ESP32S2_DEV nodemcu-12h-kit.build.cdc_on_boot=0 nodemcu-12h-kit.build.msc_on_boot=0 nodemcu-12h-kit.build.dfu_on_boot=0 nodemcu-12h-kit.build.f_cpu=240000000L nodemcu-12h-kit.build.flash_size=4MB nodemcu-12h-kit.build.flash_freq=80m nodemcu-12h-kit.build.flash_mode=dio nodemcu-12h-kit.build.boot=qio nodemcu-12h-kit.build.partitions=default nodemcu-12h-kit.build.defines= nodemcu-12h-kit.menu.CDCOnBoot.default=Disabled nodemcu-12h-kit.menu.CDCOnBoot.default.build.cdc_on_boot=0 nodemcu-12h-kit.menu.CDCOnBoot.cdc=Enabled nodemcu-12h-kit.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 nodemcu-12h-kit.menu.MSCOnBoot.default=Disabled nodemcu-12h-kit.menu.MSCOnBoot.default.build.msc_on_boot=0 nodemcu-12h-kit.menu.MSCOnBoot.msc=Enabled nodemcu-12h-kit.menu.MSCOnBoot.msc.build.msc_on_boot=1 nodemcu-12h-kit.menu.DFUOnBoot.default=Disabled nodemcu-12h-kit.menu.DFUOnBoot.default.build.dfu_on_boot=0 nodemcu-12h-kit.menu.DFUOnBoot.dfu=Enabled nodemcu-12h-kit.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 nodemcu-12h-kit.menu.UploadMode.default=UART0 nodemcu-12h-kit.menu.UploadMode.default.upload.use_1200bps_touch=false nodemcu-12h-kit.menu.UploadMode.default.upload.wait_for_upload_port=false nodemcu-12h-kit.menu.UploadMode.cdc=Internal USB nodemcu-12h-kit.menu.UploadMode.cdc.upload.use_1200bps_touch=true nodemcu-12h-kit.menu.UploadMode.cdc.upload.wait_for_upload_port=true #nodemcu-12h-kit.menu.PSRAM.disabled=Disabled #nodemcu-12h-kit.menu.PSRAM.disabled.build.defines= #nodemcu-12h-kit.menu.PSRAM.enabled=Enabled #nodemcu-12h-kit.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM nodemcu-12h-kit.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.default.build.partitions=default nodemcu-12h-kit.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) nodemcu-12h-kit.menu.PartitionScheme.defaultffat.build.partitions=default_ffat nodemcu-12h-kit.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT) nodemcu-12h-kit.menu.PartitionScheme.default_8MB.build.partitions=default_8MB nodemcu-12h-kit.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 nodemcu-12h-kit.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.minimal.build.partitions=minimal nodemcu-12h-kit.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.no_ota.build.partitions=no_ota nodemcu-12h-kit.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 nodemcu-12h-kit.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.noota_3g.build.partitions=noota_3g nodemcu-12h-kit.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 nodemcu-12h-kit.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) nodemcu-12h-kit.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat nodemcu-12h-kit.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 nodemcu-12h-kit.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) nodemcu-12h-kit.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat nodemcu-12h-kit.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 nodemcu-12h-kit.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.huge_app.build.partitions=huge_app nodemcu-12h-kit.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 nodemcu-12h-kit.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs nodemcu-12h-kit.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 nodemcu-12h-kit.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT) nodemcu-12h-kit.menu.PartitionScheme.fatflash.build.partitions=ffat nodemcu-12h-kit.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 nodemcu-12h-kit.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9MB FATFS) nodemcu-12h-kit.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB nodemcu-12h-kit.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 nodemcu-12h-kit.menu.CPUFreq.240=240MHz (WiFi) nodemcu-12h-kit.menu.CPUFreq.240.build.f_cpu=240000000L nodemcu-12h-kit.menu.CPUFreq.160=160MHz (WiFi) nodemcu-12h-kit.menu.CPUFreq.160.build.f_cpu=160000000L nodemcu-12h-kit.menu.CPUFreq.80=80MHz (WiFi) nodemcu-12h-kit.menu.CPUFreq.80.build.f_cpu=80000000L nodemcu-12h-kit.menu.CPUFreq.40=40MHz nodemcu-12h-kit.menu.CPUFreq.40.build.f_cpu=40000000L nodemcu-12h-kit.menu.CPUFreq.20=20MHz nodemcu-12h-kit.menu.CPUFreq.20.build.f_cpu=20000000L nodemcu-12h-kit.menu.CPUFreq.10=10MHz nodemcu-12h-kit.menu.CPUFreq.10.build.f_cpu=10000000L nodemcu-12h-kit.menu.FlashMode.qio=QIO nodemcu-12h-kit.menu.FlashMode.qio.build.flash_mode=dio nodemcu-12h-kit.menu.FlashMode.qio.build.boot=qio nodemcu-12h-kit.menu.FlashMode.dio=DIO nodemcu-12h-kit.menu.FlashMode.dio.build.flash_mode=dio nodemcu-12h-kit.menu.FlashMode.dio.build.boot=dio nodemcu-12h-kit.menu.FlashMode.qout=QOUT nodemcu-12h-kit.menu.FlashMode.qout.build.flash_mode=dout nodemcu-12h-kit.menu.FlashMode.qout.build.boot=qout nodemcu-12h-kit.menu.FlashMode.dout=DOUT nodemcu-12h-kit.menu.FlashMode.dout.build.flash_mode=dout nodemcu-12h-kit.menu.FlashMode.dout.build.boot=dout nodemcu-12h-kit.menu.FlashFreq.80=80MHz nodemcu-12h-kit.menu.FlashFreq.80.build.flash_freq=80m nodemcu-12h-kit.menu.FlashFreq.40=40MHz nodemcu-12h-kit.menu.FlashFreq.40.build.flash_freq=40m nodemcu-12h-kit.menu.FlashSize.4M=4MB (32Mb) nodemcu-12h-kit.menu.FlashSize.4M.build.flash_size=4MB nodemcu-12h-kit.menu.FlashSize.8M=8MB (64Mb) nodemcu-12h-kit.menu.FlashSize.8M.build.flash_size=8MB nodemcu-12h-kit.menu.FlashSize.8M.build.partitions=default_8MB nodemcu-12h-kit.menu.FlashSize.2M=2MB (16Mb) nodemcu-12h-kit.menu.FlashSize.2M.build.flash_size=2MB nodemcu-12h-kit.menu.FlashSize.2M.build.partitions=minimal nodemcu-12h-kit.menu.FlashSize.16M=16MB (128Mb) nodemcu-12h-kit.menu.FlashSize.16M.build.flash_size=16MB nodemcu-12h-kit.menu.UploadSpeed.115200=115200 nodemcu-12h-kit.menu.UploadSpeed.115200.upload.speed=115200 nodemcu-12h-kit.menu.UploadSpeed.256000.windows=256000 nodemcu-12h-kit.menu.UploadSpeed.256000.upload.speed=256000 nodemcu-12h-kit.menu.UploadSpeed.230400.windows.upload.speed=256000 nodemcu-12h-kit.menu.UploadSpeed.230400=230400 nodemcu-12h-kit.menu.UploadSpeed.230400.upload.speed=230400 nodemcu-12h-kit.menu.UploadSpeed.460800.linux=460800 nodemcu-12h-kit.menu.UploadSpeed.460800.macosx=460800 nodemcu-12h-kit.menu.UploadSpeed.460800.upload.speed=460800 nodemcu-12h-kit.menu.UploadSpeed.512000.windows=512000 nodemcu-12h-kit.menu.UploadSpeed.512000.upload.speed=512000 nodemcu-12h-kit.menu.DebugLevel.none=None nodemcu-12h-kit.menu.DebugLevel.none.build.code_debug=0 nodemcu-12h-kit.menu.DebugLevel.error=Error nodemcu-12h-kit.menu.DebugLevel.error.build.code_debug=1 nodemcu-12h-kit.menu.DebugLevel.warn=Warn nodemcu-12h-kit.menu.DebugLevel.warn.build.code_debug=2 nodemcu-12h-kit.menu.DebugLevel.info=Info nodemcu-12h-kit.menu.DebugLevel.info.build.code_debug=3 nodemcu-12h-kit.menu.DebugLevel.debug=Debug nodemcu-12h-kit.menu.DebugLevel.debug.build.code_debug=4 nodemcu-12h-kit.menu.DebugLevel.verbose=Verbose nodemcu-12h-kit.menu.DebugLevel.verbose.build.code_debug=5

    This definition (download here) could be put at the end of the list, which is not very practical considering the time it takes to scrolll down the list of ESP32 boards, in version 1.8.19 of the IDE at least. But it can be inserted anywhere within the boards.txt file. Remember, boards are displayed in the Tools menu in the order in which they appear in the file.

  3. The problem with the first two solutions is that any modification will be overwritten when the ESP32 Arduino core is updated. So I used a rather more involved solution, which involves mimicking a complete platform specification just to add a single board.
    1. First create a directory called hardware/local/esp32 in the sketchbook in the Arduino directory.
    2. Copy the content of the ESP32 package (found at ...arduino-x.x.x/portable/packages/esp32/hardware/esp32/2.0.2/ on my desktop) into the newly created directory. Here is the part of the sketchbook directory that was created.
      . ├── hardware │   └── local │   └── esp32 │   ├── boards.txt │   ├── cores │   ├── libraries │   ├── platform.txt │   ├── programmers.txt │   ├── tools │   └── variants ├── ... . .
    3. Replace the boards.txt file with the following content
      ############################################################## # copied from the original boards.txt ############################################################## menu.UploadSpeed=Upload Speed menu.CDCOnBoot=USB CDC On Boot menu.MSCOnBoot=USB Firmware MSC On Boot menu.DFUOnBoot=USB DFU On Boot menu.UploadMode=Upload Mode menu.CPUFreq=CPU Frequency menu.FlashFreq=Flash Frequency menu.FlashMode=Flash Mode menu.FlashSize=Flash Size menu.PartitionScheme=Partition Scheme menu.DebugLevel=Core Debug Level menu.PSRAM=PSRAM menu.Revision=Board Revision menu.LORAWAN_REGION=LoRaWan Region menu.LoRaWanDebugLevel=LoRaWan Debug Level menu.LoopCore=Arduino Runs On menu.EventsCore=Events Run On ############################################################## # copied from esp32s2.name=ESP32S2 Dev Module ############################################################## nodemcu-12h-kit.name=NodeMCU ESP-12H-Kit nodemcu-12h-kit.vid.0=0x303a nodemcu-12h-kit.pid.0=0x0002 nodemcu-12h-kit.upload.tool=esptool_py nodemcu-12h-kit.upload.maximum_size=1310720 nodemcu-12h-kit.upload.maximum_data_size=327680 nodemcu-12h-kit.upload.flags= nodemcu-12h-kit.upload.extra_flags= nodemcu-12h-kit.upload.use_1200bps_touch=false nodemcu-12h-kit.upload.wait_for_upload_port=false #nodemcu-12h-kit.serial.disableDTR=false #nodemcu-12h-kit.serial.disableRTS=false nodemcu-12h-kit.serial.disableDTR=true nodemcu-12h-kit.serial.disableRTS=true nodemcu-12h-kit.build.tarch=xtensa nodemcu-12h-kit.build.bootloader_addr=0x1000 nodemcu-12h-kit.build.target=esp32s2 nodemcu-12h-kit.build.mcu=esp32s2 nodemcu-12h-kit.build.core=esp32 nodemcu-12h-kit.build.variant=esp32s2 nodemcu-12h-kit.build.board=ESP32S2_DEV nodemcu-12h-kit.build.cdc_on_boot=0 nodemcu-12h-kit.build.msc_on_boot=0 nodemcu-12h-kit.build.dfu_on_boot=0 nodemcu-12h-kit.build.f_cpu=240000000L nodemcu-12h-kit.build.flash_size=4MB nodemcu-12h-kit.build.flash_freq=80m nodemcu-12h-kit.build.flash_mode=dio nodemcu-12h-kit.build.boot=qio nodemcu-12h-kit.build.partitions=default nodemcu-12h-kit.build.defines= nodemcu-12h-kit.menu.CDCOnBoot.default=Disabled nodemcu-12h-kit.menu.CDCOnBoot.default.build.cdc_on_boot=0 nodemcu-12h-kit.menu.CDCOnBoot.cdc=Enabled nodemcu-12h-kit.menu.CDCOnBoot.cdc.build.cdc_on_boot=1 nodemcu-12h-kit.menu.MSCOnBoot.default=Disabled nodemcu-12h-kit.menu.MSCOnBoot.default.build.msc_on_boot=0 nodemcu-12h-kit.menu.MSCOnBoot.msc=Enabled nodemcu-12h-kit.menu.MSCOnBoot.msc.build.msc_on_boot=1 nodemcu-12h-kit.menu.DFUOnBoot.default=Disabled nodemcu-12h-kit.menu.DFUOnBoot.default.build.dfu_on_boot=0 nodemcu-12h-kit.menu.DFUOnBoot.dfu=Enabled nodemcu-12h-kit.menu.DFUOnBoot.dfu.build.dfu_on_boot=1 nodemcu-12h-kit.menu.UploadMode.default=UART0 nodemcu-12h-kit.menu.UploadMode.default.upload.use_1200bps_touch=false nodemcu-12h-kit.menu.UploadMode.default.upload.wait_for_upload_port=false nodemcu-12h-kit.menu.UploadMode.cdc=Internal USB nodemcu-12h-kit.menu.UploadMode.cdc.upload.use_1200bps_touch=true nodemcu-12h-kit.menu.UploadMode.cdc.upload.wait_for_upload_port=true #nodemcu-12h-kit.menu.PSRAM.disabled=Disabled #nodemcu-12h-kit.menu.PSRAM.disabled.build.defines= #nodemcu-12h-kit.menu.PSRAM.enabled=Enabled #nodemcu-12h-kit.menu.PSRAM.enabled.build.defines=-DBOARD_HAS_PSRAM nodemcu-12h-kit.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.default.build.partitions=default nodemcu-12h-kit.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS) nodemcu-12h-kit.menu.PartitionScheme.defaultffat.build.partitions=default_ffat nodemcu-12h-kit.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT) nodemcu-12h-kit.menu.PartitionScheme.default_8MB.build.partitions=default_8MB nodemcu-12h-kit.menu.PartitionScheme.default_8MB.upload.maximum_size=3342336 nodemcu-12h-kit.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.minimal.build.partitions=minimal nodemcu-12h-kit.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.no_ota.build.partitions=no_ota nodemcu-12h-kit.menu.PartitionScheme.no_ota.upload.maximum_size=2097152 nodemcu-12h-kit.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.noota_3g.build.partitions=noota_3g nodemcu-12h-kit.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576 nodemcu-12h-kit.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS) nodemcu-12h-kit.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat nodemcu-12h-kit.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152 nodemcu-12h-kit.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS) nodemcu-12h-kit.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat nodemcu-12h-kit.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576 nodemcu-12h-kit.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.huge_app.build.partitions=huge_app nodemcu-12h-kit.menu.PartitionScheme.huge_app.upload.maximum_size=3145728 nodemcu-12h-kit.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS) nodemcu-12h-kit.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs nodemcu-12h-kit.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080 nodemcu-12h-kit.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT) nodemcu-12h-kit.menu.PartitionScheme.fatflash.build.partitions=ffat nodemcu-12h-kit.menu.PartitionScheme.fatflash.upload.maximum_size=2097152 nodemcu-12h-kit.menu.PartitionScheme.app3M_fat9M_16MB=16M Flash (3MB APP/9MB FATFS) nodemcu-12h-kit.menu.PartitionScheme.app3M_fat9M_16MB.build.partitions=app3M_fat9M_16MB nodemcu-12h-kit.menu.PartitionScheme.app3M_fat9M_16MB.upload.maximum_size=3145728 nodemcu-12h-kit.menu.CPUFreq.240=240MHz (WiFi) nodemcu-12h-kit.menu.CPUFreq.240.build.f_cpu=240000000L nodemcu-12h-kit.menu.CPUFreq.160=160MHz (WiFi) nodemcu-12h-kit.menu.CPUFreq.160.build.f_cpu=160000000L nodemcu-12h-kit.menu.CPUFreq.80=80MHz (WiFi) nodemcu-12h-kit.menu.CPUFreq.80.build.f_cpu=80000000L nodemcu-12h-kit.menu.CPUFreq.40=40MHz nodemcu-12h-kit.menu.CPUFreq.40.build.f_cpu=40000000L nodemcu-12h-kit.menu.CPUFreq.20=20MHz nodemcu-12h-kit.menu.CPUFreq.20.build.f_cpu=20000000L nodemcu-12h-kit.menu.CPUFreq.10=10MHz nodemcu-12h-kit.menu.CPUFreq.10.build.f_cpu=10000000L nodemcu-12h-kit.menu.FlashMode.qio=QIO nodemcu-12h-kit.menu.FlashMode.qio.build.flash_mode=dio nodemcu-12h-kit.menu.FlashMode.qio.build.boot=qio nodemcu-12h-kit.menu.FlashMode.dio=DIO nodemcu-12h-kit.menu.FlashMode.dio.build.flash_mode=dio nodemcu-12h-kit.menu.FlashMode.dio.build.boot=dio nodemcu-12h-kit.menu.FlashMode.qout=QOUT nodemcu-12h-kit.menu.FlashMode.qout.build.flash_mode=dout nodemcu-12h-kit.menu.FlashMode.qout.build.boot=qout nodemcu-12h-kit.menu.FlashMode.dout=DOUT nodemcu-12h-kit.menu.FlashMode.dout.build.flash_mode=dout nodemcu-12h-kit.menu.FlashMode.dout.build.boot=dout nodemcu-12h-kit.menu.FlashFreq.80=80MHz nodemcu-12h-kit.menu.FlashFreq.80.build.flash_freq=80m nodemcu-12h-kit.menu.FlashFreq.40=40MHz nodemcu-12h-kit.menu.FlashFreq.40.build.flash_freq=40m nodemcu-12h-kit.menu.FlashSize.4M=4MB (32Mb) nodemcu-12h-kit.menu.FlashSize.4M.build.flash_size=4MB nodemcu-12h-kit.menu.FlashSize.8M=8MB (64Mb) nodemcu-12h-kit.menu.FlashSize.8M.build.flash_size=8MB nodemcu-12h-kit.menu.FlashSize.8M.build.partitions=default_8MB nodemcu-12h-kit.menu.FlashSize.2M=2MB (16Mb) nodemcu-12h-kit.menu.FlashSize.2M.build.flash_size=2MB nodemcu-12h-kit.menu.FlashSize.2M.build.partitions=minimal nodemcu-12h-kit.menu.FlashSize.16M=16MB (128Mb) nodemcu-12h-kit.menu.FlashSize.16M.build.flash_size=16MB #nodemcu-12h-kit.menu.UploadSpeed.921600=921600 #nodemcu-12h-kit.menu.UploadSpeed.921600.upload.speed=921600 nodemcu-12h-kit.menu.UploadSpeed.115200=115200 nodemcu-12h-kit.menu.UploadSpeed.115200.upload.speed=115200 nodemcu-12h-kit.menu.UploadSpeed.256000.windows=256000 nodemcu-12h-kit.menu.UploadSpeed.256000.upload.speed=256000 nodemcu-12h-kit.menu.UploadSpeed.230400.windows.upload.speed=256000 nodemcu-12h-kit.menu.UploadSpeed.230400=230400 nodemcu-12h-kit.menu.UploadSpeed.230400.upload.speed=230400 nodemcu-12h-kit.menu.UploadSpeed.460800.linux=460800 nodemcu-12h-kit.menu.UploadSpeed.460800.macosx=460800 nodemcu-12h-kit.menu.UploadSpeed.460800.upload.speed=460800 nodemcu-12h-kit.menu.UploadSpeed.512000.windows=512000 nodemcu-12h-kit.menu.UploadSpeed.512000.upload.speed=512000 nodemcu-12h-kit.menu.DebugLevel.none=None nodemcu-12h-kit.menu.DebugLevel.none.build.code_debug=0 nodemcu-12h-kit.menu.DebugLevel.error=Error nodemcu-12h-kit.menu.DebugLevel.error.build.code_debug=1 nodemcu-12h-kit.menu.DebugLevel.warn=Warn nodemcu-12h-kit.menu.DebugLevel.warn.build.code_debug=2 nodemcu-12h-kit.menu.DebugLevel.info=Info nodemcu-12h-kit.menu.DebugLevel.info.build.code_debug=3 nodemcu-12h-kit.menu.DebugLevel.debug=Debug nodemcu-12h-kit.menu.DebugLevel.debug.build.code_debug=4 nodemcu-12h-kit.menu.DebugLevel.verbose=Verbose nodemcu-12h-kit.menu.DebugLevel.verbose.build.code_debug=5

      Download here. This is how the board shows up the IDE.

      IDE Tool/Boards/ESP32 Arduino (in sketchbook)

      The downside to this approach is that the 2.0.2 ESP32 Arduino core will continue to be used even when the ESP32 Arduino package be updated. I have tried to take care of that by not copying the ESP32 package as described in step 3.ii. Instead I used symbolic links to the package.

      michel@hp:~/.local/bin/arduino-1.8.19/portable/sketchbook/hardware/local/esp32$ ls -l total 36 -rw-rw-r-- 1 michel michel 9642 avr 20 11:51 boards.txt lrwxrwxrwx 1 michel michel 89 avr 20 01:10 cores -> /home/michel/.local/bin/arduino-1.8.19/portable/packages/esp32/hardware/esp32/2.0.2/cores lrwxrwxrwx 1 michel michel 93 avr 20 01:10 libraries -> /home/michel/.local/bin/arduino-1.8.19/portable/packages/esp32/hardware/esp32/2.0.2/libraries lrwxrwxrwx 1 michel michel 96 avr 20 01:12 platform.txt -> /home/michel/.local/bin/arduino-1.8.19/portable/packages/esp32/hardware/esp32/2.0.2/platform.txt lrwxrwxrwx 1 michel michel 99 avr 20 01:11 programmers.txt -> /home/michel/.local/bin/arduino-1.8.19/portable/packages/esp32/hardware/esp32/2.0.2/programmers.txt lrwxrwxrwx 1 michel michel 89 avr 20 01:11 tools -> /home/michel/.local/bin/arduino-1.8.19/portable/packages/esp32/hardware/esp32/2.0.2/tools lrwxrwxrwx 1 michel michel 92 avr 20 01:11 variants -> /home/michel/.local/bin/arduino-1.8.19/portable/packages/esp32/hardware/esp32/2.0.2/variants

      That saves a bit of drive storage and hopefully when the ESP32 package is updated, the ESP-12H board definition will work with it. Warning: this has not been tested.

      Reference: Hardware Folders structure in Arduino Platform specification documentation

So now a sketch can be uploaded just as easily as with the Lolin32 Lite ESP32 module or the Lolin D1 Mini ESP8266 module and the IDE serial monitor can be used without a problem.

As far as I can determine, PlatformIO cannot be used to program ESP32-S2 based boards against the ESP32 Arduino core because it is using an older version of the core.