Tuesday 22 March 2016

Updating firmware on ESP8266 devices using the Raspberry Pi

I've outline how to update the firmware on the Pimoroni ESP8266 pHAT and I thought I would expand on that a little by detailing how to use the Raspberry Pi to flash the firmware for other ESP8266 devices.  I've have a couple of NodeMCU boards which I got shipped from China for £3.75 each.  Here is one of them along side a Pimoroni pHAT:


I've been playing around with them on a PC but thought I would give one a try on a Raspberry Pi.  This device is a nice little package containing a ESP8266, a USB to serial controller and a 3.3V regulator so that the device can be powered directly from USB.  There are also 2 buttons.  One marked 'flash' and the other 'user'.  They came with the stock Espressif firmware but I have been experimenting with other files.  Using it with a Raspberry Pi is much like using the pHAT with the same tools needed.

Start with a fully patched and upgraded 'Jessie' image and install Minicom:

sudo apt-get install minicom

and then create a convenient working folder where you can download and make executable the flashing tool:

wget https://raw.githubusercontent.com/themadinventor/esptool/master/esptool.py
chmod +x esptool.py


More information about this tool can be found here and also in my previous post.  Once you have done this you have all the tools that you need and so you can connect the ESP8266 to the Pi via a USB cable.  The Pi will happily allow you to hot plug it and so we are ready to connect to the device but first we need to know what the serial port is named.  It is probably /dev/ttyUSB0 but we can check this by searching for serial devices that actually have a driver (and not just virtual devices) as follows:

 ls -l /sys/class/tty/*/device/driver

Which on my Pi gives:

lrwxrwxrwx 1 root root 0 Mar 22 17:06 /sys/class/tty/ttyAMA0/device/driver -> ../../../../bus/amba/drivers/uart-pl011
lrwxrwxrwx 1 root root 0 Mar 22 17:09 /sys/class/tty/ttyUSB0/device/driver -> ../../../../../../../../../bus/usb-serial/drivers/ch341-uart


both the built in UART and the USB device.  Now we can connect to the ESP8266 using Minicom:

minicom -b 115200 -o -D /dev/ttyUSB0

and send it an AT command:

AT

OK


You have to add Ctrl-j after the carriage return for it to work.  Once you see that it is working you can reset the device.  To do this the 'rst' pin needs to be grounded.  You can use a paper clip to briefly connect the pin to the neighbouring ground pin and you will see the LED on the device blink and loads of random characters printed to Minicom before ending in 'ready'.  The device has been hard reset.  The next thing to test is programming mode.  Hold down the button marked 'flash' while doing a reset with the paper clip.  This time the text in Minicom won't display 'ready' and you can't enter commands.  The device is in programming mode.  Close down Minicom so that it doesn't conflict and you are now ready to test with the programming tool:

./esptool.py -p /dev/ttyUSB0 read_mac

should show:

Connecting...
MAC: 5c:cf:7f:0c:40:d5


which is the MAC address of the device.  It's now ready to be programmed and I explained how to do that in my last post.

Monday 21 March 2016

Updating the firmware on the Pimoroni ESP8266 pHAT

Pimoroni recently released their ESP8266 pHAT for the Raspberry Pi and while there is plenty of information on the ESP8266 board itself there is much less about how it is connected to the Pi.  Richard Hayler has a post about getting started with the pHAT but it doesn't go beyond the basics.  I've explored the board a little more and have managed to write firmware to the device from the Pi which I will document here.

Richard has shown how to get started which I will only cover briefly here.  They are:
  • Create a new Rasbian 'Jessie' image.
  • Do updates.
  • Do upgrade.
  • Install Minicom.
  • Edit /boot/cmdline.txt to remove the reference to console=ttyAMA0
  • Power down and attach the pHAT.
  • Power back up and connect to the ESP8266 over serial using Minicom.
For convenience I wrote a quick shell script to start up MinicomOpen a new file called 'term' in your favourite text editor and type:

#!/bin/bash
minicom -b 115200 -o -D /dev/ttyAMA0


Save the file and exit and the make it executable by typing:

chmod +x term

from a command prompt.  You can now run it with:

 ./term

Now you should be able to communicate using the AT commands as Richard outlined.  Don't forget that you need to press CTRL+j after hitting return.  So far, so much the same but we need a way to reset the ESP8266 and put it into 'flash' mode.  There is not much documentation on the pHAT but a few minutes with a multimeter showed me that the 'reset' pin on the ESP8266 is connected to GPIO 17 on the Pi and GPIO #0 on the ESP8266 is connected to GPIO 27 on the Pi.  This allows the ESP8266 to be both hardware reset and put into programming mode.  The latest 'Jessie' version of Raspbian has the handy gpiozero Python module installed and we can use this to toggle the GPIO lines with a simple Python script.  Open your editor or, if you prefer, Idle for Python 3 and enter the following code:

#!/usr/bin/env python3
from gpiozero import OutputDevice
from time import sleep

# reset on pin 17, active low
rst = OutputDevice(17, False)

rst.on()
sleep(0.5)
rst.off()
rst.close()


then save it at 'reset.py'.  Make sure you have Minicom open and connected to the ESP8266 so that you can see that the script is working. You can test it from within Idle or make it executable before running it from the command line:

chmod +x reset.py
./reset.py

You should see lots of rubbish scroll by in Minicon before seeing 'ready' and allowing you to type AT commands again.  What the script above does is to define pin 17 as an output called 'rst' which is 'active' low.  ie it is normally high but when it is turned 'on' it goes low.  First the pin is turned 'on' (goes low), then we wait for half a second and turn the pin 'off' again (goes high).  This will reset the ESP8266 and restart the firmware.  We now have a handy way of resetting the device.

The next task is to put it into programming mode.  To do this GPIO #0 on the ESP8266 has to be sent low while we do the reset.  Here is the script to do this:

 #!/usr/bin/env python3
from gpiozero import OutputDevice
from time import sleep

# reset on pin 17, active low
rst = OutputDevice(17, False)
# flash mode select on pin 27, active low
flash = OutputDevice(27, False)

flash.on()
sleep(0.5)
rst.on()
sleep(0.5)
rst.off()
sleep(0.5)
flash.off()
rst.close()
flash.close()


This script defines a second pin (GPIO 27) as 'flash'.  As you can see we turn 'flash' 'on' before doing the reset.  Then we turn it off (remember that these pins are set as active low and so 'on' means going low).  Save the script as 'flash.py' and then make it executable before running it:

chmod +x flash.py
./flash.py

When this script is run you should see the while LED on the pHAT flash briefly and this time Minicom will no longer come back to being ready and you can't type commands.  We are in programming mode.  We can get back into the normal mode of operation by simply running the 'reset.py' script.

Next we need a tool to access the device in programming mode.  There is a platform independent tool on GitHub which is handily also written in Python.  There is loads of information on the tool which includes a manual for all the commands.  We can download it to the Pi using wget and then make it execuatable:

wget https://raw.githubusercontent.com/themadinventor/esptool/master/esptool.py
chmod +x esptool.py

Now we put the ESP8266 into programming mode and test the tool to see that we have a connection.  Make sure you close Minicom first so that it doesn't conflict:

./flash.py
./esptool.py -p /dev/ttyAMA0 read_mac

Hopefully you should see a message like the following:

Connecting...
MAC: 5c:cf:7f:12:72:e7


and the MAC address for the WiFi chip will be displayed.  Another useful command tells us the device id for the flash chip in the device:

./esptool.py -p /dev/ttyAMA0 flash_id
Connecting...
Manufacturer: e0
Device: 4016


As you can see the numbers returned are pretty opaque but another GitHub project has a list of many of them.  The chip in my device is 32 Mbits in size, ie 4 MBytes.

Now we need some firmware to flash.  Of the many pages of resources for the ESP8266, this is one of the most useful.  For this test I'm going to update to the latest official firmware from Espressif. Espressif's board is difficult to navigate and much of it is in Chinese but the latest firmware is posted on their announcement page.  You want to go to 'latest release' Then click the download link for the 'Non-OS SDK' and on that page scroll past the notes and comments to where the file is attached (I said it was complicated, and the exact location might change.)  As I write this, version 1.5.2 is the current file.  Also useful is the current AT commands document.  Besides the command list it also shows which files should be flashed into which locations for different flash sizes.  The firmware is a zip file that contains all source code as well as the binaries.  I unzipped this file on a PC and just moved the 'bin' folder over to the Pi.  Then using the document above I worked out which file I had to flash to which location and then used this command to write them:

./esptool.py -p /dev/ttyAMA0 write_flash 0x7e000 bin/blank.bin 0x3fe000 bin/blank.bin 0x3fc000 bin/esp_init_data_default.bin 0x00000 bin/boot_v1.5.bin 0x01000 bin/at/512+512/user1.1024.new.2.bin

and after 40 seconds I had this:

Connecting...
Erasing flash...
Took 0.09s to erase flash block
Wrote 4096 bytes at 0x0007e000 in 0.4 seconds (84.2 kbit/s)...
Erasing flash...
Took 0.08s to erase flash block
Wrote 4096 bytes at 0x003fe000 in 0.4 seconds (84.7 kbit/s)...
Erasing flash...
Took 0.08s to erase flash block
Wrote 1024 bytes at 0x003fc000 in 0.1 seconds (84.4 kbit/s)...
Erasing flash...
Took 0.13s to erase flash block
Wrote 4096 bytes at 0x00000000 in 0.4 seconds (81.5 kbit/s)...
Erasing flash...
Took 1.66s to erase flash block
Wrote 397312 bytes at 0x00001000 in 39.4 seconds (80.7 kbit/s)...

Leaving...


All that remaind was to use the reset command to boot the new firmware, connect with Minicom and check the version:

AT+GMR
AT version:0.60.0.0(Jan 29 2016 15:10:17)
SDK version:1.5.2(80914727)
compile time:Jan 29 2016 19:07:08
OK


and we have flashed new firmware!  
 

Sunday 20 March 2016

Welcome

Welcome to my blog.  I don't expect to be blogging that often and this is really just a place to post technical information that interests me and to document any projects that I might be working on.  It's not going to be a place for random musings, so expect posts on software and hardware projects and maybe tabletop gaming, writing and science fiction and fantasy.

Paul