CircuitPython BLE UART Example

It's easy to use Adafruit AirLift ESP32 co-processor boards for Bluetooth Low Energy (BLE) with CircuitPython. When you reset the ESP32, you can put it in WiFi mode (the default), or in BLE mode; you cannot use both modes simultaenously.

Here's a simple example of using BLE to connect CircuitPython with the Bluefruit Connect app. 

Note: Don't confuse the ESP32 with the ESP32-S2, which is a different module with a similar name. The ESP32-S2 does not support BLE.

Currently the AirLift support for CircuitPython only provides BLE peripheral support. BLE central is under development. So you cannot connect to BLE devices like Heart Rate monitors, etc., but you can act as a BLE peripheral yourself.
The CircuitPython 6.0.0.rc.0 build for the Adafruit MatrixPortal has a bug that prevents ESP32 BLE from working. Wait for 6.0.0.rc.1.

ESP32 Co-Processor Wiring

Depending on the Airlift board you have, you may need to do some wiring to enable BLE use of the board. BLE and WiFi share some pins, but also use different pins. If you already wired your board for WiFi, it may not be wired for BLE. Check which AirLift board you have, and refer to the appropriate section below to what you need to do, if anything.

On-Board Airlift Co-Processor - No Wiring Needed

If you have an Adafruit Metro M4 AirLift Lite, an Adafruit PyPortal (regular, Pynt or Titano), an Adafruit MatrixPortal, or other Adafruit board with an onboard ESP32 co-processor, then everything is prewired for you, and the pins you need to use are predefined in CircuitPython.

Adafruit AirLift ESP32 Breakout Wiring

If you have an Adafruit AirLift ESP32 Breakout board, you'll need to wire it to your microcontroller board. The following example shows it wired to a Feather M4. You can choose different pins for GPIO0, BUSY, and !RST, but the pin choices below correspond to several other boards, for consistency. If you do change the pins, keeping the TX and RX pins the same is a good idea. If you choose different pins, you'll need to edit the example program below.

Make these connections:

  • Breakout VIN to Feather USB
  • Breakout GND to Feather GND
  • Breakout GPIO0 to Feather D10
  • Breakout BUSY to Feather D11
  • Breakout !RST to Feather D12
  • Breakout CS to Feather D13
  • Breakout RXI to Feather TX
  • Breakout TXO to Feather RX

You must use USB or VBAT on a Feather board for powering the Adafruit AirLift Breakout because of its high current requirements! Don't power it from a regulated 3.3V output on your microntroller board unless you are confident that output will supply enough current.

Note that the breakout RXI and TXO go to TX and RX, respectively (T <-> R and R <-> T). One side transmits and the other receives.

Adafruit AirLift ESP32 Shield Wiring

If you have an Adafruit AirLift ESP32 Shield, you will need to solder three jumpers closed on the bottom side of the board to enable BLE. The rest of the ESP32 pins you need are already jumpered to certain shield pins.

Solder the three highlighted jumpers closed, marked ESP TX and RX, and G0 in the photo on the left. These markings are not on the board. After you do this, these connections are now pre-wired:

  • ESP32 GPIO0 to shield D6
  • ESP32 BUSY to shield D7
  • ESP32 !RST to shield D5
  • ESP32 CS to shield D10
  • ESP32 TX to shield D0 (RX)
  • ESP32 RX to shield D1 (TX)

Note that the ESP32 TX and RX go to the shield RX/D0 and TX/D1, respectively (T <-> R and R <-> T). One side transmits and the other receives.

Adafruit AirLift ESP32 FeatherWing Wiring

If you have an Adafruit Airlift ESP32 FeatherWing, you will need to solder three jumpers closed on the bottom side of the board to enable BLE. The rest of the ESP32 pins you need are already jumpered to certain Feather pins.

Solder the three highlighted jumpers closed, marked ESPRX, ESPTX, and ESPGPIO0 (jumper is to the left of the label in the photo). After you do this, these connections are now pre-wired:

  • ESPGPIO0 to Feather D10
  • ESPBUSY to Feather D11
  • ESPRST to Feather D12
  • ESPCS to Feather D13
  • ESPTX to Feather TX
  • ESPRX to Feather RX

Note that the ESPTX and ESPRX go to the Feather RX and TX, respectively (T <-> R and R <-> T). One side transmits and the other receives.

Adafruit Airlift Bitsy ESP32 Add-On Wiring

If you have an Adafruit Airlift Bitsy ESP32 Add-On, you will need to solder three jumpers closed on the bottom side of the board to enable BLE. The rest of the ESP32 pins you need are already jumpered to certain ItsyBitsy pins.

WARNING! The picture to the left is from the first version of this board, which has the BSY and ERST labels incorrectly reversed. The correct order is ERST, ECS, BSY, from left to right. Only the labels are wrong: there are no trace-routing issues.

Solder the three highlighted jumpers closed, marked ESPRX, ESPTX, and GPIO0. After you do this, these connections are now pre-wired:

  • GPIO0 to ItsyBitsy D10
  • BSY to ItsyBitsy D11
  • ERST to ItsyBitsy D12
  • ECS to ItsyBitsy D13
  • ESPTX to ItsyBitsy TX
  • ESPRX to ItsyBitsy RX

Note that the ESPTX and ESPRX go to the ItsyBitsy RX and TX, respectively (T <-> R and R <-> T). One side transmits and the other receives

Update the AirLift Firmware

Follow the instructions in this guide (Update External ESP32 Airlift Firmware) to update the AirLift firmware to at least version 1.7.1. Previous versions do not support BLE.

Ensure the AirLift firmware is version 1.7.1 or higher for BLE to work.

Install CircuitPython Libraries

Make sure you are running the latest version of Adafruit CircuitPython for your board; you'll need 6.0.0 or later.

Next you'll need to install the necessary libraries to use the hardware and BLE. Carefully follow the steps to find and install these libraries from Adafruit's CircuitPython library bundle.  Our CircuitPython starter guide has a great page on how to use the library bundle.

Install these libraries from the bundle:

  • adafruit_airlift
  • adafruit_ble

Before continuing make sure your board's lib folder or root filesystem has the adafruit_airlift and adafruit_ble folders copied over.

Install the Adafruit Bluefruit LE Connect App

The Adafruit Bluefruit LE Connect iOS and Android apps allow you to connect to BLE peripherals that provide a over-the-air "UART" service. Follow the instructions in the Bluefruit LE Connect Guide to download and install the app on your phone or tablet.

Copy and Adjust the Example Program

Copy the program below to the file code.py on CIRCUITPY on your board.

TAKE NOTE: Adjust the program as needed to suit the AirLift board you have. Comment and uncomment lines 12-39 below as necessary.

Download: file
import board

from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

from adafruit_airlift.esp32 import ESP32

# If you are using a Metro M4 Airlift Lite, PyPortal,
# or MatrixPortal, you can use the default pin settings.
# Leave this DEFAULT line uncommented.
esp32 = ESP32() # DEFAULT

# If you are using an AirLift FeatherWing or AirLift Bitsy Add-On,
# use the pin settings below. Comment out the DEFAULT line above
# and uncomment the lines below.
# If you are using an AirLift Breakout, check that these
# choices match the wiring to your microcontroller board,
# or change them as appropriate.
# esp32 = ESP32(
#     reset=board.D12,
#     gpio0=board.D10,
#     busy=board.D11,
#     chip_select=board.D13,
#     tx=board.TX,
#     rx=board.RX,
# )

# If you are using an AirLift Shield,
# use the pin settings below. Comment out the DEFAULT line above
# and uncomment the lines below.
# esp32 = ESP32(
#     reset=board.D5,
#     gpio0=board.D6,
#     busy=board.D7,
#     chip_select=board.D10,
#     tx=board.TX,
#     rx=board.RX,
# )

adapter = esp32.start_bluetooth()

ble = BLERadio(adapter)
uart = UARTService()
advertisement = ProvideServicesAdvertisement(uart)

while True:
    ble.start_advertising(advertisement)
    print("waiting to connect")
    while not ble.connected:
        pass
    print("connected: trying to read input")
    while ble.connected:
        # Returns b'' if nothing was read.
        one_byte = uart.read(1)
        if one_byte:
            print(one_byte)
            uart.write(one_byte)

Talk to the AirLift via the Bluefruit LE Connect App

Start the Bluefruit LE Connect App on your phone or tablet. You should see a CIRCUITPY device available to connect to. Tap the Connect button (1):

You'll then see a list of Bluefruit Connect functions ("modules"). Choose the UART module (2):

On the UART module page, you can type a string and press Send (3). You'll see that string entered, and then see it echoed back (echoing is in gray).

This guide was first published on Feb 26, 2019. It was last updated on Feb 26, 2019.

This page (CircuitPython BLE) was last updated on Nov 06, 2020.