System Circuitry and Programming
Last month, Brian presented iPad-based IR “learning” remote and explained some of the theory behind IR code protocols. Now he details the system’s circuitry and covers the technical and programming aspects of the ESP8266 Wi-Fi module.
I‘ve owned Apple’s iPod Touch and iPad for as long as they have been available, and am a big fan. In the first part of this article series, I described a project involving an IR learning remote featuring an iPad (or iPhone, iPod Touch) touchscreen, which replaced the multitude of tiny buttons on most IR remotes. Since each individual remote that’s emulated can have its own screen, it makes it much easier to navigate, particularly at night when it is dark, and also for seniors.
In the first part of this series, I covered the original design concepts as well as shedding some light on the theory behind IR code protocols. In this second part, I am going to explain, in detail, the technical/programming aspects of the Adafruit Industries ESP8266 Wi-Fi module, as well as explaining the overall circuitry. Lastly, I’ll include a brief “user’s manual” for the unit.
ESP8266 WI-FI MODULE
Since the ESP8266 Wi-Fi module was a critical part of the design, I’ll spend a bit of time describing its operation. These modules are basically serial-to-Wi-Fi bridge devices and operate using the 802.11 B/G/N protocols. They have a powerful transmitter (19.5 dBm) and a sensitive receiver. Even with its small, on-board antenna I have had no problems using these devices up to 40’ away from my home router/wireless access point (see Photo 1).
Your microcontroller communicates with the ESP8266 module via a UART link. You must do some preliminary setup to inform the ESP8266 of the SSID and pass phrase of your wireless access point (WAP). After you connect to your WAP, you can then issue commands/data to initiate various forms of internet messages. The 32-bit processor on the module handles all of the difficult tasks involved in a wireless link, allowing even a simple microcontroller, acting as the master controller, to perform some meaningful function with Internet access.
There are a growing number of variations of the ESP8266 module, but the most basic model costs as little as $2 (see Photo 1). It comes with a 4 × 2 pin 0.1” header connector, making it easy to connect to compared to some other modules which use fine-pitch SMD terminals. It contains a standard UART interface and two GPIO lines. Other ESP8266 modules containing more GPIO lines, ADC, and so on are available at a somewhat higher cost.
Regardless of the physical layout of the various modules, the main System on a Chip (SoC) is a Espressif Systems ESP8266EX, which is a 32-bit, ARM-based processor with a complete 2.4-GHz RF transceiver built in. When these devices boot up, the name “AI-Thinker” is displayed. I don’t know if that is the company that makes the modules, the company that wrote the firmware in the SoC, or both. Also on the board is an SPI flash device. On the modules that I have, this is a Winbond 25Q40BT, which is a 4-Mb (512K × 8) flash chip. As far as I can tell, the SoC loads the operating firmware into RAM from this external SPI flash device. Since the ARM SoC runs with an 80-MHz clock, the Quad-SPI mode is used to speed up the transfer of code from the flash to RAM. This protocol transfers data 4 bits at a time, using a 20-MHz clock for the transfers.
You might ask why GPIO lines would be useful on a serial-to-Wi-Fi bridge chip. The answer is that the ESP8266 can be readily (re)programmed with many types of firmware. Some variations of the firmware transform the ESP8266 into a stand-alone device for which such dedicated I/O pins are useful.
There are a few forms of firmware that are currently available for the ESP8266. To put your mind at ease, I’ll note that loading this firmware into the ESP8266 is pretty easy to achieve using the built-in serial boot loader found on all ESP8266 chips. No device-specific programmer is needed.
There are three distinct firmware variations that you can currently load into the ESP8266: serial-to-Wi-Fi bridge firmware using an “AT” command set; the Lua interpreter; and the Arduino IDE. Let’s review each one.
The serial-to-Wi-Fi bridge firmware using an “AT” command set makes the ESP8266 into a slave processor that must receive its commands from a microcontroller via a UART port. The AT commands are short mnemonics that are more cryptic than descriptive of the function they perform. I find it interesting that “AT”-style commands are still being used. They were originally introduced by the Hayes Microcomputer Products for the telephone modems they sold about 35 years ago.
If you connect an ESP8266 running the Lua interpreter to a PC running terminal software, you can send some fairly high-level commands to the ESP8266, and get meaningful responses back. Lua is a scripting language developed in Brazil, and it is similar to many currently popular scripted languages. Using Lua, it is really easy to test whether your ESP8266 is connecting to your WAP, and with just a few commands you can set up a simple web server, for example. Beyond this, you can make up Lua scripts to perform the various data transfers needed for an embedded application. These scripts can be placed in a text file, and then downloaded to the ESP8266, in much the same way that you download the Lua interpreter firmware itself.
The Arduino IDE has been expanded to cover quite a few microcontroller families besides the original 8-bit AVR microcontrollers for which Arduino was designed. The ESP8266 has now been integrated into the Arduino IDE (versions 1.64 and beyond). From this version on, the Arduino IDE comes with a “Boards Manager.” Using the Arduino IDE’s Board menu, you can choose your ESP8266 module and then write code with the same syntax used by the original AVR microcontrollers supported by the Arduino IDE. The ESP8266’s wireless class library closely emulates the original Arduino wireless class library (meant to work with Arduino wireless shields). For anyone accustomed to Arduino, it is an easy way to get your custom program loaded into the ESP8622, transforming it into a stand-alone microcontroller with Wi-Fi capability as well as GPIO, ADC, SPI, and an I2C port (at least on the larger modules that contain more I/O lines).
I used the Serial/Wi-Fi Bridge firmware, as it was a good match for the simple data transfer protocol needed for this project. The ESP8266-01 module that I bought from Adafruit was preprogrammed with the Serial/Wi-Fi bridge AT command set firmware. However, if you order an ESP8266 module from eBay (probably directly from China), you might get a module with or without firmware. For instance, you could get firmware for the Lua interpreter or Arduino IDE, as specified by the vendor, but possibly an outdated version. (Things are changing so quickly with ESP8266 modules that this is a distinct possibility.) Or, it might come without firmware (not too common). So, the first thing you should do with a new ESP8266 module is to connect it to a power source and also connect a USB-to-serial adapter cable between your PC computer and the ESP8266 module. As you do, consider the following.
Depending on the module you buy, it may require a regulated 3.3-V power supply, or it may contain a regulator on-board that allows you to use a higher, nonregulated power source. The documentation with the specific module should specify this. Most ESP8266 modules require 3.3-V logic signals. You must use a USB-to-serial adapter cable that provides 3.3-V logic signals or you will destroy the ESP8266 device. Also note that while many FTDI (and clone) adapter cables are available with 3.3-V logic signals, the VCC pin on these cables often puts out 5 V. So, you may or may not be able to supply power to the ESP8266 module from the USB serial adapter cable, depending upon whether the cable’s VCC voltage matches that needed by the ESP8266 module that you have. The Transmit pin of the ESP8266 goes to the Receive pin of the USB serial adapter. The Receive pin of the ESP8266 goes to the Transmit pin of the USB serial adapter. You have to connect the CH_PD (power down) to VCC to prevent the ESP8266 from entering the IDLE mode. And lastly, unless your module already looks after this, both GPIO0 and GPIO2 should be pulled to VCC with a pull-up resistor.
A quick note about the power requirements for these modules. When the module is transmitting, it requires a current of around 215 mA in short bursts. If you merely put your digital multimeter in series with the power supply line, you will read a current value much lower than this, as your meter will display only the average current over about 0.5 seconds. So, take the 215 mA specified by the data-sheet as being correct.
Many USB-to-serial adapter cables can supply 215 mA. (The maximum available from a USB outlet is 500 mA.) But, if your module seems to be responding to commands but not connecting to your WAP, it may be that your power supply is insufficient to handle these transmit current bursts.
When you power up the ESP8266 module, have a terminal program running on your PC (set to the correct port for the USB-serial adapter cable). You can use the Arduino Serial Terminal if you wish. You will have to set the baud rate in the terminal program, of course. Here is where it gets a bit tricky. Regardless of the ESP8266 firmware loaded, a long string of “garbage” characters is sent out at high data rate. Nothing in this string resembles any normal start-up message. It has been reported that someone has actually measured this with an oscilloscope at about 75,000 bps, but I suspect it actually is 115,200 bps. After this string, if you have the AT command set firmware, you will get the start-up message:[System Ready, Vendor:www.ai-thinker.com]
The actual data rate that you need to set in your PC terminal program will depend upon what version ESP8266 firmware you are running. Try 9,600 bps first since the current versions of both the Lua and the AT firmware currently use this value. Older versions of the AT firmware used 115,200 bps.
While it is fresh in your mind, let me warn you again about this high data rate “garbage string.” When using a terminal program, you can just ignore this string of a few hundred characters and wait until you see the “real” start-up message (although it may be way off the screen to the right). But, if you are connecting the ESP8266 module to a microcontroller running a program of your own, you will have to take some special measures to handle it. What I do is to wait at least 2 seconds after the ESP8266 has been powered up (or its RESET pin negated). By then, all of the “garbage” characters will have already been sent. Only after this time delay, do I open up the microcontroller’s serial port at the correct baud rate. Doing it this way, I don’t capture the start-up message at the end and can’t compare it to the legitimate start-up string. But trying to search for the start-up message with so many high baud rate “garbage” characters preceding it would be difficult anyway. It’s better to check for a valid response to the first command that you issue the module, in my opinion.
As a last point, note that the ESP8266 Wi-Fi-to-serial bridge firmware (using AT commands) needs a <CR><LF> after any command that you send it. Your terminal program might send only a <CR> by default, and you will have to change it. Refer to the Reference section at the end of this article for a document describing the first steps associated with using the AT firmware.
LOADING THE FIRMWARE (OPTIONAL)
Let’s review the steps needed for loading firmware that’s different than what came with the ESP8266 module. The first thing to do is to provide a way to put the ESP8266 into the serial boot mode. This requires two switches. Some modules already have these, but if not, you need a RESET switch (from the RST pin to ground, as well as a 100-kΩ pull-up resistor from there to VCC) and a PROGRAM switch (from GPIO0 to ground, and as well as a 100-kΩ pull-up resistor to VCC).
To enter Programming mode, press and hold the PROGRAM switch while pressing/releasing the RESET switch. Some modules have an LED mounted, and when you are activating the Programming mode, the LED will be brightly lit when the switch is pressed and dimly lit when released. Other boards without such an LED will show no indication whether they are in the Programming mode, apart from passing/failing the programming procedure.
To burn the Wi-Fi/serial bridge firmware (AT command set), you need the Expressif ESP8266_Flasher application for Windows, as well as the binary file to load into the ESP8266. Refer to the References section of this article for a link to these. Photo 2 is a screen capture of this program in the process of programming the ESP8266.
To incorporate an IR code “learning” function into this module, I chose Atmel’s ATmega1284P AVR microcontroller, which contains 8 KB of SRAM. If you are planning on examining/changing the Arduino source code for this project, you will have to use the Arduino IDE’s board manager to import and use the “original Mighty 1284P 8 MHz” board. The ATmega1284P is run with a VCC of 3.3 V, since that is what is required by the ESP8266 module. The ATmega1284P isn’t specified to run at 16 MHz at 3.3 V, so I used an 8-MHz clock instead.
Note: When you get an ATmega1284P fresh from the factory, its internal fuses are set to enable the JTAG function. This uses PORTC as the JTAG port. Use your programmer to edit this fuse and disable the JTAG function, so that PORTC will work normally. The LCD is connected to PORTC and won’t work if this is not done.
Figure 1 shows the project’s circuitry. I used a common 2 × 16 LCD to provide user feedback during the IR learning process, as well as displaying status information when the unit is attempting to connect to the wireless access point at start-up. User input is provided by a single rotary encoder and an ENTER switch. These are all mounted on the top of the cabinet, as shown in Photo 3. To store all of the “raw” IR codes requires a significant amount of EEPROM space, as I mentioned earlier. I determined that a 32K × 8-bit SPI EEPROM would be sufficient to handle at least 100 button codes, which was more than enough for my needs. I chose the Atmel AT25256 as I had them on hand from past projects.
To receive the IR codes during the Learning mode, I chose a Vishay Intertechnology TSMP1138, which is a special-purpose IR receiver module made specifically for IR learning remotes. Note the presence of filter capacitors C4 and C5 right across the power supply terminals. These are recommended by the manufacturer to prevent any high-frequency noise that may be riding on the power rails (mainly from the microcontroller) to enter the IR module, disrupting its sensitive amplifier circuits.
During normal operation, we must send out the IR codes to the target home entertainment device. A Vishay Intertechnology TSAL6400 IR LED is capable of being driven at high current levels in a pulse mode such as this. I used Q1 to drive the LED, and a 56-Ω resistor limits the IR LED current to about 60 mA. At this level the unit had no problem triggering my various home entertainment devices at distances of 15’ or so. I also drive a visible LED simultaneously. The user can confirm that when a button is tapped on the iPad screen, this visible LED will flicker to indicate that this signal has passed—from the iPad to the router to this unit—and has been translated into a valid IR code. Refer to Photo 4 to see the TSMP1138 IR module and the two LEDS. I mounted a red plastic filter on the front panel to block stray room light from the TSMP1138 (and it looks better than a hole).
I fitted a six-pin header in the “FTDI Friend” configuration and connected it to the ATmega1284’s second USART port. This enables you to connect either an FTDI USB/serial cable (3.3 V model only!) or an Adafruit FTDI Friend module for troubleshooting/diagnostic purposes. During the IR learning process, all of the “raw” IR code information is sent out this serial port so it can be examined in a serial terminal (set to 9,600 bps). Also, as a one-time operation, you would need to use this serial link to your PC to enter your router’s SSID and pass phrase information. In this configuration mode, the unit prompts you for these two parameters, which are then stored permanently in the microcontroller’s EEPROM.
The ESP8266 module is wired to 3.3-V power, and its RST line is connected to the ATmega1284P’s PD7 line. This enables the ATmega1284P to control the ESP8266’s actual reset time. This reset timing is important, as mentioned earlier, in regards to the long stream of high-data rate characters that are emitted from the ESP8266 module at start-up. This must be ignored by the ATmega1284P’s USART port.
The ESP8266 CH_PD pin must be pulled high in order for the module to operate. The Rx, Tx lines between the ESP8266 and the Atmega1284P are hooked up with an additional jumper and four-pin header. These enable you to connect up a USB/serial cable directly between the ESP8266 and a PC, which is useful early on when you are testing the ESP8266’s responses to the AT command set. As noted earlier, you must ensure that your ESP8266 is using version 0.9.2.2 firmware and not an earlier/different version.
One disadvantage of using low-cost Wi-Fi modules made in China, such as the ESP8266, is that there can be pretty rapid changes in the firmware occurring as the manufacturer adapts to user problem reports and feature requests. In a project such as this where the master MCU is using the ESP8266 as a Wi-Fi/serial bridge co-processor, it is important that your ESP8266 has the correct level of firmware loaded, or it may not respond correctly to the commands sent to it from my program in the Atmega1284P microcontroller.
Power is supplied to the unit from a 5-V/1-A AC wall adapter. I chose one of the newest wall adapters available that require virtually no idle power, as the project really only draws any appreciable power when it is receiving Wi-Fi button messages/sending out IR pulse trains. A Texas Instruments LM1086-3.3 low dropout regulator is used to supply all of the power to the unit, with the exception of the IR/visible LEDs, which are powered by the 5-V supply directly.
While not shown in Figure 1, I mounted the standard Atmel six-pin AVR in-circuit serial programmer header and connected it to the microcontroller’s SPI port pins, etc. I did this so I could program the ATmega1284P using the Atmel AVRISP mkII programmer, rather than burning the Arduino serial bootloader into the Atmega1284P and then using the Arduino serial bootloader.
The project has to work in three basic modes: configuration mode, learning mode, and operating mode. I decided to include a small character LCD panel for messages and a rotary encoder/ENTER switch for a simple user interface. I also included a USB/serial link to a PC.
In configuration mode, you must enter some configuration information such as the SSID and passphrase of your Wi-Fi access point (router). These only have to be entered once, assuming that you keep the same router and don’t change the password. Because these are alphanumeric values, and can be long, I decided to implement this function via a USB/serial link to a PC, rather than add a keypad and larger LCD. When you choose this mode, and are running a terminal program on the PC (at 9,600 bps), you will be prompted for both the SSID and the passphrase. After entry, these values are stored in the ATmega1284P internal EEPROM.
In learning mode, the unit displays the current button number and waits for you to tap the associated button on your remote. After the IR pulse train is complete, the LCD panel will display “got it,” and the pulse parameters will be sent out the USB/serial link to the PC (for diagnostic purposes only). If you run a terminal program, you can see all of the pulse parameters that have been captured and stored in EEPROM memory. During the learning mode, the unit will automatically increment the button number after each “capture.” Also, if you were to “learn” all of the buttons of one remote, and then shut the unit down, it will automatically position you at the next available button number, when you start up again to do subsequent remote controls.
In operating mode, you have presumably already learned/stored all of the necessary buttons for your remote controls (and configured the SSID/passphrase). The unit will wait for button numbers to be received from your iOS device via the third-party Mote application, which I mentioned earlier. For any valid number (other than 0) that it receives, the unit will use that number to do a look-up into a table held in the ATmega1284P’s EEPROM. The value returned is the starting address of the “raw” IR code that is stored in an external AT25256 SPI EEPROM (from the “learning” process performed beforehand). The firmware will read this information (including the length of the code) from the AT25256 EEPROM into the ATmega1284P’s SRAM memory. Then it will call a routine that converts these codes into the proper IR pulses at the proper carrier frequency (which is also stored in the table). These pulses are sent out via a TSAL6400 IR LED connected to PortD5. I also included a regular red LED in this circuit, so I could see when an IR pulse train was being sent. The program also displays the button number received from the iPad on the unit’s LCD panel.
When the unit is first turned on, it will check to see if the Enter button is pressed. If it is, it indicates that the user wants to enter either the initial configuration mode or the learning mode. Once you release the button, the LCD panel will display each set-up mode separately, as you turn the rotary encoder. Press the Enter button when the desired mode is displayed and then proceed as I explained earlier. However, if the Enter button is not pressed at start-up, the ATmega1284P will send various AT-style commands via a serial link to the ESP8266-01 module. This initialization routine should connect the ESP8266-01 module to your Wi-Fi access point, using the SSID and passphrase stored in EEPROM. Each step of this process, including the relevant AT command, is displayed on the LCD panel. If all goes well, it will indicate that a good connection has been established, and will also display the IP number that your router has assigned to the ESP8266-01 module. You will need to record this number, as the Mote app on your iOS device will need to know the IP address to which it must send its button commands.
Generally, every time a given device is connected to a Wi-Fi access point, it will be issued the same IP number by the access point (using DHCP). However, you can’t always count on this! Therefore, I accessed my router’s administrative homepage via a web browser and went into the advanced settings where I could assign a fixed IP number to a specific Wi-Fi device. I assigned a fixed IP number to the ESP8266-01 module. Generally, in order to do this, you need to know the MAC number of the ESP8266-01 module. If you don’t know the MAC number, you can get this from the LuaLoader software for the PC, since it reveals the MAC number prior to programming. But remember that you don’t want to actually program the ESP8266 with the Lua interpreter for this project! Note that the DHCP protocol is still being used, except that the router is always issuing the same IP number to the ESP8266 module in this case.
I’ll also mention that my ATmega1284P firmware will periodically reset the ESP8266 and request a new IP lease from the router. This is necessary, since your router may terminate the ESP8266’s IP lease after a while if it sees no traffic coming from the ESP8266. This will happen often enough, as you are not watching the TV all of the time, right?
I don’t like the thought that I now have two spare home-built touchscreen IR remotes gathering dust, while I use this newest model exclusively. But I am surrounded by lots of commercial tech items that have only served a useful purpose for a few years, so I am getting used to this. While you may be entirely satisfied with your IR remotes, the concept of this project, combined with the easy-to-use “Mote” iOS app, might prompt you to come up with your own remote control applications for your Apple iOS device.
Author’s Note: The ESP8266-01 module that I obtained from Adafruit is no longer supplied by them. However, ESP8266-01 modules are readily available from many other on-line sources, such as SparkFun Electronics (www.sparkfun.com).
Adafruit Industries, “Adafruit HUZZAH ESP8266 Breakout,” 2015, https://learn.adafruit.com/adafruit-huzzah-esp8266-breakout.
ElectroDragon, “ESP8266 AT Command Set,” V0.9.2.2, www.pridopia.co.uk/pi-doc/ESP8266ATCommandsSet.pdf.
FTDI Friend module
Adafruit Industries | www.adafruit.com
ATmega1284P Microcontroller and AVRISP mkII programmer
Atmel | www.atmel.com
Espressif | www.espressif.com
TSMP1138 IR Receiver and TSAL6400 IR LED
Vishay Intertechnology | www.vishay.com
Mote iOS App
Worried Cat LLC | www.worriedcat.com
ESP8266 AT Command firmware flasher program (v0.9.2.2 AT Firmware.bin)
XESS Corp. | www.xess.com/blog/esp8266-reflash/
PUBLISHED IN CIRCUIT CELLAR MAGAZINE • JUNE 2016 #311 – Get a PDF of the issue