Wireless Arduino Programming with Electric Imp
Getting Started
This tutorial will show you how to use an Electric Imp to repogram an Arduino from a webpage. Yep, you read that right. Now you can reprogram an Arduino (and an Imp) from anywhere in the world!
The Electric Imp is a powerful device that allows you to connect to the internet relatively easily. For a lot of my Imp projects, I use an Arduino to handle the interface between the various bits of hardware. While reprogramming the Imp is extremely easy via their web-based IDE, reprogramming an Arduino is much more tedious and requires plugging in a computer and downloading new code. Why not use the Imp's wireless connection to push new Arduino sketches as well?
If you've ever installed an Arduino into a place that required a scissor lift, in a water tight enclosure, on the top of a building, or into a paper-mache piƱata, you understand how problematic it can be to fix that bug you never imagined. With a few bits of hardware you can have an Arduino attached firmly to the Internet of things as well as making the Imp+Arduino a heck of a lot easier to reprogram.
What in the world is Tomatoless Boots? Sorry. It's a joke first told by Rob Faludi:
Wireless is a pointless way to describe wireless. It only describes what wireless is not, not what it is.
For example, it also has no tomatoes, so we might as well call it 'tomatoless'.
And since it's a bootloader of sorts, we decided (against good judgement) to call it Tomatoless Boots. Zomg thank you Aron Steg for writing the original Imp code. We took his code and made a few improvements to dramatically improve the bootload time and to get it to work with general Arduinos.
Required Materials
Parts you'll need:
Along with the above parts, you'll need the following tools.
- Exacto Knife
- Soldering iron and a bit of wire
- Local Wifi access
This reprogramming-over-wifi trick only works with ATmega328 based Arduinos with a serial bootloader such as the Arduino Uno, Fio, LilyPad, Pro, Pro Mini, and RedBoard. This tutorial will not work with the Due, Leonardo, Micro, Galileo, or Teensy. There are probably some really good ways of getting these other boards to bootload over wifi but their bootloaders are different enough that this tutorial doesn't attempt to cover them.
Suggested Reading
Other tutorials you may want to brush up on before diving into this one:
Bootloading 101
Now for a bit of history and bootloader basics:
There have been lots of serial bootloaders written throughout the years for lots of different microcontrollers. I wrote one for the PIC ages ago and one to wirelessly bootload Arduinos over XBee as well. The Arduino originally used the STK500 bootloader written by Atmel(see app note AVR061) that was then updated by Peter Knight and Bill Westfield to become the shrunk down Optiboot. Optiboot and a handful of similar bootloaders are what are installed on every ATmega328 based Arduino today.
The serial bootloader is activated each time the ATmega328/Arduino is powered up or reset. For a brief period of time (about 500ms), the microcontroller will listen for a special set of characters. If it hears nothing from the computer, then the ATmega will exit the bootloader and begin to run the user's code that resides in flash memory. However, if the microcontroller hears those special characters, then it will know that a new program needs to be downloaded and begins to wait for a HEX file to be sent. Normally this communication is done while connected to a computer (via a USB to serial connection), but anything capable of attaching to the serial port on the Arduino has the option to reprogram it. The Imp can talk serial with ease, and the fact that it connects to the world wide web so easily makes it a good choice for wirelessly bootloading your board.
Hardware Connections
The very first step is to solder the Arduino headers to the Imp shield. For more information about how to do this, checkout this tutorial.
Next, we need to re-route the Imp's UART to the Arduino's serial pins (0 and 1). By default the Imp Shield connects the Imp's serial port (pins 5 and 7) to Arduino's pins 8 and 9.
Luckily, the genius behind the Imp shield design had the foresight to make it easy to switch pins (Jim is awesome). On the back of the shield, you'll find two jumpers labeled RX and TX. In the image above, you should see a small trace connecting the TX and RX pins of the Imp to the right pads labeled 8 and 9.
Carefully use an exacto knife to cut the default trace. If you've never cut a trace before don't worry - it's easy! Just take your time. Cutting a trace is less like cutting through metal and more like scoring tile or scraping ice off your windshield; it takes a few passes. Once you've cut the traces, use a multimeter to do a continuity test to verify that you have indeed severed the connection between the center pad and the pad to the right.
Next, add some solder and jumper the center pads to their matching left pad. The Imp should now be wired directly to the Arduino's serial port.
The final hardware modification is a jumper from P1 of the Imp to RST on the shield. This will allow the Imp to reset the Arduino whenever it pulls the P1 pin low.
Once you've soldered the jumpers and single wire, add the Imp shield to your Arduino and connect a USB cable. Assuming you have commissioned your Imp to your local wifi, the Imp should power up, blink red, then blink green as it attaches to the Internet.
Now why did I tell you to take your time cutting the default traces? Because I made a big mistake when cutting the default TX trace. Have a second look:
Don't see the problem? How about now:
I was going too fast, the cut I made was too long, and I ended up cutting the TX trace to the Imp. When I attached everything to my Imp bootloading failed to work; everything was timing out because the Imp never heard a response from the Arduino (because the TX trace was cut). Luckily, I had a second functioning setup, so I tested my code on that. Everything worked, so I knew it must be a hardware problem with the board I was using for this tutorial. After a few minutes of scratching my head I used a multimeter to start probing for continuity. Once I discovered TX was not connected I tracked down this bad cut.
With some 30AWG wire wrap wire and some hemostats, the trace was quickly repaired, and the board started working as expected.
Take extra time when cutting traces so as to not cut beyond or knick nearby traces.
Software Connections
We are going to assume that you have already commissioned your Imp and gotten it onto your local wifi. Log in to your Electric Imp account and open the Imp IDE. Here is the code you'll need to load code into the Agent:
And here is the code you'll need to load into the Imp Device:
Once you've successfully loaded both bits of code, find the agent link at the top of the page. Open another browser tab, and navigate to the agent link. You should be presented with a simple HTML page:
From here you can select the hex file you would like to send to your Arduino. The HEX file is found after compiling your sketch in the Arduino IDE. We'll tell you how to get these HEX files in the next section. For now, use these two:
Download these HEX files to your local computer. Select the Blink-1Hz.hex
from the 'Choose File' button, then 'Send' the file to the Arduino. After a few seconds, your Arduino should be bootloaded with the new program! The LED should be blinking once per second. Now select the Blink-Fast hex file, and upload it. The LED should now be blinking four times per second.
The Imp will provide various bits debug information as well during booloading. If you run into issues, be sure to check the output from the Imp IDE.
Getting HEX
By default, Arduino outputs the HEX file of your sketch to a rather hard to find, hidden, temporary folder such as C:\Users\Cylon\AppData\Local\Temp\build7734646579940080062.tmp\Blink.cpp.hex
. Here's a trick to make change the output folder of Arduino to an easier to find C:\HEXFiles\Blink.cpp.hex
.
Open Arduino, and click on File->Preferences. This will show you where the preferences.txt
file is stored. If you move your cursor to this area of the window, the directory will turn blue, and if you click on it, you will open the directory that contains the preferences.txt
file. You must close Arduino before editing this file. Every time Arduino closes, it will overwrite the preferences file with the current settings. If you edit the preferences file while Arduino is open all your changes will be lost.
With Arduino closed, open the preferences.txt
. Add a line:
build.path=C:\Arduino-Output\
Or the equivalent path for your OS. Any path without spaces is valid. I enjoy pointing both my Arduino sketch folder and output folder to a dropbox folder so that I can share libraries and HEX files between computers. You will need to avoid spaces in your build.path otherwise you may see this error:
C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-ar: unable to rename 'core.a'; reason: File exists
For example: build.path=C:\Arduino HEX Files\
does not work because of the spaces.
Once you have a path in place, save the changes, and close the file. Reopen Arduino, and open a sketch of your choice (use the Examples->Digital->Blink if you have no other sketches). Hit the Verify button to compile the sketch.
Now, navigate to the build.path folder. You should see a bunch of files including one with a .hex
extension. This is the file that needs to be selected and sent via the Electric Imp bootloader.
Resources and Going Further
The Tomatoless Boots project is a work in progress. If you found this tutorial helpful, or if you know Squirrel and would like to help, we would love it! Please let us know. There is also a place over on Github to file issues and help make improvements. A few features that would make Tomatoless Boots even better:
Create a send again button: As you develop a project it's common to send the same sketch over and over again with small tweaks so it would be really handy to avoid having to navigate to the same HEX file location. If the previous HEX file location can be remembered it should be relatively easy to create a button that allows a user to send the file that resides in the same spot. For example the contents of
Blink.cpp.hex
may change, but I'll want to send it multiple times as I work out bugs and features. It would be nice to just hit a 'Send Again' button.Pull from and poll a dropbox folder: If we can direct the Imp to monitor a page or folder location out on the Internet it would remove the need to even select the HEX file. I love dropbox, and it's possible to have Arduino export directly to a given folder (see previous section). Why not have Arduino compile to a shared dropbox folder, and when the Imp detects a status change (aka /delta), automatically bootload that HEX file to the target Arduino?
For more wireless goodness, check out these other SparkFun tutorials:
- Wimp Weather Station combines the bootloader with an active wireless weather station
- Bluetooth Basics
- BlueSMiRF Hookup Guide
- RN-52 Audio Bluetooth Hookup Guide
- BC127 Audio Bluetooth Hookup Guide
- MetaWatch Teardown and Hookup
- WiFly Shield Hookup Guide
- Hacking the MindWave Mobile
- Exploring XBees and XCTU