Sunday, September 15, 2019

Misadventures with an ESP-01 board (ESP8266 wifi module)

To add wifi capability to an electronics project, the ESP8266 chip is apparently a popular choice.  It is a microcontroller with a wireless ethernet stack built in.  We got three ESP-01 boards that feature this chip, an antenna, and some flash memory (1 MB).  They are very small!


The tutorials on this board are generally quite confusing, as you can incorporate it easily into a project of your choosing in many ways.  Many makers are familiar with the Arduino platform and are comfortable with its development tools, even though this isn't entirely necessary.  Also, there appears to be a tradition of "hello world = flashing LED" tutorials for Arduino.  This tradition extends to ESP-01 boards in a somewhat unfortunate way. 

The ESP-01 board ships with an old-school Hayes-modem "AT" command interface.  It talks to a host via serial at 115200 baud out of the box -- though with 3.3 V signaling instead of 5 V or RS-232 levels.  (Nearly everyone warns you that 5 V will kill the device, but that actually seems a bit suspect.  I imagine RS-232 levels would really toast it, though!)  In any case, if you hook up a serial terminal, you can talk AT commands and pretty easily connect the board to a nearby access point.  The commands are

AT+CWMODE_CUR=3
AT+CWJAP_CUR="<ssid>","<pwd>"

If you want to see what access points are visible, use

AT+CWMODE_CUR=3
AT+CWLAP

If you want to see what IP you've been assigned once connected, use

AT+CIFSR

The documentation for all the commands is located here. a nice short listing of commands is here.  It's essentially like a cross between old-school modem commands and sockets programming.

Since modern computers don't have a hardware serial port (and most old hardware serial ports don't support 115200 baud), you typically use a USB-to-serial converter.  There are many of these available -- I have several -- but for a quick hack you can coerce an Arduino into helping.  Actually, "coerce" is the right word, because what you do is hold the Arduino in a reset state (it's effectively disabled) while you hijack its USB-to-serial chip.  Here's the circuit that I used.  The resistors form a voltage divider that brings the Arduino's 5 V signaling down to 3.3 ish volts.  (It didn't make much of a difference when I hooked the RX lines directly together, though that is apparently ill-advised...) 


Since I am using an Arduino Mega held in reset, it seems that plenty of 3.3 V is available for the ESP-01, contrary to the many tutorials warning that a separate power supply is required.  I imagine you might have problems if you allow the Arduino to boot up.


OK, back to the unfortunate part of the story.  Since the tradition is to make an LED flash as your first project, there are many tutorials explaining how to make an ESP8266 flash an LED.  This involves -- naturally enough -- overwriting the flash memory with a program that simply toggles one of the GPIO pins.  However, this means that the modem firmware gets overwritten!  If you're a newbie (or even if you're not), this means that the ESP-01 board is now useless as a wifi dongle!  Putting the original firmware back is not exactly a trivial task.

I was faced with the task of reflashing 2 of the 3 ESP-01 boards we have.  (The remaining one was fortunately unharmed, so I was able to figure out how it was supposed to work!)

First of all, you need special software that understands how to flash memory on the board with the ESP8266 chip.  Fortunately, the right tool for the job is an open source python script esptool which has minimal dependencies.  Starting this up was no problem, and I started by re-using my existing circuit.  I figured that I would start by clearing the flash memory, since I already knew it to be useless...

$ python esptool.py --port /dev/ttyACM0 erase_flash

Sadly, this just hung while "connecting".  I hooked up my logic analyzer to the TX and RX lines, and was able to verify that data was getting transferred, so it looked like the chip was merely ignoring the commands.  After digging some more, I found that the right course of action was to ground the GPIO0 pin first.  This puts the ESP8266 chip into a "flash mode", which is required for programming it.  To start programming, you briefly pulse the RST pin to ground to reset the chip.  Then it happily started flashing the memory, or so I thought. 


However, as it turns out my board has a flash chip that doesn't like the default SPI settings.  Unfortunately, they appear to work just fine, and the files I flashed even verify correctly through esptool.  But they are wrong!  There are some dark words in Amazon reviews for the ESP-01 about defective boards, but that didn't seem to add up.  The boards were indeed talking -- I could watch the data transfer both directions on my logic analyzer -- so I didn't think they were defective. 

After a bit more poking, I found the solution.  The problem is that the default setting in epstool optimizes runtime, using the fastest protocol to write the flash.  Apparently this isn't supported by all flash chips, and it silently causes problems with some of them.  There's a detailed explanation of what's going on in the esptool documentation and on the Wikipedia page for the Serial Peripheral Interface

OK.

Let's flash the board correctly!

You can use the stock firmware, by following detailed instructions about the flash map in their documentation.  But there is also an enhanced version of the firmware that adds a few additional AT commands.  It's a little easier to flash the enhanced version since it's all in one contiguous block starting at address 0x00000 rather than several separate files flashed into different addresses, which is how the stock firmware is distributed.  In any case, the command to do the job is

$ python esptool.py --port /dev/ttyACM0 write_flash 0x00000 AiThinker_ESP8266_DIO_8M_8M_20160615_V1.5.4.bin --flash_mode dout

This set things right, and the boards once again respond to AT commands!

Saturday, September 14, 2019

Morse code trainer



This is a quick weekend project.  I wanted something that would send random strings of characters in Morse code, grouped into sets of 3 or 4 at at time.  This little box has a power switch, a speaker, a knob for volume, and a knob for sending speed.  It's powered by a 9v battery, and is controlled by an Arduino Nano.  There's really not much else to it except for the code.