Programming Arduino Wirelessly

 

The Arduino system offers an easy and open-source method for programming microcontrollers. Normally this means using a serial cable or USB cable attached directly to the microcontroller project. But what if your project is floating in a weather balloon, glued to the bottom of a swimming pool or baked into a loaf of bread? It would be great to upload code changes wirelessly, and even greater if you could do it from several kilometers away.

The following example demonstrates how to build a complete wireless solution for uploading code to a remote Arduino microcontroller using a couple of XBee radios, and a handy function for accomplishing wireless resets.

   

Practical Example

Minimum parts needed: (see Tom Igoe's parts list for additional details)

Step 1:

Using a serial connection, program the two XBee radios to talk to each other at 19,200 baud. You can use a program like HyperTerm or ZTerm. On Mac OS X you can use the screen program in a terminal window. (The command would be something like: screen /dev/tty.Keyserial1 9600).

This example uses the default PAN ID of 3332, but you should choose a different one so that other XBee radios in the area do not interfere with your communications. For the first XBee, use the +++ sequence to go into command mode. You should receive an OK message back. Then issue this command:

ATID3332,DH0,DL1,MY0,BD4,WR,CN

You have now set the ID to 3332 (remember that this should be changed to something else in your actual command), the destination to 01 (that 's the address of your other XBee), the local address to 0 and your baud rate register to 4, which corresponds to 19,200 baud. WR writes the configuration to the firmware, so that the settings are preserved in firmware. From now on you'll be talking to the XBee at 19,200 baud. [If at some point you want to go back to 9600 baud, the command ATBD3,WR,CN will do the trick.]

Connect your second XBee and again use the +++ sequence to go into command mode. Then issue this command:

ATID3332,DH0,DL0,MY1,BD4,WR,CN

The only difference here is that for the second XBee, you set the destination address to 0 and the local address to 1. The two XBees are now configured to talk to each other.

 
Step 2:

Set up the breadboard with a 3.3 Volt regulator for powering the XBee radio. The 3.3V regulator used in this example is arranged (from left to right) Ground-Output-Input, which is different from the 5 Volt one. Make sure that you wire it correctly so that you don't fry the regulator or anything else on your board. The XBee module is powered with 3.3 Volts and connected to the RX and TX pins 0 and 1 of the Arduino. An LED is connected to pin 13, and the base of a transistor is connected to pin 12. The transistor's collector is connected to the reset pin and the emitter is connected to ground

TOP VIEW: XBee running on 3.3 Volt regulated Arduino breadboard with transistor controlling Arduino reset pin.

 

SCHEMATIC VIEW: Programming Arduino Wirelessly. Click to enlarge.

 

Step 3:

Load the following example code on the Arduino microcontroller, initially using a wired serial or USB connection. The easy way to do this is to put the Arduino microcontroller into one of the regular Arduino boards and upload the code normally.

/* Programming Arduino Wirelessly
 * ------------
 * This program waits for a *reset serial message from a remote computer,
 * then resets the Arduino chip after a delay to allow the microcontroller to
 * accept an upload of new code from a remote device.
 * Robert Faludi
 * rob@faludi.com
 */
int ledPin = 13; // LED connected to digital pin
 						  int transistorPin = 12;
void setup()  {
   pinMode(ledPin, OUTPUT); // sets the digital pin as output
   pinMode(transistorPin, OUTPUT);
 blinkLED(ledPin, 2, 500); // startup blink
   delay(1000);
   Serial.begin(19200); // start serial at 19200 baud, same as programmer speed
   }
void loop()  {
   blinkLED(ledPin, 1, 250);
 if ( Serial.available() > 0) { // if there are bytes waiting on the serial port
   char inByte = Serial.read(); // read a byte
   if (inByte == '*') { // if that byte is the desired character
   int len = 5; // expected string is 6 bytes long
   char inString[len]; // declare string variable
   for (int i = 0; i < len; i++) {
   inString[i] = Serial.read();
 }
   if ( strstr(inString, "reset") != NULL ) // check to see if the respose is "reset"
     resetChip(5000); // reset the chip after waiting for the specified # of milliseconds
   }
  }
}
 					  
void resetChip(int delayTime) {
   /* if the project does not typically receive data, and accidental chip resets are tolerable,
   * this is a simple method that should work just fine. Otherwise it is recommended that the 
   * reset request string be part of a call-response sequence, be transmitted with a
   * reserved byte or byte string, or be transmitted in some way out of band, so that it is not 
   * accidentally received.
   */
   Serial.print("\nArduino will reset in ");
   Serial.print(delayTime/1000, DEC);
   Serial.print(" seconds...\n\r");
   blinkLED(ledPin, delayTime/100, 100); // wait for the specified amount of time, doing nothing
   Serial.print("\nResetting NOW.\n\r");
   digitalWrite(transistorPin, HIGH); // switch on a transistor that pulls the chip's reset pin to ground
}
 					  
void blinkLED(int targetPin, int numBlinks, int blinkRate) {
   // this function blinks the an LED light as many times as requested
   for (int i=0; i<numBlinks; i++) {
    digitalWrite(targetPin, HIGH); // sets the LED on
    delay(blinkRate); // waits for a second
    digitalWrite(targetPin, LOW); // sets the LED off
    delay(blinkRate);
   }
}

 

Once the code has been loaded, replace the Arduino microcontroller into the breadboard setup. You are now ready to upload code wirelessly!

 

 
Step 4:

Attach one XBee to your computer so that you can communicate with it from a serial terminal program, and also from the Arduino program. As mentioned above, my example circuit for XBee firmware uploads works great for this. The other remote XBee will be mounted on your Arduino breadboard, as shown in Step 2.


FLOW DIAGRAM: Programming Arduino wirelessly using XBee radios.

 

When you are ready to upload a new code to the microcontroller:

1. Have your Arduino program running. Change the code slightly. For example you could alter the first line in the loop to be blinkLED(ledPin, 1, 1000); for a slower blinking light. Leave the Arduino program running. You'll need to return to it quickly in a moment.

2. Open a serial connection to the attached XBee at 19,200 baud. You can use a program like HyperTerm or ZTerm. On Mac OS X you can use the screen program in a terminal window. (The command would be something like: screen /dev/tty.Keyserial1 19200).

3. Type the following quickly into the terminal window. It may work best to copy to the clipboard and paste it all at once: *reset

4. You should receive a reply, "Arduino will reset in 5 seconds". Disconnect immediately from the terminal program to free the serial port, change to the Arduino program, and click on the button for Upload to I/O Board. The timing will probably take a little practice at first.

5. When you've got the timing right, your code will begin to upload wirelessly to the remote Arduino, and you will officially be living in a brave new world.

 
  Step 5:

Go crazy putting your PAW enabled Arduino systems into impossible places, knowing that you can still fix bugs, make improvements and try out new ideas. Make sure that your new code always includes the function which monitors for the *reset command!

Extend the above example to multiple Arduino nodes. See how close you can get to the theoretical limit of 65,536 different devices.

Try adding a Lantronix XPort or WiPort to extend your programming connection over the Internet.

Try using Bluetooth in place of the XBees. While this will probably cost more and be somewhat less flexible, it could be a useful solution is your project already uses Bluetooth, has fewer than eight nodes, or if you don't want to connect anything to your laptop externally.

If you are in an adventurous mood, open up your project by allowing others to change the code on your microcontroller.

 
 
This page created by Rob Faludi