Feather is the new development board from Adafruit, and like it's namesake it is thin, light, and lets you fly! We designed Feather to be a new standard for portable microcontroller cores.

This is the Adafruit Feather 32u4 Bluefruit - our take on an 'all-in-one' Arduino-compatible + Bluetooth Low Energy with built in USB and battery charging. Its an Adafruit Feather 32u4 with a BTLE module, ready to rock! We have other boards in the Feather family, check'em out here

Bluetooth Low Energy is the hottest new low-power, 2.4GHz spectrum wireless protocol. In particular, its the only wireless protocol that you can use with iOS without needing special certification and it's supported by all modern smart phones. This makes it excellent for use in portable projects that will make use of an iOS or Android phone or tablet. It also is supported in Mac OS X and Windows 8+

At the Feather 32u4's heart is at ATmega32u4 clocked at 8 MHz and at 3.3V logic, a chip setup we've had tons of experience with as it's the same as the Flora. This chip has 32K of flash and 2K of RAM, with built in USB so not only does it have a USB-to-Serial program & debug capability built in with no need for an FTDI-like chip, it can also act like a mouse, keyboard, USB MIDI device, etc.

To make it easy to use for portable projects, we added a connector for any of our 3.7V Lithium polymer batteries and built in battery charging. You don't need a battery, it will run just fine straight from the micro USB connector. But, if you do have a battery, you can take it on the go, then plug in the USB to recharge. The Feather will automatically switch over to USB power when its available. We also tied the battery thru a divider to an analog pin, so you can measure and monitor the battery voltage to detect when you need a recharge.

Here's some handy specs! Like all Feather 32u4's you get:

  • Measures 2.0" x 0.9" x 0.28" (51mm x 23mm x 8mm) without headers soldered in
  • Light as a (large?) feather - 5.7 grams
  • ATmega32u4 @ 8MHz with 3.3V logic/power
  • 3.3V regulator with 500mA peak current output
  • USB native support, comes with USB bootloader and serial port debugging
  • You also get tons of pins - 20 GPIO pins
  • Hardware Serial, hardware I2C, hardware SPI support
  • 7 x PWM pins
  • 10 x analog inputs
  • Built in 100mA lipoly charger with charging status indicator LED
  • Pin #13 red LED for general purpose blinking
  • Power/enable pin
  • 4 mounting holes
  • Reset button

The Feather 32u4 Bluefruit LE uses the extra space left over to add our excellent Bluefruit BTLE module + two status indicator LEDs

The Power of Bluefruit LE

The Bluefruit LE module is an nRF51822 chipset from Nordic, programmed with multi-function code that can do quite a lot! For most people, they'll be very happy to use the standard Nordic UART RX/TX connection profile. In this profile, the Bluefruit acts as a data pipe, that can 'transparently' transmit back and forth from your iOS or Android device. You can use our iOS App or Android App, or write your own to communicate with the UART service.

The board is capable of much more than just sending strings over the air!  Thanks to an easy to learn AT command set, you have full control over how the device behaves, including the ability to define and manipulate your own GATT Services and Characteristics, or change the way that the device advertises itself for other Bluetooth Low Energy devices to see. You can also use the AT commands  to query the die temperature, check the battery voltage, and more, check the connection RSSI or MAC address, and tons more. Really, way too long to list here!

Use the Bluefruit App to get your project started

Using our Bluefruit iOS App or Android App, you can quickly get your project prototyped by using your iOS or Android phone/tablet as a controller. We have a color picker, quaternion/accelerometer/gyro/magnetometer or location (GPS), and an 8-button control game pad. This data can be read over BLE and piped into the ATmega32u4 chip for processing & control

You can do a lot more too!

Comes fully assembled and tested, with a USB bootloader that lets you quickly use it with the Arduino IDE. We also toss in some header so you can solder it in and plug into a solderless breadboard. Lipoly battery, MicroSD card and USB cable not included (but we do have lots of options in the shop if you'd like!)


The Feather 32u4 Bluefruit LE is chock-full of microcontroller goodness. There's also a lot of pins and ports. We'll take you a tour of them now!

The DFU pin is accidentally labeled GND on the bottom, sorry about that! it should be labeled DFU, dont use it as a GND

Power Pins

  • GND - this is the common ground for all power and logic
  • BAT - this is the positive voltage to/from the JST jack for the optional Lipoly battery
  • USB - this is the positive voltage to/from the micro USB jack if connected
  • EN - this is the 3.3V regulator's enable pin. It's pulled up, so connect to ground to disable the 3.3V regulator
  • 3V - this is the output from the 3.3V regulator, it can supply 500mA peak

Logic pins

This is the general purpose I/O pin set for the microcontroller. All logic is 3.3V

  • #0 / RX - GPIO #0, also receive (input) pin for Serial1 and Interrupt #2
  • #1 / TX - GPIO #1, also transmit (output) pin for Serial1 and Interrupt #3
  • #2 / SDA - GPIO #2, also the I2C (Wire) data pin. There's no pull up on this pin by default so when using with I2C, you may need a 2.2K-10K pullup. Also Interrupt #1
  • #3 / SCL - GPIO #3, also the I2C (Wire) clock pin. There's no pull up on this pin by default so when using with I2C, you may need a 2.2K-10K pullup. Can also do PWM output and act as Interrupt #0.
  • #5 - GPIO #5, can also do PWM output
  • #6 - GPIO #6, can also do PWM output and analog input A7
  • #9 - GPIO #9, also analog input A9 and can do PWM output. This analog input is connected to a voltage divider for the lipoly battery so be aware that this pin naturally 'sits' at around 2VDC due to the resistor divider
  • #10 - GPIO #10, also analog input A10 and can do PWM output.
  • #11 - GPIO #11, can do PWM output.
  • #12 - GPIO #12, also analog input A11
  • #13 - GPIO #13, can do PWM output and is connected to the red LED next to the USB jack
  • A0 thru A5 - These are each analog input as well as digital I/O pins.
  • SCK/MOSI/MISO - These are the hardware SPI pins, used by the Bluefruit LE module too! You can use them as everyday GPIO pins if you don't activate the Bluefruit and keep the BLE CS pin high. However, we really recommend keeping them free as they should be kept available for the Bluefruit. If they are used, make sure its with a device that will kindly share the SPI bus! Also used to reprogram the chip with an AVR programmer if you need.

Bluefruit LE Module + Indicator LEDs

Since not all pins can be brought out to breakouts, due to the small size of the Feather, we use these to control the BLE module

  • #8 - used as the Bluefruit CS (chip select) pin
  • #7 - used as the Bluefruit IRQ (interrupt request) pin.
  • #4 - used as the Bluefruit Reset pin

Since these are not brought out there should be no risk of using them by accident!

Other Pins!

Top Side

  • RST - this is the Reset pin, tie to ground to manually reset the AVR, as well as launch the bootloader manually
  • ARef - the analog reference pin. Normally the reference voltage is the same as the chip logic voltage (3.3V) but if you need an alternative analog reference, connect it to this pin and select the external AREF in your firmware. Can't go higher than 3.3V!
  • DFU - this is the force-DFU (device firmware upgrade) pin for over-the-air updates to the Bluefruit module. You probably don't need to use this but its available if you need to upgrade!  Check out the DFU Bluefruit Upgrades page for how to use it. Otherwise, keep it disconnected.

Bottom Side

On the back we also have SWDIO/SWCLK/RESET pins, these are used for programming the Bluefruit LE module itself.

SWD Debug Input

You normally should not connect to the SWDIO and SWCLK pins unless you want to wipe out the Bluefruit LE module firmware for some reason, such as flashing an entirely custom firmware image written by yourself, though this is entirely at your own risk since it will wipe the Bluefruit firmware! Flashing firmware or using the SWD interface will require something like a Segger J-Link EDU Mini to communicate via the debug controller inside the nRF51822.

Factory Reset

The Reset pad (not to be confused with the 0.1" circular RST pin!) is the factory reset pin, which is also rarely used, but  you can use it to set the module back to the factory default settings if it gets really messed up. Connect the 'Reset' pin to GND when you boot the device up to force a factory reset in HW (via the bootloader).


We ship Feathers fully tested but without headers attached - this gives you the most flexibility on choosing how to use and configure your Feather

Header Options!

Before you go gung-ho on soldering, there's a few options to consider!

The first option is soldering in plain male headers, this lets you plug in the Feather into a solderless breadboard

Another option is to go with socket female headers. This won't let you plug the Feather into a breadboard but it will let you attach featherwings very easily

We also  have 'slim' versions of the female headers, that are a little shorter and give a more compact shape

Finally, there's the "Stacking Header" option. This one is sort of the best-of-both-worlds. You get the ability to plug into a solderless breadboard and plug a featherwing on top. But its a little bulky

Soldering in Plain Headers

Prepare the header strip:

Cut the strip to length if necessary. It will be easier to solder if you insert it into a breadboard - long pins down

Add the breakout board:

Place the breakout board over the pins so that the short pins poke through the breakout pads

And Solder!

Be sure to solder all pins for reliable electrical contact.

(For tips on soldering, be sure to check out our Guide to Excellent Soldering).

Solder the other strip as well.

You're done! Check your solder joints visually and continue onto the next steps

Soldering on Female Header

Tape In Place

For sockets you'll want to tape them in place so when you flip over the board they don't fall out

Flip & Tack Solder

After flipping over, solder one or two points on each strip, to 'tack' the header in place

And Solder!

Be sure to solder all pins for reliable electrical contact.

(For tips on soldering, be sure to check out our Guide to Excellent Soldering).

You're done! Check your solder joints visually and continue onto the next steps

Power Management

Battery + USB Power

We wanted to make the Feather easy to power both when connected to a computer as well as via battery. There's two ways to power a Feather. You can connect with a MicroUSB cable (just plug into the jack) and the Feather will regulate the 5V USB down to 3.3V. You can also connect a 4.2/3.7V Lithium Polymer (Lipo/Lipoly) or Lithium Ion (LiIon) battery to the JST jack. This will let the Feather run on a rechargable battery. When the USB power is powered, it will automatically switch over to USB for power, as well as start charging the battery (if attached) at 100mA. This happens 'hotswap' style so you can always keep the Lipoly connected as a 'backup' power that will only get used when USB power is lost.

The JST connector polarity is matched to Adafruit LiPoly batteries. Using wrong polarity batteries can destroy your Feather

The above shows the Micro USB jack (left), Lipoly JST jack (top left), as well as the 3.3V regulator and changeover diode (just to the right of the JST jack) and the Lipoly charging circuitry (to the right of the Reset button). There's also a CHG LED, which will light up while the battery is charging. This LED might also flicker if the battery is not connected.

The charge LED is automatically driven by the Lipoly charger circuit. It will try to detect a battery and is expecting one to be attached. If there isn't one it may flicker once in a while when you use power because it's trying to charge a (non-existant) battery. It's not harmful, and its totally normal!

Power supplies

You have a lot of power supply options here! We bring out the BAT pin, which is tied to the lipoly JST connector, as well as USB which is the +5V from USB if connected. We also have the 3V pin which has the output from the 3.3V regulator. We use a 500mA peak SPX3819. While you can get 500mA from it, you can't do it continuously from 5V as it will overheat the regulator. It's fine for, say, powering an ESP8266 WiFi chip or XBee radio though, since the current draw is 'spiky' & sporadic.

Measuring Battery

If you're running off of a battery, chances are you wanna know what the voltage is at! That way you can tell when the battery needs recharging. Lipoly batteries are 'maxed out' at 4.2V and stick around 3.7V for much of the battery life, then slowly sink down to 3.2V or so before the protection circuitry cuts it off. By measuring the voltage you can quickly tell when you're heading below 3.7V

To make this easy we stuck a double-100K resistor divider on the BAT pin, and connected it to D9 (a.k.a analog #9 A9). You can read this pin's voltage, then double it, to get the battery voltage.

Download: file
#define VBATPIN A9
float measuredvbat = analogRead(VBATPIN);
measuredvbat *= 2;    // we divided by 2, so multiply back
measuredvbat *= 3.3;  // Multiply by 3.3V, our reference voltage
measuredvbat /= 1024; // convert to voltage
Serial.print("VBat: " ); Serial.println(measuredvbat);

This voltage will 'float' at 4.2V when no battery is plugged in, due to the lipoly charger output, so its not a good way to detect if a battery is plugged in or not (there is no simple way to detect if a battery is plugged in)

ENable pin

If you'd like to turn off the 3.3V regulator, you can do that with the EN(able) pin. Simply tie this pin to Ground and it will disable the 3V regulator. The BAT and USB pins will still be powered

Alternative Power Options

The two primary ways for powering a feather are a 3.7/4.2V LiPo battery plugged into the JST port or a USB power cable.

If you need other ways to power the Feather, here's what we recommend:

Here's what you cannot do:

  • Do not use alkaline or NiMH batteries and connect to the battery port - this will destroy the LiPoly charger and there's no way to disable the charger
  • Do not use 7.4V RC batteries on the battery port - this will destroy the board

The Feather is not designed for external power supplies - this is a design decision to make the board compact and low cost. It is not recommended, but technically possible:

  • Connect an external 3.3V power supply to the 3V and GND pins. Not recommended, this may cause unexpected behavior and the EN pin will no longer. Also this doesn't provide power on BAT or USB and some Feathers/Wings use those pins for high current usages. You may end up damaging your Feather.
  • Connect an external 5V power supply to the USB and GND pins. Not recommended, this may cause unexpected behavior when plugging in the USB port because you will be back-powering the USB port, which could confuse or damage your computer.

Arduino IDE Setup

The first thing you will need to do is to download the latest release of the Arduino IDE. You will need to be using version 1.8 or higher for this guide

After you have downloaded and installed the latest version of Arduino IDE, you will need to start the IDE and navigate to the Preferences menu. You can access it from the File menu in Windows or Linux, or the Arduino menu on OS X.

A dialog will pop up just like the one shown below.

We will be adding a URL to the new Additional Boards Manager URLs option. The list of URLs is comma separated, and you will only have to add each URL once. New Adafruit boards and updates to existing boards will automatically be picked up by the Board Manager each time it is opened. The URLs point to index files that the Board Manager uses to build the list of available & installed boards.

To find the most up to date list of URLs you can add, you can visit the list of third party board URLs on the Arduino IDE wiki. We will only need to add one URL to the IDE in this example, but you can add multiple URLS by separating them with commas. Copy and paste the link below into the Additional Boards Manager URLs option in the Arduino IDE preferences.


Here's a short description of each of the Adafruit supplied packages that will be available in the Board Manager when you add the URL:

  • Adafruit AVR Boards - Includes support for Flora, Gemma, Feather 32u4, Trinket, & Trinket Pro.
  • Adafruit SAMD Boards - Includes support for Feather M0 and M4, Metro M0 and M4, ItsyBitsy M0 and M4, Circuit Playground Express, Gemma M0 and Trinket M0
  • Arduino Leonardo & Micro MIDI-USB - This adds MIDI over USB support for the Flora, Feather 32u4, Micro and Leonardo using the arcore project.

If you have multiple boards you want to support, say ESP8266 and Adafruit, have both URLs in the text box separated by a comma (,)

Once done click OK to save the new preference settings. Next we will look at installing boards with the Board Manager.

Now continue to the next step to actually install the board support package!

Using with Arduino IDE

Since the Feather 32u4 uses an ATmega32u4 chip running at 8 MHz, you can pretty easily get it working with the Arduino IDE. Many libraries (including the popular ones like NeoPixels and display) work great with the '32u4 and 8 MHz clock speed.

Now that you have added the appropriate URLs to the Arduino IDE preferences, you can open the Boards Manager by navigating to the Tools->Board menu.

Once the Board Manager opens, click on the category drop down menu on the top left hand side of the window and select Contributed. You will then be able to select and install the boards supplied by the URLs added to the prefrences. In the example below, we are installing support for Adafruit AVR Boards, but the same applies to all boards installed with the Board Manager.

Next, quit and reopen the Arduino IDE to ensure that all of the boards are properly installed. You should now be able to select and upload to the new boards listed in the Tools->Board menu.

Install Drivers (Windows 7 Only)

When you plug in the Feather, you'll need to possibly install a driver

Windows 10 folks can skip this, the drivers now come built into Windows 10!

Click below to download our Driver Installer

Download and run the installer

Run the installer! Since we bundle the SiLabs and FTDI drivers as well, you'll need to click through the license

Select which drivers you want to install:

Click Install to do the installin'


Now you can upload your first blink sketch!

Plug in the Feather 32u4 and wait for it to be recognized by the OS (just takes a few seconds). It will create a serial/COM port, you can now select it from the dropdown, it'll even be 'indicated' as Feather 32u4!

Now load up the Blink example

Download: file
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
  pinMode(13, OUTPUT);

// the loop function runs over and over again forever
void loop() {
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second

And click upload! That's it, you will be able to see the LED blink rate change as you adapt the delay() calls.

Manually bootloading

If you ever get in a 'weird' spot with the bootloader, or you have uploaded code that crashes and doesn't auto-reboot into the bootloader, double-click the RST button to get back into the bootloader. The red LED will pulse, so you know that its in bootloader mode. Do the reset button double-press right as the Arduino IDE says its attempting to upload the sketch, when you see the Yellow Arrow lit and the Uploading... text in the status bar.

Don't click the reset button before uploading, unlike other bootloaders you want this one to run at the time Arduino is trying to upload

Ubuntu & Linux Issue Fix

If you're on Linux, and are seeing multi-second delays connecting to the serial console, or are seeing "AT" and other gibberish when you connect, follow the steps on this page.

Installing BLE Library

Install the Adafruit nRF51 BLE Library

In order to try out our demos, you'll need to download the Adafruit BLE library for the nRF51 based modules such as this one (a.k.a. Adafruit_BluefruitLE_nRF51)

You can check out the code here at github, but its likely easier to just download via the Arduino library manager.

Open up the Arduino library manager:

Search for the Adafruit BluefruitLE nRF51 library and install it

We also have a great tutorial on Arduino library installation at:

Check that you see the library folder with examples:

Run first example

Lets begin with the beginner project, which we can use to do basic tests. To open the ATCommand sketch, click on the File > Examples > Adafruit_BluefruitLE_nRF51 folder in the Arduino IDE and select atcommand:

This will open up a new instance of the example in the IDE, as shown below:

Don't upload the sketch yet! You will have to begin by changing the configuration.

Go to the second tab labeled BluefruitConfig.h and find these lines

Download: file
// ----------------------------------------------------------------------------------------------
// The following macros declare the pins to use for HW and SW SPI communication.
// SCK, MISO and MOSI should be connected to the HW SPI pins on the Uno when
// using HW SPI.  This should be used with nRF51822 based Bluefruit LE modules
// that use SPI (Bluefruit LE SPI Friend).
// ----------------------------------------------------------------------------------------------
#define BLUEFRUIT_SPI_CS               8
#define BLUEFRUIT_SPI_IRQ              7
#define BLUEFRUIT_SPI_RST              6    // Optional but recommended, set to -1 if unused

And change the last line to:

Download: file
#define BLUEFRUIT_SPI_RST              4   // Optional but recommended, set to -1 if unused

(The Bluefruit Feather has the reset on digital #4 not #6)

Now go back to the main tab atcommand and look for this line of code

Download: file
/* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */

Make sure that the second line is uncommented (it should be)

OK now you can upload to the Bluefruit Feather!
If you're using Ubuntu 15.04 or other Linux distributions and run into errors attempting to upload a program to the board, scroll up to the Ubuntu and Linux issue fix in the previous section

Uploading to the Feather Bluefruit LE

It's pretty easy to upload, first up make sure you have Adafruit Feather 32u4 selected on the boards dropdown as above. Also, in the Ports menu, look for the port labeled as such:

Now click the upload button on the Arduino IDE (or File Menu -> Upload)

If all is good you will see Done Uploading in the status bar

Uploading to a brand new board/Upload failures

If you are uploading for the first time to a new board, or if upload fails, pres the RESET mini button on the Feather 32u4 Bluefruit when you see the Yellow Arrow lit and the Uploading... text in the status bar. When you see the red LED pulsing on and off, you know the bootloader is running.

Don't click the reset button before uploading, unlike other bootloaders you want this one to run at the time Arduino is trying to upload

Run the sketch

OK check again that the correct port is selected

Then open up the Serial console. You will see the following:

This sketch starts by doing a factory reset, then querying the BLE radio for details. These details will be useful if you are debugging the radio. If you see the information as above, you're working! (Note that the dates and version numbers may vary)

AT command testing

Now you can try out some AT commands - check the rest of the learn guide for a full list. We'll just start with AT+HWGETDIETEMP which will return the approximate ambient temperature of the BLE chipset

OK now you know how to upload/test/communicate with your Feather 32u4 Bluefruit. Next up we have a bunch of tutorials who can follow for checking out the bluetooth le radio and apps.

For all the following examples, we share the same code between various modules so don't forget to make sure you have the RESET pin set to 4 in BluefruitConfig.h for each sketch before uploading, and that Hardware SPI mode is selected by checking for

Download: file
      /* ...hardware SPI, using SCK/MOSI/MISO hardware SPI pins and then user selected CS/IRQ/RST */

AT Commands

The Bluefruit LE modules use a Hayes AT-style command set to configure the device.

The advantage of an AT style command set is that it's easy to use in machine to machine communication, while still being somewhat user friendly for humans.

Test Command Mode '=?'

'Test' mode is used to check whether or not the specified command exists on the system or not.  

Certain firmware versions or configurations may or may not include a specific command, and you can determine if the command is present by taking the command name and appending '=?' to it, as shown below

Download: file

If the command is present, the device will reply with 'OK'.  If the command is not present, the device will reply with 'ERROR'.

Download: file

Write Command Mode '=xxx'

'Write' mode is used to assign specific value(s) to the command, such as changing the radio's transmit power level using the command we used above.

To write a value to the command, simple append an '=' sign to the command followed by any paramater(s) you wish to write (other than a lone '?' character which will be interpretted as tet mode):

Download: file

If the write was successful, you will generally get an 'OK' response on a new line, as shown below:

Download: file

If there was a problem with the command (such as an invalid parameter) you will get an 'ERROR' response on a new line, as shown below:

Download: file

Note: This particular error was generated because '3' is not a valid value for the AT+BLEPOWERLEVEL command.  Entering '-4', '0' or '4' would succeed since these are all valid values for this command.

Execute Mode

'Execute' mode will cause the specific command to 'run', if possible, and will be used when the command name is entered with no additional parameters.

Download: file

You might use execute mode to perform a factory reset, for example, by executing the AT+FACTORYRESET command as follows:

Download: file

NOTE: Many commands that are means to be read will perform the same action whether they are sent to the command parser in 'execute' or 'read' mode. For example, the following commands will produce identical results:

Download: file

If the command doesn't support execute mode, the response will normally be 'ERROR' on a new line.

Read Command Mode '?'

'Read' mode is used to read the current value of a command. 

Not every command supports read mode, but you generally use this to retrieve information like the current transmit power level for the radio by appending a '?' to the command, as shown below:

Download: file

If the command doesn't support read mode or if there was a problem with the request, you will normally get an 'ERROR' response.

If the command read was successful, you will normally get the read results followed by 'OK' on a new line, as shown below:

Download: file

Note: For simple commands, 'Read' mode and 'Execute' mode behave identically.

Command Examples

The following code snippets can be used when operating in Command Mode to perform specific tasks.

Heart Rate Monitor Service

The command list below will add a Heart Rate service to the BLEFriend's attribute table, with two characteristics:

Download: file
# Perform a factory reset to make sure we get a clean start
# Add the Heart Rate service entry

# Add the Heart Rate Measurement characteristic

# Add the Body Sensor Location characteristic

# Create a custom advertising packet that includes the Heart Rate service UUID

# Reset the device to start advertising with the custom payload

# Update the value of the heart rate measurement (set it to 0x004A)

Python Script

The following code performs the same function, but has been placed inside a Python wrapper using PySerial to show how you can script actions for the AT parser.

Download: file
import io
import sys
import serial
import random
from time import sleep

filename = "hrm.py"
ser = None
serio = None
verbose = True  # Set this to True to see all of the incoming serial data

def usage():
    """Displays information on the command-line parameters for this script"""
    print "Usage: " + filename + " <serialPort>\n"
    print "For example:\n"
    print "  Windows : " + filename + " COM14"
    print "  OS X    : " + filename + " /dev/tty.usbserial-DN009WNO"
    print "  Linux   : " + filename + " /dev/ttyACM0"

def checkargs():
    """Validates the command-line arguments for this script"""
    if len(sys.argv) < 2:
        print "ERROR: Missing serialPort"
    if len(sys.argv) > 2:
        print "ERROR: Too many arguments (expected 1)."

def errorhandler(err, exitonerror=True):
    """Display an error message and exit gracefully on "ERROR\r\n" responses"""
    print "ERROR: " + err.message
    if exitonerror:

def atcommand(command, delayms=0):
    """Executes the supplied AT command and waits for a valid response"""
    serio.write(unicode(command + "\n"))
    if delayms:
    rx = None
    while rx != "OK\r\n" and rx != "ERROR\r\n":
        rx = serio.readline(2000)
        if verbose:
            print unicode(rx.rstrip("\r\n"))
    # Check the return value
    if rx == "ERROR\r\n":
        raise ValueError("AT Parser reported an error on '" + command.rstrip() + "'")

if __name__ == '__main__':
    # Make sure we received a single argument (comPort)

    # This will automatically open the serial port (no need for ser.open)
    ser = serial.Serial(port=sys.argv[1], baudrate=9600, rtscts=True)
    serio = io.TextIOWrapper(io.BufferedRWPair(ser, ser, 1),

    # Add the HRM service and characteristic definitions
        atcommand("AT+FACTORYRESET", 1000)  # Wait 1s for this to complete
        atcommand("AT+GATTADDCHAR=UUID=0x2A37, PROPERTIES=0x10, MIN_LEN=2, MAX_LEN=3, VALUE=00-40")
        atcommand("AT+GATTADDCHAR=UUID=0x2A38, PROPERTIES=0x02, MIN_LEN=1, VALUE=3")
        # Perform a system reset and wait 1s to come back online
        atcommand("ATZ", 1000)
        # Update the value every second
        while True:
            atcommand("AT+GATTCHAR=1,00-%02X" % random.randint(50, 100), 1000)
    except ValueError as err:
        # One of the commands above returned "ERROR\n"
    except KeyboardInterrupt:
        # Close gracefully on CTRL+C

The results of this script can be seen below in the 'HRM' app of Nordic's nRF Toolbox application:

Please note that nRF Toolbox will only display HRM data if the value changes, so you will need to update the Heart Rate Measurement characteristic at least once after opening the HRM app and connecting to the BLEFriend

SDEP (SPI Data Transport)

In order to facilitate switching between UART and SPI based Bluefruit LE modules, the Bluefruit LE SPI Friend and Shield uses the same AT command set at the UART modules (ATI, AT+HELP, etc.).  

These text-based AT commands are encoded as binary messages using a simple binary protocol we've named SDEP (Simple Data Exhange Protocol).

Most of the time, you never need to deal with SDEP directly, but we've documented the protocol here in case you need understand the Bluefruit LE SPI interface in depth!

SDEP Overview

SDEP was designed as a bus neutral protocol to handle binary commands and responses -- including error responses -- in a standard, easy to extend manner. 'Bus neutral' means that we can use SDEP regardless of the transport mechanism (USB HID, SPI, I2C, Wireless data over the air, etc.).

All SDEP messages have a four byte header, and in the case of the Bluefruit LE modules up to a 16 byte payloads. Larger messages are broken up into several 4+16 bytes message chunks which are rebuilt at either end of the transport bus. The 20 byte limit (4 byte header + 16 byte payload) was chosen to take into account the maximum packet size in Bluetooth Low Energy 4.0 (20 bytes per packet).

SPI Setup

While SDEP is bus neutral, in the case of the Bluefruit LE SPI Friend or Shield, an SPI transport is used with the following constraints and assumptions, largely to take into account the HW limitations of the nRF51822 system on chip:

SPI Hardware Requirements

  • The SPI clock should run <=4MHz
  • A 100us delay should be added between the moment that the CS line is asserted, and before any data is transmitted on the SPI bus
  • The CS line must remain asserted for the entire packet, rather than toggling CS every byte
  • The CS line can however be deasserted and then reasserted between individual SDEP packets (of up to 20 bytes each).
  • The SPI commands must be setup to transmit MSB (most significant bit) first (not LSB first)


The IRQ line is asserted by the Bluefruit LE SPI Friend/Shield as long as an entire SDEP packet is available in the buffer on the nRF51822, at which point you should read the packet, keeping the CS line asserted for the entire transaction (as detailed above).

The IRQ line will remain asserted as long as one or more packets are available, so the line may stay high after reading a packet, meaning that more packets are still available in the FIFO on the SPI slave side.

SDEP Packet and SPI Error Identifier

Once CS has been asserted and the mandatory 100us delay has passed, a single byte should be read from the SPI bus which will indicate the type of payload available on the nRF51822 (see Message Type Indicator below for more information on SDEP message types). Keep CS asserted after this byte has been read in case you need to continue reading the rest of the frame.

If a standard SDEP message type indicator (0x10, 0x20, 0x40 or 0x80) is encountered, keep reading as normal. There are two other indicators that should be taken into account, though, which indicate a problem on the nRF51822 SPI slave side:

  • 0xFE: Slave device not ready (wait a bit and try again)
  • 0xFF: Slave device read overflow indicator (you've read more data than is available)

This means there are six possible response bytes reading the message type indicator (the first byte read after an SDEP command is sent): 0x10, 0x20, 0x40, 0x80, which indicate a valid message type, or 0xFE, 0xFF which indicate an error condition.

Sample Transaction

The following image shows a sample SDEP response that is spread over two packets (since the response is > 20 bytes in size). Notice that the IRQ line stays asserted between the packets since more than one packet was available in the FIFO on the Bluefruit LE SPI side:

SDEP (Simple Data Exchange Protocol)

The Simple Data Exchange Protocol (SDEP) can be used to send and receive binary messages between two connected devices using any binary serial bus (USB HID, USB Bulk, SPI, I2C, Wireless, etc.), exchanging data using one of four distinct message types (Command, Response, Alert and Error messages).

The protocol is designed to be flexible and extensible, with the only requirement being that individual messages are 20 bytes or smaller, and that the first byte of every message is a one byte (U8) identifier that indicates the message type, which defines the format for the remainder of the payload.


All values larger than 8-bits are encoded in little endian format. Any deviation from this rule should be clearly documented.

Message Type Indicator

The first byte of every message is an 8-bit identifier called the Message Type Indicator. This value indicates the type of message being sent, and allows us to determine the format for the remainder of the message.

Message Type





ID (U8)





SDEP Data Transactions

Either connected device can initiate SDEP transactions, though certain transport protocols imposes restrictions on who can initiate a transfer. The master device, for example, always initiates transactions with Bluetooth Low Energy or USB, meaning that slave devices can only reply to incoming commands.

Every device that receives a Command Message must reply with a Response Message, Error Message or Alert message.

Message Types

Command Messages

Command messages (Message Type = 0x10) have the following structure:


Message Type

Command ID

Payload Length












Always '0x10'

Unique Command Identifier

[7] More data
[6-5] Reserved
[4-0] Payload length (0..16)

Optional command payload (parameters, etc.)

Command ID (bytes 1-2) and Payload Length (byte 3) are mandatory in any command message. The message payload is optional, and will be ignored if Payload Length is set to 0 bytes. When a message payload is present, it’s length can be anywhere from 1..16 bytes, to stay within the 20-byte maximum message length.

A long command (>16 bytes payload) must be divided into multiple packets. To facilitate this, the More data field (bit 7 of byte 3) is used to indicate whether additional packets are available for the same command. The SDEP receiver must continue to reads packets until it finds a packet with More data == 0, then assemble all sub-packets into one command if necessary.

The contents of the payload are user defined, and can change from one command to another.

A sample command message would be:

Download: file
10 34 12 01 FF

0: Message Type (U8)

1+2: Command ID (U16)

3: Payload Len (U8)

4: Payload (...)


0x34 0x12



  • The first byte is the Message Type (0x10), which identifies this as a command message.
  • The second and third bytes are 0x1234 (34 12 in little-endian notation), which is the unique command ID. This value will be compared against the command lookup table and redirected to an appropriate command handler function if a matching entry was found.
  • The fourth byte indicates that we have a message payload of 1 byte
  • The fifth byte is the 1 byte payload: 0xFF

Response Messages

Response messages (Message Type = 0x20) are generated in response to an incoming command, and have the following structure:


Message Type

Command ID

Payload Length












Always  '0x20'

Command ID this message is a response to

[7] More data
[6-5] Reserved
[4-0] Payload length (0..16)

Optional response payload (parameters, etc.)

By including the Command ID that this response message is related to, the recipient can more easily correlate responses and commands. This is useful in situations where multiple commands are sent, and some commands may take a longer period of time to execute than subsequent commands with a different command ID.

Response messages can only be generate in response to a command message, so the Command ID field should always be present.

A long response (>16 bytes payload) must be divided into multiple packets. Similar to long commands, the More data field (bit 7 of byte 3) is used to indicate whether additional packets are available for the same response. On responses that span more than one packet, the More data bit on the final packet will be set to 0 to indicate that this is the last packet in the sequence. The SDEP receiver must re-assemble all sub-packets in into one payload when necessary.

If more precise command/response correlation is required a custom protocol should be developed, where a unique message identifier is included in the payload of each command/response, but this is beyond the scope of this high-level protocol definition.

A sample response message would be:

Download: file
20 34 12 01 FF

0: Message Type (U8)

1+2: Command ID (U16)

3: Payload Len (U8)

4: Payload


0x34 0x12



  • The first byte is the Message Type (0x20), which identifies this as a response message.
  • The second and third bytes are 0x1234, which is the unique command ID that this response is related to.
  • The fourth byte indicates that we have a message payload of 1 byte.
  • The fifth byte is the 1 byte payload: 0xFF

Alert Messages

Alert messages (Message Type = 0x40) are sent whenever an alert condition is present on the system (low battery, etc.), and have the following structure:


Message Type

Alert ID

Payload Length








Always '0x40'

Unique ID for the Alert Condition

Payload Length (0..16)

Optional response payload

A sample alert message would be:

Download: file
40 CD AB 04 42 07 00 10

0: Message Type (U8)

1+2: Alert ID (U16)

3: Payload Length

4+5+6+7: Payload


0xCD 0xAB


0x42 0x07 0x00 0x10

  • The first byte is the Message Type (0x40), which identifies this as an alert message.
  • The second and third bytes are 0xABCD, which is the unique alert ID.
  • The fourth byte indicates that we have a message payload of 4 bytes.
  • The last four bytes are the actual payload: 0x10000742 in this case, assuming we were transmitting a 32-bit value in little-endian format.

Standard Alert IDs

Alert IDs in the range of 0x0000 to 0x00FF are reserved for standard SDEP alerts, and may not be used by custom alerts.

The following alerts have been defined as a standard part of the protocol:








System Reset

Battery Low

Battery Critical


Reserved for future use

The system is about to reset

The battery level is low

The battery level is critically low

Error Messages

Error messages (Message Type = 0x80) are returned whenever an error condition is present on the system, and have the following structure:


Message Type

Error ID







Always '0x80'

Unique ID for the error condition

Reserved for future use

Whenever an error condition is present and the system needs to be alerted (such as a failed request, an attempt to access a non-existing resource, etc.) the system can return a specific error message with an appropriate Error ID.

A sample error message would be:

Download: file
80 01 00 00

0: Message ID (U8)

1+2: Error ID (U16)

3: Reserved (U8)


0x01 0x00


Standard Error IDs

Error IDs in the range of 0x0000 to 0x00FF are reserved for standard SDEP errors, and may not be used by custom errors.

The following errors have been defined as a standard part of the protocol:







Invalid CMD ID

Invalid Payload


Reserved for future use

CMD ID wasn't found in the lookup table

The message payload was invalid

Existing Commands

At present, there are only four SDEP commands implemented in the Bluefruit SPIFRIEND32 firmware:


SDEP_CMDTYPE_INITIALIZE can be used to reset the SDEP system when a HW RST line isn't available.

The two SDEP_CMDTYPE_UART* commands send data over the BLE UART service.

SDEP_CMDTYPE_AT_WRAPPER is the command you will use most of the time, which is a wrapper that sends AT commands over the binary SDEP transport.  This isn't terribly efficient, and a binary mechanism would have taken less bytes per command, but it allows the reuse of all of the earlier AT parser commands without having to implement one wrapper for every command which would significantly increase the overall code size.

SDEP AT Wrapper Usage

To use the SDEP AT Wrapp you simply send the correct header, along with the AT command you which to send to the parser.  For example:

Download: file
  • Message Type: 0x10 (Command)
  • Command ID: 0x0A00
  • Command Payload Length: 3 bytes
  • Command Payload: 'a' + 't' + 'i'

This will cause the ATI command to be executed, which will return basic system information.

GATT Service Details

Data in Bluetooth Low Energy is organized around units called 'GATT Services' and 'GATT Characteristics'.  To expose data to another device, you must instantiate at least one service on your device.

Adafruit's Bluefruit LE Pro modules support some 'standard' services, described below (more may be added in the future).

UART Service

The UART Service is the standard means of sending and receiving data between connected devices, and simulates a familiar two-line UART interface (one line to transmit data, another to receive it).

The service is described in detail on the dedicated UART Service page.

Software Resources

To help you get your Bluefruit LE module talking to other Central devices, we've put together a number of open source tools for most of the major platforms supporting Bluetooth Low Energy.

Bluefruit LE Client Apps and Libraries

Adafruit has put together the following mobile or desktop apps and libraries to make it as easy as possible to get your Bluefruit LE module talking to your mobile device or laptop, with full source available where possible:

Bluefruit LE Connect (Android/Java)

Bluetooth Low Energy support was added to Android starting with Android 4.3 (though it was only really stable starting with 4.4), and we've already released Bluefruit LE Connect to the Play Store.

The full source code for Bluefruit LE Connect for Android is also available on Github to help you get started with your own Android apps.  You'll need a recent version of Android Studio to use this project.

Bluefruit LE Connect  (iOS/Swift)

Apple was very early to adopt Bluetooth Low Energy, and we also have an iOS version of the Bluefruit LE Connect app available in Apple's app store.

The full swift source code for Bluefruit LE Connect for iOS is also available on Github. You'll need XCode and access to Apple's developper program to use this project:

Version 2.x of the app is a complete rewrite that includes iOS, OS X GUI and OS X command-line tools in a single codebase.

Bluefruit LE Connect for OS X (Swift)

This OS X desktop application is based on the same V2.x codebase as the iOS app, and gives you access to BLE UART, basic Pin I/O and OTA DFU firmware updates from the convenience of your laptop or mac.

This is a great choice for logging sensor data locally and exporting it as a CSV, JSON or XML file for parsing in another application, and uses the native hardware on your computer so no BLE dongle is required on any recent mac.

The full source is also available on Github.

Bluefruit LE Command Line Updater for OS X (Swift)

This experimental command line tool is unsupported and provided purely as a proof of concept, but can be used to allow firmware updates for Bluefruit devices from the command line.

This utility performs automatic firmware updates similar to the way that the GUI application does, by checking the firmware version on your Bluefruit device (via the Device Information Service), and comparing this against the firmware versions available online, downloading files in the background if appropriate.

Simply install the pre-compiled tool via the DMG file and place it somewhere in the system path, or run the file locally via './bluefruit' to see the help menu:

Download: file
$ ./bluefruit
bluefruit v0.3
	bluefruit <command> [options...]

	Scan peripherals:   scan
	Automatic update:   update [--enable-beta] [--uuid <uuid>]
	Custom firmware:    dfu --hex <filename> [--init <filename>] [--uuid <uuid>]
	Show this screen:   --help
	Show version:       --version

	--uuid <uuid>    If present the peripheral with that uuid is used. If not present a list of peripherals is displayed
	--enable-beta    If not present only stable versions are used

Short syntax:
	-u = --uuid, -b = --enable-beta, -h = --hex, -i = --init, -v = --version, -? = --help

Deprecated: Bluefruit Buddy (OS X)

This native OS X application is a basic proof of concept app that allows you to connect to your Bluefruit LE module using most recent macbooks or iMacs. You can get basic information about the modules and use the UART service to send and receive data.

The full source for the application is available in the github repo at Adafruit_BluefruitLE_OSX.

ABLE (Cross Platform/Node+Electron)

ABLE (Adafruit Bluefruit LE Desktop) is a cross-platform desktop application based on Sandeep Misty's noble library and the Electron project from Github (used by Atom).

It runs on OS X, Windows 7+ and select flavours of Linux (Ubuntu tested locally).  Windows 7 support is particularly interesting since Windows 7 has no native support for Bluetooth Low Energy but the noble library talks directly to supported Bluetooth 4.0 USB dongles to emulate BLE on the system (though at this stage it's still in early BETA and drops the connection and takes more care to work with).

This app allows you to collect sensor data or perform many of the same functionality offered by the mobile Bluefruit LE Connect apps, but on the desktop.

The app is still in BETA, but full source is available in addition to the easy to use pre-compiled binaries.

Bluefruit LE Python Wrapper

As a proof of concept, we've played around a bit with getting Python working with the native Bluetooth APIs on OS X and the latest version of Bluez on certain Linux targets.

There are currently example sketches showing how to retreive BLE UART data as well as some basic details from the Device Information Service (DIS).

This isn't an actively support project and was more of an experiment, but if you have a recent Macbook or a Raspberry Pi and know Python, you might want to look at Adafruit_Python_BluefruitLE in our github account.

Debug Tools

If your sense of adventure gets the better of you, and your Bluefruit LE module goes off into the weeds, the following tools might be useful to get it back from unknown lands.

These debug tools are provided purely as a convenience for advanced users for device recovery purposes, and are not recommended unless you're OK with potentially bricking your board. Use them at your own risk.

AdaLink (Python)

This command line tool is a python-based wrapper for programming ARM MCUs using either a Segger J-Link or an STLink/V2. You can use it to reflash your Bluefruit LE module using the latest firmware from the Bluefruit LE firmware repo.

Details on how to use the tool are available in the readme.md file on the main Adafruit_Adalink repo on Github.

Completely reprogramming a Bluefruit LE module with AdaLink would require four files, and would look something like this (using a JLink):

Download: file
adalink nrf51822 --programmer jlink --wipe
  --program-hex "Adafruit_BluefruitLE_Firmware/softdevice/s110_nrf51_8.0.0_softdevice.hex" 
  --program-hex "Adafruit_BluefruitLE_Firmware/bootloader/bootloader_0002.hex"
  --program-hex "Adafruit_BluefruitLE_Firmware/0.6.7/blefriend32/blefriend32_s110_xxac_0_6_7_150917_blefriend32.hex"
  --program-hex "Adafruit_BluefruitLE_Firmware/0.6.7/blefriend32/blefriend32_s110_xxac_0_6_7_150917_blefriend32_signature.hex"

You can also use the AdaLink tool to get some basic information about your module, such as which SoftDevice is currently programmed or the IC revision (16KB SRAM or 32KB SRAM) via the --info command:

Download: file
$ adalink nrf51822 -p jlink --info
Hardware ID : QFACA10 (32KB)
Segger ID   : nRF51822_xxAC
SD Version  : S110 8.0.0
Device Addr : **:**:**:**:**:**
Device ID   : ****************

Adafruit nRF51822 Flasher (Python)

Adafruit's nRF51822 Flasher is an internal Python tool we use in production to flash boards as they go through the test procedures and off the assembly line, or just testing against different firmware releases when debugging.

It relies on AdaLink or OpenOCD beneath the surface (see above), but you can use this command line tool to flash your nRF51822 with a specific SoftDevice, Bootloader and Bluefruit firmware combination.

It currently supports using either a Segger J-Link or STLink/V2 via AdaLink, or GPIO on a Raspberry Pi if you don't have access to a traditional ARM SWD debugger.  (A pre-built version of OpenOCD for the RPi is included in the repo since building it from scratch takes a long time on the original RPi.)

We don't provide active support for this tool since it's purely an internal project, but made it public just in case it might help an adventurous customer debrick a board on their own.

Download: file
$ python flash.py --jtag=jlink --board=blefriend32 --softdevice=8.0.0 --bootloader=2 --firmware=0.6.7
jtag       	: jlink
softdevice 	: 8.0.0
bootloader 	: 2
board      	: blefriend32
firmware   	: 0.6.7
Writing Softdevice + DFU bootloader + Application to flash memory
adalink -v nrf51822 --programmer jlink --wipe --program-hex "Adafruit_BluefruitLE_Firmware/softdevice/s110_nrf51_8.0.0_softdevice.hex" --program-hex "Adafruit_BluefruitLE_Firmware/bootloader/bootloader_0002.hex" --program-hex "Adafruit_BluefruitLE_Firmware/0.6.7/blefriend32/blefriend32_s110_xxac_0_6_7_150917_blefriend32.hex" --program-hex "Adafruit_BluefruitLE_Firmware/0.6.7/blefriend32/blefriend32_s110_xxac_0_6_7_150917_blefriend32_signature.hex"


Can I talk to Classic Bluetooth devices with a Bluefruit LE modules?

No.  Bluetooth Low Energy and 'Classic' Bluetooth are both part of the same Bluetooth Core Specification -- defined and maintained by the Bluetooth SIG -- but they are completely different protocols operating with different physical constraints and requirements.  The two protocols can't talk to each other directly.

Can my Bluefruit LE module connect to other Bluefruit LE peripherals

No, the Bluefruit LE firmware from Adafruit is currently peripheral only, and doesn't run in Central mode, which would cause the module to behave similar to your mobile phone or BLE enabled laptop.

If you required Central support, you should look at the newer nRF52832 based products like the Adafruit Feather nRF52 Bluefruit LE, which contains a SoftDevice which is capable of running in either Central or Peripheral mode. The nRF518322 based products (such as the one used in this learning guide) are not capable of running in Central mode because it isn't supported by the SoftDevice they use, and it isn't possible to update the SoftDevice safely without special hardware.

I just got my Bluefruit board and  when I run a sketch it hangs forever on the 'Connecting...' stage!

There are several possible explanations here, but the first thing to try is to:

  1. Disconnect and close the Bluefruit LE Connect app if it's open
  2. Disable BLE on your mobile device
  3. Restart your Bluefruit sketch and HW
  4. Turn BLE back on again (on the mobile device)
  5. Open the Bluefruit LE Connect mobile app again and try to connect again

If problems persist, try performing a Factory Reset of your device (see the appropriate learning guide for details on how to do this since it varies from one board to another).

Why are none of my changes persisting when I reset with the sample sketches?

In order to ensure that the Bluefruit LE modules are in a known state for the Adafruit demo sketches, most of them perform a factory reset at the start of the sketch.

This is useful to ensure that the sketch functions properly, but has the side effect of erasing any custom user data in NVM and setting everything back to factory defaults every time your board comes out of reset and the sketch runs.

To disable factory reset, open the demo sketch and find the FACTORYRESET_ENABLE flag and set this to '0', which will prevent the factory reset from happening at startup.

If you don't see the 'FACTORYRESET_ENABLE' flag in your .ino sketch file, you probably have an older version of the sketches and may need to update to the latest version via the Arduino library manager.

Do I need CTS and RTS on my UART based Bluefruit LE Module?

Using CTS and RTS isn't strictly necessary when using HW serial, but they should both be used with SW serial, or any time that a lot of data is being transmitted.

The reason behind the need for CTS and RTS is that the UART block on the nRF51822 isn't very robust, and early versions of the chip had an extremely small FIFO meaning that the UART peripheral was quickly overwhelmed.

Using CTS and RTS significantly improves the reliability of the UART connection since these two pins tell the device on the other end when they need to wait while the existing buffered data is processed.

To enable CTS and RTS support, go into the BluefruitConfig.h file in your sketch folder and simply assign an appropriate pin to the macros dedicated to those functions (they may be set to -1 if they aren't currently being used).

Enabling both of these pins should solve any data reliability issues you are having with large commands, or when transmitting a number of commands in a row.

How can I update to the latest Bluefruit LE Firmware?

The easiest way to keep your Bluefruit LE modules up to date is with our Bluefruit LE Connect app for Android or Bluefruit LE Connect for iOS.  Both of these apps include a firmware update feature that allows you to automatically download the latest firmware and flash your Bluefruit LE device in as safe and painless a manner as possible. You can also roll back to older versions of the Bluefruit LE firmware using these apps if you need to do some testing on a previous version.

Which firmware version supports 'xxx'?

We regularly release Bluefruit LE firmware images with bug fixes and new features. Each AT command in this learning guide lists the minimum firmware version required to use that command, but for a higher level overview of the changes from one firmware version to the next, consult the firmware history page.

Does my Bluefruit LE device support ANCS?

ANCS is on the roadmap for us (most likely in the 0.7.x release family), but we don't currently support it since there are some unusual edge cases when implementing it as a service.

My Bluefruit LE device is stuck in DFU mode ... what can I do?

If your device is stuck in DFU mode for some reason and the firmware was corrupted, you have several options.

First, try a factory reset by holding down the DFU button for about 10 seconds until the CONN LED starts flashing, then release the DFU button to perform a factory reset. 

If this doesn't work, you may need to reflash your firmware starting from DFU mode, which can be done in one of the following ways:

Bluefruit LE Connect (Android)

  • Place the module in DFU mode (constant LED blinky)
  • Open Bluefruit LE Connect
  • Connect to the 'DfuTarg' device
  • Once connected, you will see a screen with some basic device information. Click the '...' in the top-right corner and select Firmware Updates
  • Click the Use Custom Firmware button
  • Select the appropriate .hex and .init files (copied from the Bluefruit LE Firmware repo) ... for the BLEFRIEND32 firmware version 0.6.7, this would be:
    • Hex File: blefriend32_s110_xxac_0_6_7_150917_blefriend32.hex
    • Init File: blefriend32_s110_xxac_0_6_7_150917_blefriend32_init.dat
  • Click Start Update

Unfortunately, the iOS app doesn't yet support custom firmware updates from DFU mode yet, but we will get this into the next release.

Nordic nRF Toolbox

You can also use Nordic's nRF Toolbox application to update the firmware using the OTA bootloader.

On Android:

  • Open nRF Toolbox (using the latest version)
  • Click the DFU icon
  • Click the Select File button
  • Select Application from the radio button list, then click OK
  • Find the appropriate .hex file (ex. 'blefriend32_s110_xxac_0_6_7_150917_blefriend32.hex')
  • When asked about the 'Init packet', indicate Yes, and select the appropriate *_init.dat file (for example: 'blefriend32_s110_xxac_0_6_7_150917_blefriend32_init.dat').
  • Click the Select Device button at the bottom of the main screen and find the DfuTarg device, clicking on it
  • Click the Upload button, which should now be enabled on the home screen
  • This will begin the DFU update process which should cause the firmware to be updated or restored on your Bluefruit LE module

On iOS:

  • Create a .zip file containing the .hex file and init.dat file that you will use for the firmware update.  For example:
    • Rename 'blefriend32_s110_xxac_0_6_7_150917_blefriend32.hex' to application.hex
    • Rename 'blefriend32_s110_xxac_0_6_7_150917_blefriend32_init.dat' to application.dat
  • Upload the .zip file containing the application.hex and application.dat files to your iPhone using uTunes, as described here
  • Open the nRF Toolbox app (using the latest version)
  • Click the DFU icon
  • Click the Select File text label
  • Switch to User Files to see the .zip file you uploaded above
  • Select the .zip file (ex. blefriend32_065.zip)
  • On the main screen select Select File Type
  • Select application
  • On the main screen select SELECT DEVICE
  • Select DfuTarg
  • Click the Upload button which should now be enabled
  • This will begin the DFU process and your Bluefruit LE module will reset when the update is complete
  • If you get the normal 2 or 3 pulse blinky pattern, the update worked!


As a last resort, if you have access to a Raspberry Pi, a Segger J-Link or a STLink/V2, you can also try manually reflashing the entire device, as described in the FAQ above, with further details on the Software Resources page.

How do I reflash my Bluefruit LE module over SWD?

Reflashing Bluefruit LE modules over SWD (ex. switching to the sniffer firmware and back) is at your own risk and can lead to a bricked device, and we can't offer any support for this operation!  You're on your own here, and there are unfortunately 1,000,000 things that can go wrong, which is why we offer two separate Bluefruit LE Friend boards -- the sniffer and the normal Bluefruit LE Friend board with the non-sniffer firmware, which provides a bootloader with fail safe features that prevents you from ever bricking boards via OTA updates.

AdaLink (SWD/JTAG Debugger Wrapper)

Transitioning between the two board types (sniffer and Bluefruit LE module) is unfortunately not a risk-free operation, and requires external hardware, software and know-how to get right, which is why it isn't covered by our support team.

That said ... if you're determined to go down that lonely road, and you have a Segger J-Link (which is what we use internally for production and development), or have already erased your Bluefruit LE device, you should have a look at AdaLink, which is the tool we use internally to flash the four files required to restore a Bluefruit LE module. (Note: recent version of AdaLink also support the cheaper STLink/V2, though the J-Link is generally more robust if you are going to purchase a debugger for long term use.)

The mandatory Intel Hex files are available in the Bluefruit LE Firmware repo. You will need to flash: 

  • An appropriate bootloader image
  • An appropriate SoftDevice image
  • The Bluefruit LE firmware image
  • The matching signature file containing a CRC check so that the bootloader accepts the firmware image above (located in the same folder as the firmware image)

The appropriate files are generally listed in the version control .xml file in the firmware repository.

If you are trying to flash the sniffer firmware (at your own risk!), you only need to flash a single .hex file, which you can find here. The sniffer doesn't require a SoftDevice image, and doesn't use the fail-safe bootloader -- which is why changing is a one way and risky operation if you don't have a supported SWD debugger.


We also have an internal python tool available that sits one level higher than AdaLink (referenced above), and makes it easier to flash specific versions of the official firmware to a Bluefruit LE module.  For details, see the Adafruit_nRF51822_Flasher repo.

Can I access BETA firmware releases?

The latest versions of the Bluefruit LE Connect applications for iOS and Android allow you to optionally update your Bluefruit LE modules with pre-release or BETA firmware.  

This functionality is primarilly provided as a debug and testing mechanism for support issues in the forum, and should only be used when trying to identify and resolve specific issues with your modules!

Enabling BETA Releases on iOS

  • Make sure you have at least version 1.7.1 of Bluefruit LE Connect
  • Go to the Settings page
  • Scroll to the bottom of the Settings page until you find Bluefruit LE
  • Click on the Bluefruit LE icon and enable the Show beta releases switch
  • You should be able to see any BETA releases available in the firmware repo now when you use Bluefruit LE Connect

Enabling BETA Releases on Android

  • Make sure you have the latest version of Bluefruit LE Connect
  • Open the Bluefruit LE Connect application
  • Click the "..." icon in the top-right corner of the app's home screen
  • Select Settings
  • Scroll down to the Software Updates section and enable Show beta releases
  • You should be able to see any BETA releases available in the firmware repo now when you use Bluefruit LE Connect

Why can't I see my Bluefruit LE device after upgrading to Android 6.0?

In Android 6.0 there were some important security changes that affect Bluetooth Low Energy devices.  If location services are unavailable (meaning the GPS is turned off) you won't be able to see Bluetooth Low Energy devices advertising either. See this issue for details.

Be sure to enable location services on your Android 6.0 device when using Bluefruit LE Connect or other Bluetooth Low Energy applications with your Bluefruit LE modules.

What is the theoretical speed limit for BLE?

This depends on a variety of factors, and is determined by the capabilities of the central device (the mobile phone, etc.) as much as the peripheral.

Taking the HW limits on the nR51822 into account (max 6 packets per connection interval, and a minimum connection interval of 7.5ms) you end up with the following theoretical limits on various mobile operating systems:

  • iPhone 5/6 + IOS 8.0/8.1
    6 packets * 20 bytes * 1/0.030 s = 4 kB/s = 32 kbps
  • iPhone 5/6 + IOS 8.2/8.3
    3 packets * 20 bytes * 1/0.030 s = 2 kB/s = 16 kbps
  • iPhone 5/6 + IOS 8.x with nRF8001
    1 packet * 20 bytes * 1/0.030 s = 0.67 kB/s = 5.3 kbps
  • Nexus 4
    4 packets * 20 bytes * 1/0.0075 s = 10.6 kB/s = 84 kbps
  • Nordic Master Emulator Firmware (MEFW) with nRF51822 0.9.0
    1 packet * 20 bytes * 1/0.0075 = 2.67 kB/s = 21.33 kbps
  • Nordic Master Emulator Firmware (MEFW) with nRF51822 0.11.0
    6 packets * 20 bytes * 1/0.0075 = 16 kB/s = 128 kbps

There are also some limits imposed by the Bluefruit LE firmware, but we are actively working to significantly improve the throughput in the upcoming 0.7.0 release, which will be available Q2 2016.  The above figures are useful as a theoretical maximum to decide if BLE is appropriate for you project or not.

UPDATE: For more specific details on the limitations of various Android versions and phones, see this helpful post from Nordic Semiconductors.

Can my Bluefruit board detect other Bluefruit boards or Central devices?

No. All of our Bluefruit LE modules currently operate in peripheral mode, which means they can only advertise their own existence via the advertising payload. The central device (usually your phone or laptop) is responsible for listening for these advertising packets, starting the connection process, and inititating any transactions between the devices.  There is no way for a Bluefruit module to detect other Bluefruit modules or central devices in range, they can only send their own advertising data out and wait for a connection request to come in.

How can I determine the distance between my Bluefruit module and my phone in m/ft?

The short answer is: you can't.

RF devices normally measure signal strength using RSSI, which stands for Received Signal Strength Indicator, which is measured in dBm.  The closer the devices are the strong the RSSI value generally is (-90dBm is much weaker than -60dBm, for example), but there is no reliable relationship between RSSI values in dBm and distance in the real world.  If there is a wall between devices, RSSI will fall.  If there is a lot of interference on the same 2.4GHz band, RSSI will fall. Depending on the device, if you simply change the antenna orientation, RSSI will fall.  You can read the RSSI value between two connected devices with the AT+BLEGETRSSI command, but there are no meaningful and repeatable conclusions that can be drawn from this value about distance other than perhaps 'farther' or 'closer' in a very loose sense of the terms.

How far away from my phone can I have my Bluefruit LE module?

This depends on a number of factors beyond the module itself such as antenna orientation, the antenna design on the phone, transmit power on the sending node, competing traffic in the same 2.4GHz bandwidth, obstacles between end points, etc.

It could be as low as a couple meters up to about 10 meters line of sight, but generally Bluetooth Low Energy is designed for very short range and will work best in the 5-6 meter or less range for reliable communication, assuming normal Bluefruit firmware settings.

How many GATT services and characteristics can I create?

For firmware 0.7.0 and higher, the following limitations are present:

  • Maximum number of services: 10
  • Maximum number of characteristics: 30
  • Maximum buffer size for each characteristic: 32 bytes
  • Maximum number of CCCDs: 16

Is it possible to modify or disable the built in GATT services and characteristics (DIS, DFU, etc.)?

No, unfortunately you can't. We rely on the Device Information Service (DIS) contents to know which firmware and bootloader version you are running, and wouldn't be able to provide firmware updates without being able to trust this information, which i why it's both mandatory and read only.

Similarly, the DFU service is mandatory to maintain over the air updates and disabling it would create more problems that it's presence would cause.

How can I use BlueZ and gatttool with Bluefruit modules?

BlueZ has a bit of a learning curve associated with it, but you can find some notes below on one option to send and receive data using the BLE UART Service built into all of our Bluefruit LE modules and boards.

These commands may change with different versions of BlueZ. Version 5.21 was used below.

Download: file
# Initialise the USB dongle
$ sudo hciconfig hci0 up

# Scan for the UART BLE device
$ sudo hcitool lescan
  D6:4E:06:4F:72:86 UART

# Start gatttool, pointing to the UART device found above
$ sudo gatttool -b D6:4E:06:4F:72:86 -I -t random --sec-level=high

  [D6:4E:06:4F:72:86][LE]> connect
  Attempting to connect to D6:4E:06:4F:72:86
  Connection successful
# Scan for primary GATT Services
  [D6:4E:06:4F:72:86][LE]> primary
  attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb
  attr handle: 0x0008, end grp handle: 0x0008 uuid: 00001801-0000-1000-8000-00805f9b34fb
  attr handle: 0x0009, end grp handle: 0x000e uuid: 6e400001-b5a3-f393-e0a9-e50e24dcca9e
  attr handle: 0x000f, end grp handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb

# Get the handles for the entries in the UART service (handle 0x0009)
  [D6:4E:06:4F:72:86][LE]> char-desc
  handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb
  handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb
  handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
  handle: 0x0004, uuid: 00002803-0000-1000-8000-00805f9b34fb
  handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
  handle: 0x0006, uuid: 00002803-0000-1000-8000-00805f9b34fb
  handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
  handle: 0x0008, uuid: 00002800-0000-1000-8000-00805f9b34fb
  handle: 0x0009, uuid: 00002800-0000-1000-8000-00805f9b34fb
  handle: 0x000a, uuid: 00002803-0000-1000-8000-00805f9b34fb
  handle: 0x000b, uuid: 6e400002-b5a3-f393-e0a9-e50e24dcca9e
  handle: 0x000c, uuid: 00002803-0000-1000-8000-00805f9b34fb
  handle: 0x000d, uuid: 6e400003-b5a3-f393-e0a9-e50e24dcca9e
  handle: 0x000e, uuid: 00002902-0000-1000-8000-00805f9b34fb
  handle: 0x000f, uuid: 00002800-0000-1000-8000-00805f9b34fb
  handle: 0x0010, uuid: 00002803-0000-1000-8000-00805f9b34fb
  handle: 0x0011, uuid: 00002a27-0000-1000-8000-00805f9b34fb

# 6e400002 (handle 0x000b) = TX characteristic
# 6e400003 (handle 0x000d) = RX characteristic

# Optional (but maybe helpful) ... scan for CCCD entries
  [D6:4E:06:4F:72:86][LE]> char-read-uuid 2902
  handle: 0x000e 	 value: 00 00 
# Enable notifications on the RX characteristic (CCCD handle = 0x000e)
# 0100 = get notifications
# 0200 = get indications
# 0300 = get notifications + indications
# 0000 = disable notifications + indications
  [D6:4E:06:4F:72:86][LE]> char-write-req 0x000e 0100
  Characteristic value was written successfully

# Just to make sure it was updated
  [D6:4E:06:4F:72:86][LE]> char-read-hnd 0x000e
  Characteristic value/descriptor: 01 00 
# Writing "test" in the Serial Monitor of the Arduino sketch should
# cause this output not that notifications are enabled:
  Notification handle = 0x000d value: 74 65 73 74 

# Write something to the TX characteristic (handle = 0x000b)
# This should cause E F G H to appear in the Serial Monitor
  [D6:4E:06:4F:72:86][LE]> char-write-cmd 0x000b 45         
  [D6:4E:06:4F:72:86][LE]> char-write-cmd 0x000b 46
  [D6:4E:06:4F:72:86][LE]> char-write-cmd 0x000b 47
  [D6:4E:06:4F:72:86][LE]> char-write-cmd 0x000b 48

# To send multiple bytes
  [D6:4E:06:4F:72:86][LE]> char-write-cmd 0x000B 707172737475
# If you are running the callbackEcho sketch and notifications
# are enabled you should get this response after the above cmd:
  Notification handle = 0x000d value: 70 71 72 73 74 75 


# If you just want to enable constant listening, enter the following command from the CLI:
$ sudo gatttool -b D6:4E:06:4F:72:86 -t random --char-write-req -a 0x000e -n 0100 --listen

# This should give us the following output as data is written on the Uno,
# though we can't send anything back:
  Characteristic value was written successfully
  Notification handle = 0x000d value: 74 65 73 74 
  Notification handle = 0x000d value: 6d 6f 72 65 20 74 65 73 74 

Can I use the IRQ pin to wake my MCU up from sleep when BLE UART data is available?

No, on SPI-based boards the IRQ pin is used to indicate that an SDEP response is available to an SDEP command. For example, when you sent the `AT+BLEUARTRX` command as an SDEP message, the Bluefruit firmware running on the nRF51822 will parse the message, prepare an SDEP response, and trigger the IRQ pin to tell the MCU that the response is ready. This is completely independant from the BLE UART service, which doesn't have interrupt capability at present.

Can I also update the sketch running on the device using Bluefruit LE Connect?

No, only the core firmware can be updated over the air. Sketches need to be loaded using the Arduino IDE and serial bootloader.

DFU Bluefruit Updates

The video below is out of date and applies to early versions of the board before the Bluefruit LE Connect apps were available for iOS, Android and OS X in the respective app stores. To keep your device up to date, simply install and open the Bluefruit LE Connect app and connect to your Bluefruit device. If a firmware update is available, it will be automatically proposed, and the entire update process will be handled transparently for you.

You can reprogram the Bluefruit LE module itself over-the-air using an Android or iOS phone/tablet. This doesn't reprogram the ATmega32u4 in the Bluefruit Micro, only the BLE module itself. Since its not a common thing to do, its a little challenging to do.

You will need to disconnect/unpower the Bluefruit Micro, connect a wire temporarily between the DFU pin and GND and then power up the board via USB or battery.

The red LED will blink continuously, letting you know it's in DFU mode. Then follow our guide for field updating the firmware



Click to embiggen

We've changed the regulator from an SPX3819 to AP2112 - it has lower dropout but cannot handle higher than 6V

Fabrication Print

Dimensions in inches

Device Recovery

Sometimes, bad things unfortunately happen. Thankfully, 99% of the time it's purely a SW issue and the Bluefruit devices have a robust bootloader with some fail safes that can almost always recover your device.

How to Recover a Bluefruit Board

1. Force DFU Mode at Startup

The first step is to force your board into a special bootloader mode, which will prevent any faulty user sketches or corrupted config data from causing problems.

  • Connect the DFU pin to GND with a jumper cable, or if your board has a DFU button hold the button down when adding power to your board (connecting the USB cable, etc.)
  • Once the device is powered, you should see a faster DFU MODE blinky pattern that lets you know you are in bootloader mode.
  • Now remove the jumper cable between DFU and GND (to prevent going into DFU mode when you reset)
Remove the jumper cable between DFU and GND once you are in DFU mode so that you exit it during the next reset!

2. Update the Bluefruit Firmware

Next, update your device to the latest Bluefruit firmware using the Bluefruit LE Connect app. We regularly fix bugs, and it's always a good idea to be on the latest release.

You can perform a firmware update in DFU mode, although the Bluefruit board may appear as DfuTarg in the Bluefruit LE Connect app, and you will will need to select the right firmware 'family' for you board.

Because bootloader mode is a fail safe mode and has a small subset of Bluefruit's features, we can't tell the Bluefruit LE Connect app very many details about our HW. As such, you will need to indicate which firmware type to flash ... specifically, whether to flash the UART of SPI based firmware. Be sure to select the right one, based on your product and the table below:



3. Flash a Test Sketch

Once the core Bluefruit firmware has been updated, flash a test sketch to the device from the Arduino IDE, such as the following blinky code:

Download: file
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second

4. Perform a Factory Reset

Once the core Bluefruit firmware has been updated, the final step is to perform a factory reset.

  • With the board still powered up, connect the DFU pin to GND
  • Leave the pin set to GND (or hold the DFU button down) for >5 seconds until the BLUE status LED starts to blink
  • Remove the DFU jumper cable or release the DFU button

This will cause a factory reset which will wipe all config data, and should restore your board, getting you back to a normal state in most situations!

Still Having Problems?

Hop on over to our support forums clearly explaining your problem along with the following information, and, we'll be happy to help:

  • You product name and ideally the product ID
  • The Bluefruit firmware version you are using (available at the top of the Serial Monitor output on most example sketches)
  • The Operating System your are using
  • The Arduino IDE version you are using

Providing the above information in your first post will skip a round of two of back and forth and you'll get an answer from us quicker, saving everyone time and effort!

Be sure to see the FAQ section of this learning guide as well, which has answer to many common problems!

Feather HELP!

Even though this FAQ is labeled for Feather, the questions apply to ItsyBitsy's as well!

My ItsyBitsy/Feather stopped working when I unplugged the USB!

A lot of our example sketches have a

while (!Serial);

line in setup(), to keep the board waiting until the USB is opened. This makes it a lot easier to debug a program because you get to see all the USB data output. If you want to run your Feather without USB connectivity, delete or comment out that line

My Feather never shows up as a COM or Serial port in the Arduino IDE

A vast number of Itsy/Feather 'failures' are due to charge-only USB cables

We get upwards of 5 complaints a day that turn out to be due to charge-only cables!

Use only a cable that you know is for data syncing

If you have any charge-only cables, cut them in half throw them out. We are serious! They tend to be low quality in general, and will only confuse you and others later, just get a good data+charge USB cable

Ack! I "did something" and now when I plug in the Itsy/Feather, it doesn't show up as a device anymore so I cant upload to it or fix it...

No problem! You can 'repair' a bad code upload easily. Note that this can happen if you set a watchdog timer or sleep mode that stops USB, or any sketch that 'crashes' your board

  1. Turn on verbose upload in the Arduino IDE preferences
  2. Plug in Itsy or Feather 32u4/M0, it won't show up as a COM/serial port that's ok
  3. Open up the Blink example (Examples->Basics->Blink)
  4. Select the correct board in the Tools menu, e.g. Feather 32u4, Feather M0, Itsy 32u4 or M0 (physically check your board to make sure you have the right one selected!)
  5. Compile it (make sure that works)
  6. Click Upload to attempt to upload the code
  7. The IDE will print out a bunch of COM Ports as it tries to upload. During this time, double-click the reset button, you'll see the red pulsing LED that tells you its now in bootloading mode
  8. The board will show up as the Bootloader COM/Serial port
  9. The IDE should see the bootloader COM/Serial port and upload properly

I can't get the Itsy/Feather USB device to show up - I get "USB Device Malfunctioning" errors!

This seems to happen when people select the wrong board from the Arduino Boards menu.

If you have a Feather 32u4 (look on the board to read what it is you have) Make sure you select Feather 32u4 for ATMega32u4 based boards! Do not use anything else, do not use the 32u4 breakout board line.

If you have a Feather M0 (look on the board to read what it is you have) Make sure you select Feather M0 - do not use 32u4 or Arduino Zero

If you have a ItsyBitsy M0 (look on the board to read what it is you have) Make sure you select ItsyBitsy M0 - do not use 32u4 or Arduino Zero

I'm having problems with COM ports and my Itsy/Feather 32u4/M0

Theres two COM ports you can have with the 32u4/M0, one is the user port and one is the bootloader port. They are not the same COM port number!

When you upload a new user program it will come up with a user com port, particularly if you use Serial in your user program.

If you crash your user program, or have a program that halts or otherwise fails, the user COM port can disappear.

When the user COM port disappears, Arduino will not be able to automatically start the bootloader and upload new software.

So you will need to help it by performing the click-during upload procedure to re-start the bootloader, and upload something that is known working like "Blink"

I don't understand why the COM port disappears, this does not happen on my Arduino UNO!

UNO-type Arduinos have a seperate serial port chip (aka "FTDI chip" or "Prolific PL2303" etc etc) which handles all serial port capability seperately than the main chip. This way if the main chip fails, you can always use the COM port.

M0 and 32u4-based Arduinos do not have a seperate chip, instead the main processor performs this task for you. It allows for a lower cost, higher power setup...but requires a little more effort since you will need to 'kick' into the bootloader manually once in a while

I'm trying to upload to my 32u4, getting "avrdude: butterfly_recv(): programmer is not responding" errors

This is likely because the bootloader is not kicking in and you are accidentally trying to upload to the wrong COM port

The best solution is what is detailed above: manually upload Blink or a similar working sketch by hand by manually launching the bootloader

I'm trying to upload to my Feather M0, and I get this error "Connecting to programmer: .avrdude: butterfly_recv(): programmer is not responding"

You probably don't have Feather M0 selected in the boards drop-down. Make sure you selected Feather M0.

I'm trying to upload to my Feather and i get this error "avrdude: ser_recv(): programmer is not responding"

You probably don't have Feather M0 / Feather 32u4 selected in the boards drop-down. Make sure you selected Feather M0 (or Feather 32u4).

I attached some wings to my Feather and now I can't read the battery voltage!

Make sure your Wing doesn't use pin #9 which is the analog sense for the lipo battery!

The yellow LED Is flickering on my Feather, but no battery is plugged in, why is that?

The charge LED is automatically driven by the Lipoly charger circuit. It will try to detect a battery and is expecting one to be attached. If there isn't one it may flicker once in a while when you use power because it's trying to charge a (non-existant) battery.

It's not harmful, and its totally normal!

This guide was first published on Nov 18, 2015. It was last updated on Nov 18, 2015.