# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/080/455/medium800thumb/adafruit_products_4363.jpg?1567623171)

Give your ItsyBitsy project a lift with the Adafruit AirLift Bitsy Add-On! This sweet add-on for the ItsyBitsy lets you use the powerful ESP32 as a WiFi or BLE co-processor. You probably have your favorite ItsyBitsy ([like the ItsyBitsy M4](https://www.adafruit.com/product/3800)) that comes with its own set of awesome peripherals and lots of libraries. But it doesn't have WiFi built in! So let's give that chip a best friend, the ESP32. This chip can handle all the heavy lifting of connecting to a WiFi network and transferring data from a site, even if its using the latest TLS/SSL encryption (it has root certificates pre-burned in).

![](https://cdn-learn.adafruit.com/assets/assets/000/080/353/medium800/adafruit_products_iso_main_crop.png?1567539026)

Having WiFi managed by a separate chip means your code is simpler, you don't have to cache socket data, or compile in & debug an SSL library. Instead the Airlift Add-On allows you to send basic but powerful socket-based commands over 8MHz SPI for high speed data transfer. You can use the 3V 32u4, M0, or M4 ItsyBitsy in&nbsp; Arduino although **the '32u4 will not be able to do very complex tasks or buffer a lot of data&nbsp;** because&nbsp;they do not have a lot of RAM. The add-on also works great with CircuitPython, though a SAMD51/Cortex M4 minimum required since we need a bunch of RAM. All you need is an SPI bus and 2 control pins plus a power supply that can provide up to 250mA during WiFi usage.

The ESP32 also supports BLE (Bluetooth Low Energy), though not simultaneously with WiFi. Many of our CircuitPython builds include native support for ESP32 BLE. Right now, we only support the ESP32 acting as a BLE peripheral, but that's sufficient to communicate with the ESP32 from a phone, tablet, host computer, or another BLE-capable board. You use a few control pins and the RX and TX pins to talk to the ESP32 when it's in BLE mode.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/080/354/medium800/adafruit_products_4363_kit_orig_2019_09.jpg?1567539112)

We placed an ESP32 module on a BitsyWing with a tri-state chip for MOSI so you can share the SPI bus. The add on comes fully assembled and tested, pre-programmed with ESP32 SPI WiFi co-processor firmware that&nbsp;[you can use in CircuitPython to use this into&nbsp; WiFi co-processsor over SPI + 2 pins](https://github.com/ladyada/Adafruit_CircuitPython_ESP32SPI). We also toss in some header so you can solder it in though&nbsp; **you'll need stacking headers for your ItsyBitsy to put the add-on on top.**

[The firmware on board is a slight variant of the Arduino WiFiNINA core, which works great!](https://github.com/adafruit/nina-fw)&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/080/355/medium800/adafruit_products_4363_quarter_orig_2019_09.jpg?1567539292)

# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## Pinouts

![](https://cdn-learn.adafruit.com/assets/assets/000/080/359/medium800/adafruit_products_4363_top_orig_2019_09.jpg?1567541417)

# Power Pins
![](https://cdn-learn.adafruit.com/assets/assets/000/080/358/medium800/adafruit_products_pins_power.jpg?1567541347)

- **GND&nbsp;** - Common power/logic ground.
- **3.3V** - Power supply for the ublox WiFi module. You'll need up to 250mA to power the module. ItsyBitsy's tend to have a 500mA regulator so they should be OK, just make sure you're aware of your power budget

## SPI and Control Pins

To keep transfers speedy, we use SPI&nbsp;_not UART Serial.&nbsp;_UART is too slow and hard to synchronize. This uses more pins but the experience is much better!

![](https://cdn-learn.adafruit.com/assets/assets/000/080/363/medium800/adafruit_products_pins_spi.jpg?1567543075)

Classic SPI Pins:

- **SCK** &nbsp;- SPI Clock from your microcontroller,&nbsp; **logic level is 3.3V only**
- **MISO** &nbsp;- SPI Data&nbsp;_from_&nbsp;the AirLift&nbsp;_to_&nbsp;the microcontroller,&nbsp; **logic level is 3.3V only.&nbsp;** This is tri-stated when not selected, so you can share the SPI bus with other devices.
- **MOSI** - SPI Data&nbsp;_to&nbsp;_the AirLift&nbsp;_from_&nbsp;the microcontroller,&nbsp; **logic level is 3.3V only.**
- **ESPCS&nbsp;** - SPI Chip Select from the microcontroller to start sending commands to the AirLift, and to choose BLE mode on reset, **logic level is 3.3V only**

Required Control Pins:

- **ESPBUSY&nbsp;** - this pin is an input from the AirLift, it will let us know when its ready for more commands to be sent. **This is 3.3V logic out.&nbsp;** This pin&nbsp;_must_&nbsp;be connected.
- **ESPRST** - this pin is an output to the AirLift. Set low to put the AirLift into reset. You should use this pin, even though you might be able to run for a short while without it, it's essential to 'kick' the chip if it ever gets into a locked up state.&nbsp; **Logic level is 3.3V**

Warning: 

Optional Control Pins:

- **ESPGPIO0** &nbsp;- this is the ESP32&nbsp; **GPIO0&nbsp;** pin, which is used to put the WiFi module it into bootloading mode if you want to update the firmware. It is also used if you like when the ESP32 is acting as a server, to let you know data is ready for reading. It's not required in WiFi mode, but you'll need to connect it for BLE mode. **You'll need to solder the pad on the bottom of the Bitsy Add-on to connect it**.
- **ESPRX&nbsp;** &&nbsp; **ESPTX** - Serial data in and Serial data out, used for bootloading new firmware, and for communication when in BLE mode. Leave disconnected if not using BLE or when not uploading new WiFi firmware to the AirLift (which is a rare occurrence). **You'll need to solder the two pads on the bottom of the Bitsy Add-on** to use these pins. Soldering the pads connects ESPTX to RX and ESPTX to RX, respectively.

![](https://cdn-learn.adafruit.com/assets/assets/000/080/366/medium800/adafruit_products_jumpers.jpg?1567543632)

## RGB LED

There is a small RGB LED to the left of the ESP32. These RGB LEDs are available in the Arduino and CircuitPython libraries if you'd like to PWM them for a visual alert. They're connected to the ESP32's pins 26 ( **Red** ), 25 ( **Green** ), and 27 ( **Blue** ).

![](https://cdn-learn.adafruit.com/assets/assets/000/080/364/medium800/adafruit_products_pins_rgb.jpg?1567543155)

# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## Assembly

![](https://cdn-learn.adafruit.com/assets/assets/000/080/454/medium800thumb/adafruit_products_4363.jpg?1567623159)

Danger: 

![](https://cdn-learn.adafruit.com/assets/assets/000/080/365/medium800/adafruit_products_antenna_watchout.png?1567543381)

To stack the Airlift Add-on on top of the ItsyBitsy, you'll need stacking headers for the ItsyBitsy. For now you'll need to cut down a set of [Feather Stacking Headers](https://www.adafruit.com/product/2830) to fit the ItsyBitsy however we will have headers with the correctly length soon!

![adafruit_products_feather_2830-06.jpg](https://cdn-learn.adafruit.com/assets/assets/000/080/351/medium640/adafruit_products_feather_2830-06.jpg?1567533523)

# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## CircuitPython WiFi

It's easy to use the Adafruit AirLift breakout with CircuitPython and the [Adafruit CircuitPython ESP32SPI](https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI) module.&nbsp; This module allows you to easily add WiFi to your project.

Danger: 

## CircuitPython Microcontroller Pinout
Since all CircuitPython-running ItsyBitsies follow the same pinout, you do not need to change any of the pins listed below.

To use the ESP32's pins, copy the following lines into your code:

```python
esp32_cs = DigitalInOut(board.D13)
esp32_reset = DigitalInOut(board.D12)
esp32_ready = DigitalInOut(board.D11)
```

Then, include the following code to use the pin:

```python
esp32_gpio0 = DigitalInOut(board.D10)
```

## Add Your **settings.toml** File

Remember to add your **settings.toml** file as described in the [Create Your settings.toml File page](https://learn.adafruit.com/pico-w-wifi-with-circuitpython/create-your-settings-toml-file) earlier in the guide. You'll need to include your `CIRCUITPY_WIFI_SSID` and `CIRCUITPY_WIFI_PASSWORD` in the file.&nbsp;

```auto
CIRCUITPY_WIFI_SSID = "your-ssid-here"
CIRCUITPY_WIFI_PASSWORD = "your-ssid-password-here"
```

## CircuitPython Setup

First make sure you are running the [latest version of Adafruit CircuitPython](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython) for your board.

Next you'll need to install the necessary libraries to use the hardware. Thankfully, we can do this in one go. In the example below, click the **Download Project Bundle** button below to download the necessary libraries and the **code.py** file in a zip file. Extract the contents of the zip file, and copy the **entire lib folder** and the **code.py** file to your **CIRCUITPY** drive.

Your **CIRCUITPY/lib** folder should contain the following folders and files:

- **/adafruit\_bus\_device**
- **/adafruit\_esp32spi**
- **adafruit\_requests.mpy**

![CIRCUITPY](https://adafruit.github.io/Adafruit_Learning_System_Guides/Metro_M7_Examples_WiFi.png )

## CircuitPython Usage

Copy the following code to your **code.py** file on your microcontroller:

```python
import board
import busio
from digitalio import DigitalInOut

from adafruit_esp32spi import adafruit_esp32spi

print("ESP32 SPI hardware test")

esp32_cs = DigitalInOut(board.D13)
esp32_reset = DigitalInOut(board.D12)
esp32_ready = DigitalInOut(board.D11)

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
    print("ESP32 found and in idle mode")
print("Firmware vers.", esp.firmware_version)
print("MAC addr:", [hex(i) for i in esp.MAC_address])

for ap in esp.scan_networks():
    print("\t%s\t\tRSSI: %d" % (str(ap['ssid'], 'utf-8'), ap['rssi']))

print("Done!")
```

[Connect to the serial console](https://learn.adafruit.com/welcome-to-circuitpython/interacting-with-the-serial-console) to see the output. It should look something like the following:

![](https://cdn-learn.adafruit.com/assets/assets/000/076/153/medium800/adafruit_products_AirLift_Output.png?1559078537)

Make sure you see the same output! If you don't, check your wiring. Note that we've changed the pinout in the code example above to reflect the CircuitPython Microcontroller Pinout at the top of this page.

Once you've succeeded, continue onto the next page!

Warning: If you can read the Firmware and MAC address but fails on scanning SSIDs, check your power supply, you may be running out of juice to the ESP32 and it's resetting.

# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## Create Your settings.toml File

CircuitPython works with WiFi-capable boards to enable you to make projects that have network connectivity. This means working with various passwords and API keys. As of [CircuitPython 8](https://circuitpython.org/downloads), there is support for a **settings.toml** file. This is a file that is stored on your **CIRCUITPY** drive, that contains all of your secret network information, such as your SSID, SSID password and any API keys for IoT services. It is designed to separate your sensitive information from your **code.py** file so you are able to share your code without sharing your credentials.

CircuitPython previously used a **secrets.py** file for this purpose. The **settings.toml** file is quite similar.

Warning: Your **settings.toml** file should be stored in the main directory of your **CIRCUITPY** drive. It should not be in a folder.

## CircuitPython **settings.toml** File

This section will provide a couple of examples of what your **settings.toml** file should look like, specifically for CircuitPython WiFi projects in general.

The most minimal **settings.toml** file must contain your WiFi SSID and password, as that is the minimum required to connect to WiFi. Copy this example, paste it into your **settings.toml** , and update:

- `your_wifi_ssid`
- `your_wifi_password`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
```

Many CircuitPython network-connected projects on the Adafruit Learn System involve using Adafruit IO. For these projects, you must _also_ include your Adafruit IO username and key. Copy the following example, paste it into your settings.toml file, and update:

- `your_wifi_ssid`
- `your_wifi_password`
- `your_aio_username`
- `your_aio_key`

```auto
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
ADAFRUIT_AIO_USERNAME = "your_aio_username"
ADAFRUIT_AIO_KEY = "your_aio_key"
```

Some projects use different variable names for the entries in the **settings.toml** file. For example, a project might use `ADAFRUIT_AIO_ID` in the place of `ADAFRUIT_AIO_USERNAME`. **If you run into connectivity issues, one of the first things to check is that the names in the settings.toml file match the names in the code.**

Warning: Not every project uses the same variable name for each entry in the **settings.toml** file! Always verify it matches the code.

## **settings.toml** File Tips
Here is an example **settings.toml** file.

```auto
# Comments are supported
CIRCUITPY_WIFI_SSID = "guest wifi"
CIRCUITPY_WIFI_PASSWORD = "guessable"
CIRCUITPY_WEB_API_PORT = 80
CIRCUITPY_WEB_API_PASSWORD = "passw0rd"
test_variable = "this is a test"
thumbs_up = "\U0001f44d"
```

In a **settings.toml** file, it's important to keep these factors in mind:

- Strings are wrapped in double quotes; ex: `"your-string-here"`
- Integers are _ **not** _ quoted and may be written in decimal with optional sign (`+1`, `-1`, `1000`) or hexadecimal (`0xabcd`).
  - Floats (decimal numbers), octal (`0o567`) and binary (`0b11011`) are not supported.

- Use `\u` escapes for weird characters, `\x` and `\ooo` escapes are not available in **.toml** files
  - Example: `\U0001f44d` for 👍 (thumbs up emoji) and `\u20ac` for € (EUR sign)

- Unicode emoji, and non-ASCII characters, stand for themselves as long as you're careful to save in "UTF-8 without BOM" format

&nbsp;

&nbsp;

When your&nbsp; **settings.toml&nbsp;** file is ready, you can save it in your text editor with the **.toml** &nbsp;extension.

![adafruit_products_dotToml.jpg](https://cdn-learn.adafruit.com/assets/assets/000/117/071/medium640/adafruit_products_dotToml.jpg?1671034293)

## Accessing Your **settings.toml** Information in **code.py**
In your **code.py** file, you'll need to `import` the `os` library to access the **settings.toml** file. Your settings are accessed with the `os.getenv()` function. You'll pass your settings entry to the function to import it into the **code.py** file.

```python
import os

print(os.getenv("test_variable"))
```

![](https://cdn-learn.adafruit.com/assets/assets/000/117/072/medium800/adafruit_products_tomlOutput.jpg?1671034496)

In the upcoming CircuitPython WiFi examples, you'll see how the **settings.toml&nbsp;** file is used for connecting to your SSID and accessing your API keys.

# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## Internet Connect!

# Connect to WiFi

OK, now that you have your&nbsp; **settings.toml** file set up - you can connect to the Internet.

To do this, you need to first install a few libraries, into the lib folder on your **CIRCUITPY** drive. Then you need to update **code.py** with the example script.

Thankfully, we can do this in one go. In the example below, click the **Download Project Bundle** button below to download the necessary libraries and the **code.py** file in a zip file. Extract the contents of the zip file, open the directory **examples/** and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your **CIRCUITPY** drive.

Your **CIRCUITPY** drive should now look similar to the following image:

![CIRCUITPY](https://adafruit.github.io/Adafruit_CircuitPython_Bundle/esp32spi_esp32spi_simpletest.py.png )

Info: Update to CircuitPython 9.2.x or later to use this example.

https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/blob/main/examples/esp32spi_simpletest.py

And save it to your board, with the name **code.py**.

Don't forget you'll also need to create the **settings.toml** file as seen above, with your WiFi ssid and password.

In a serial console, you should see something like the following. For more information about connecting with a serial console, view the guide [Connecting to the Serial Console](https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console).

```terminal
&gt;&gt;&gt; import wifitest
ESP32 SPI webclient test
ESP32 found and in idle mode
Firmware vers. 1.7.5
MAC addr: 24:C9:DC:BD:0F:3F
	HomeNetwork             RSSI: -46
	HomeNetwork             RSSI: -76
	Fios-12345              RSSI: -92
	FiOS-AB123              RSSI: -92
	NETGEAR53               RSSI: -93
Connecting to AP...
Connected to HomeNetwork 	RSSI: -45
My IP address is 192.168.1.245
IP lookup adafruit.com: 104.20.39.240
Ping google.com: 30 ms
Fetching text from http://wifitest.adafruit.com/testwifi/index.html
----------------------------------------
This is a test of Adafruit WiFi!
If you can read this, its working :)
----------------------------------------

Fetching json from http://wifitest.adafruit.com/testwifi/sample.json
----------------------------------------
{'fun': True, 'company': 'Adafruit', 'founded': 2005, 'primes': [2, 3, 5], 'pi': 3.14, 'mixed': [False, None, 3, True, 2.7, 'cheese']}
----------------------------------------
Done!
```

Going over the example above, here's a breakdown of what the program is doing:

- Initialize the ESP32 over SPI using the SPI port and 3 control pins:

```python
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)

#...

else:
    spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
```

- Get the socket pool and the SSL context, and then tell the `adafruit_requests` library about them.

```python
pool = adafruit_connection_manager.get_radio_socketpool(esp)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp)
requests = adafruit_requests.Session(pool, ssl_context)
```

- Verify an ESP32 is found, checks the firmware and MAC address

```auto
if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
    print("ESP32 found and in idle mode")
print("Firmware vers.", esp.firmware_version)
print("MAC addr:", ":".join("%02X" % byte for byte in esp.MAC_address))
```

- Perform a scan of all access points it can see and print out the name and signal strength.

```python
for ap in esp.scan_networks():
    print("\t%-23s RSSI: %d" % (ap.ssid, ap.rssi))
```

- Connect to the AP we've defined here, then print out the local IP address. Then attempt to do a domain name lookup and ping google.com to check network connectivity. (Note sometimes the ping fails or takes a while; this isn't a big deal.)

```python
print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(ssid, password)
    except OSError as e:
        print("could not connect to AP, retrying: ", e)
        continue
print("Connected to", esp.ap_info.ssid, "\tRSSI:", esp.ap_info.rssi)
print("My IP address is", esp.ipv4_address)
print(
    "IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com"))
)
```

Now we're getting to the really interesting part of the example program. We've written a library for web fetching web data, named [adafruit\_requests](https://github.com/adafruit/Adafruit_CircuitPython_Requests). It is a lot like the regular Python library named [requests](https://requests.readthedocs.io/en/latest/). This library allows you to send HTTP and HTTPS requests easily and provides helpful methods for parsing the response from the server.

- Here is the part of the example program is fetching text data from a URL.

```python
TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html"  # Further up in the program

# ...

print("Fetching text from", TEXT_URL)
r = requests.get(TEXT_URL)
print('-' * 40)
print(r.text)
print('-' * 40)
r.close()
```

- Finally, here the program is fetching some JSON data. The `adafruit_requests` library will parse the JSON into a Python dictionary whose structure is the same as the structure of the JSON.

```auto
JSON_URL = "http://wifitest.adafruit.com/testwifi/sample.json"   # Further up in the program

# ...

print("Fetching json from", JSON_URL)
r = requests.get(JSON_URL)
print('-' * 40)
print(r.json())
print('-' * 40)
r.close()
```

# Advanced Requests Usage

Want to send custom HTTP headers, parse the response as raw bytes, or handle a response's http status code in your CircuitPython code?

We've written an&nbsp;example to show advanced usage of the requests module below.

To use with CircuitPython, you need to first install a few libraries, into the lib folder on your **CIRCUITPY** drive. Then you need to update **code.py** with the example script.

Thankfully, we can do this in one go. In the example below, click the **Download Project Bundle** button below to download the necessary libraries and the **code.py** file in a zip file. Extract the contents of the zip file, open the directory **examples/** and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your **CIRCUITPY** drive.

https://github.com/adafruit/Adafruit_CircuitPython_Requests/blob/main/examples/esp32spi/requests_esp32spi_advanced.py

Your **CIRCUITPY** drive should now look similar to the following image:

![CIRCUITPY](https://adafruit.github.io/Adafruit_CircuitPython_Bundle/requests_esp32spi_requests_esp32spi_advanced.py.png )

# WiFi Manager

The way the examples above connect to WiFi works but it's a little finicky. Since WiFi is not necessarily so reliable, you may have disconnects and need to reconnect. For more advanced uses, we recommend using the `WiFiManager` class. It will wrap the connection/status/requests loop for you - reconnecting if WiFi drops, resetting the ESP32 if it gets into a bad state, etc.

Here's a more advanced example that shows using the `WiFiManager` and also how to fetch the current time from a web source.

https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/blob/main/examples/esp32spi_localtime.py

# Further Information

For more information on the basics of doing networking in CircuitPython, see this guide:

### Networking in CircuitPython

[Networking in CircuitPython](https://learn.adafruit.com/networking-in-circuitpython)
# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## OLD - CircuitPython WiFi

It's easy to use the Adafruit AirLift breakout with CircuitPython and the [Adafruit CircuitPython ESP32SPI](https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI) module.&nbsp; This module allows you to easily add WiFi to your project.

You need plenty of RAM for CircuitPython/requests/json, so the ItsyBitsy M0 will _not_ work! Please use an Itsy with at least 100KB of RAM, like the ItsyBitsy M4!

## CircuitPython Microcontroller Pinout

Since all CircuitPython-running ItsyBitsies follow the same pinout, you do not need to change any of the pins listed below.

To use the ESP32's pins, copy the following lines into your code:

```
esp32_cs = DigitalInOut(board.D13)
esp32_reset = DigitalInOut(board.D12)
esp32_ready = DigitalInOut(board.D11)
```

Then, include the following code to use the pin:

```
esp32_gpio0 = DigitalInOut(board.D10)
```

# CircuitPython Installation of ESP32SPI Library

You'll need to install the&nbsp;[Adafruit CircuitPython ESP32SPI](https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI)&nbsp;library on your CircuitPython board.

First make sure you are running the&nbsp;[latest version of Adafruit CircuitPython](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython)&nbsp;for your board.

Next you'll need to install the necessary libraries&nbsp;to use the hardware--carefully follow the steps to find and install these libraries from&nbsp;[Adafruit's CircuitPython library bundle](https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases).&nbsp; Our CircuitPython starter guide has [a great page on how to install the library bundle](https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries).

You can manually install the necessary libraries from the bundle:

- **adafruit\_esp32spi**
- **adafruit\_bus\_device**

Before continuing make sure your board's lib folder or root filesystem has the&nbsp; **adafruit\_esp32spi** and **adafruit\_bus\_device** folders **&nbsp;** copied over.  
  
Next[&nbsp;make sure you are set up to connect to the serial console](https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console)

# CircuitPython Usage

Copy the following code to your **code.py** file on your microcontroller:

```
import board
import busio
from digitalio import DigitalInOut

from adafruit_esp32spi import adafruit_esp32spi

print("ESP32 SPI hardware test")

esp32_cs = DigitalInOut(board.D13)
esp32_reset = DigitalInOut(board.D12)
esp32_ready = DigitalInOut(board.D11)

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

if esp.status == adafruit_esp32spi.WL_IDLE_STATUS:
    print("ESP32 found and in idle mode")
print("Firmware vers.", esp.firmware_version)
print("MAC addr:", [hex(i) for i in esp.MAC_address])

for ap in esp.scan_networks():
    print("\t%s\t\tRSSI: %d" % (str(ap['ssid'], 'utf-8'), ap['rssi']))

print("Done!")
```

[Connect to the serial console](https://learn.adafruit.com/welcome-to-circuitpython/interacting-with-the-serial-console) to see the output. It should look something like the following:

![](https://cdn-learn.adafruit.com/assets/assets/000/080/184/medium800/adafruit_products_AirLift_Output.png?1567044021)

Make sure you see the same output! If you don't, check your wiring. Note that we've changed the pinout in the code example above to reflect the CircuitPython Microcontroller Pinout at the top of this page.

Once you've succeeded, continue onto the next page!

Warning: 

# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## CircuitPython BLE

## 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 simultaneously.

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

**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.

Warning: Currently, AirLift BLE support is not currently available on boards with Espressif chips. If the Espressif board provides `_bleio`, it is for native BLE support (e.g. ESP32-S3), not AirLift.

Info: 

# Adafruit Airlift Bitsy ESP32 Add-On Wiring

If you have an&nbsp; **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.

## Update the AirLift Firmware

You will need to update the AirLift's firmware to at least version 1.7.1. **Previous versions of the AirLift firmware do not support BLE.&nbsp;**

Follow the instructions in the guide below, and come back to this page when you've upgraded the AirLift's firmware:

[Upgrade External ESP32 AirLift Firmware](https://learn.adafruit.com/upgrading-esp32-firmware/upgrade-an-external-esp32)
Warning: 

## Install CircuitPython Libraries

First make sure you are running the [latest version of Adafruit CircuitPython](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython) for your board.

Next you'll need to install the necessary libraries to use the hardware. Thankfully, we can do this in one go. In the example below, click the **Download Project Bundle** button below to download the necessary libraries and the **code.py** file in a zip file. Extract the contents of the zip file, and copy the **entire lib folder** and the **code.py** file to your **CIRCUITPY** drive.

Your **CIRCUITPY/lib** folder should contain the following folders and files:

- **/adafruit\_airlift**
- **/adafruit\_ble**
- **/adafruit\_bus\_device**
- **/adafruit\_esp32spi**
- **adafruit\_requests.mpy**

![CIRCUITPY](https://adafruit.github.io/Adafruit_Learning_System_Guides/CircuitPython_Templates_airlift_ble_example.png )

## 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](https://learn.adafruit.com/bluefruit-le-connect/) to download and install the app on your phone or tablet.

## BLE Example
Warning: 

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/CircuitPython_Templates/airlift_ble_example/code.py

## 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):

![](https://cdn-learn.adafruit.com/assets/assets/000/096/566/medium800/adafruit_products_airlift-connect.png?1603914360)

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

![](https://cdn-learn.adafruit.com/assets/assets/000/096/567/medium800/adafruit_products_airlift-uart.png?1603914460)

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).

![](https://cdn-learn.adafruit.com/assets/assets/000/096/569/medium800/adafruit_products_airlift-echo.png?1603914605)

# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## Arduino WiFi

You can use the AirLift with Arduino. Unlike CircuitPython, it work work with most of the Arduino compatible ItsyBitsies, even the **3V** ItsyBitsy 32u4. However, if you want to use libraries like ArduinoJSON or add sensors and SD card, you'll really want an ATSAMD21 (Cortex M0) or ATSAMD51 (Cortex M4), both of which have _plenty_ or RAM

# Library Install

We're using a variant of the Arduino WiFiNINA library, which is amazing and written by the Arduino team! **The official WiFi101 library won't work because it doesn't support the ability to change the pins**.

So! We made a fork that you can install.

Click here to download the library:

[Download Adafruit's version of WiFiNINA](https://github.com/adafruit/WiFiNINA/archive/master.zip)
Within the Arduino IDE, select **Install library from ZIP...**

![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/344/medium800/adafruit_products_image.png?1554927164)

# First Test

OK now you have it wired and library installed, time to test it out!

Lets start by scanning the local networks. Load up the&nbsp; **ScanNetworks** &nbsp;example

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/345/medium800/adafruit_products_image.png?1554927615)](https://learn.adafruit.com/assets/74345)

At the top you'll see a section where the GPIO pins are defined

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/351/medium800/adafruit_products_image.png?1554929035)](https://learn.adafruit.com/assets/74351)

If you don't see this, you may have the wrong WiFiNINA library installed. Uninstall it and re-install the Adafruit one as above.

Compile and upload to your board wired up to the AirLift

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/349/medium800/adafruit_products_image.png?1554928982)](https://learn.adafruit.com/assets/74349)

If you don't even get the MAC address printed out, check your wiring.

If you get the MAC address but cannot scan any networks, check your power supply. You need a solid 3.3V into&nbsp; **Vin** &nbsp;in order for the ESP32 not to brown out.

# WiFi Connection Test

Now that you have your wiring checked, time to connect to the Internet!

Open up the&nbsp; **WiFiWebClient&nbsp;** example

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/355/medium800/adafruit_products_image.png?1554929528)](https://learn.adafruit.com/assets/74355)

Open up the secondary tab,&nbsp; **arduino\_secrets.h**. This is where you will store private data like the SSID/password to your network.

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/356/medium800/adafruit_products_image.png?1554929677)](https://learn.adafruit.com/assets/74356)

You must change these string values before updating to your board!

After you've set it correctly, upload and check the serial monitor. You should see the following. If not, go back, check wiring, power and your SSID/password

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/357/medium800/adafruit_products_image.png?1554929767)](https://learn.adafruit.com/assets/74357)

# Secure Connection Example

Many servers today do not allow non-SSL connectivity. Lucky for you the ESP32 has a great TLS/SSL stack so you can have that all taken care of for you. Here's an example of a secure WiFi connection:

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/359/medium800/adafruit_products_image.png?1554930586)](https://learn.adafruit.com/assets/74359)

Note we use&nbsp;`WiFiSSLClient client;`&nbsp;instead of&nbsp;`WiFiClient client;`&nbsp;to require an SSL connection!

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/358/medium800/adafruit_products_image.png?1554930524)](https://learn.adafruit.com/assets/74358)

## JSON Parsing Demo
This example is a little more advanced - many sites will have API's that give you JSON data. We'll use&nbsp;[ArduinoJSON](https://arduinojson.org/)&nbsp;to convert that to a format we can use and then display that data on the serial port (which can then be re-directed to a display of some sort)

First up,&nbsp;[use the Library manager to install ArduinoJSON](https://arduinojson.org/v6/doc/installation/).

Then load the example&nbsp; **JSONdemo**

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/362/medium800/adafruit_products_image.png?1554932723)](https://learn.adafruit.com/assets/74362)

By default it will connect to to the Twitter banner image API, parse the username and followers and display them.

[![adafruit_products_image.png](https://cdn-learn.adafruit.com/assets/assets/000/074/361/medium800/adafruit_products_image.png?1554932631)](https://learn.adafruit.com/assets/74361)

## Adapting Other Examples

Once you've got it connecting to the Internet you can check out the other examples. Most of the sketches included with the Adafruit fork of the WiFiNINA library above will have the pin mapping done for the ItsyBitsies. For other examples the only change you'll want to make is at the&nbsp; **top** &nbsp;of the sketches, add:

```
#define SPIWIFI       SPI  // The SPI port
#define SPIWIFI_SS    13   // Chip select pin
#define ESP32_RESETN  12   // Reset pin
#define SPIWIFI_ACK   11   // a.k.a BUSY or READY pin
#define ESP32_GPIO0   -1
```

 **Note:** &nbsp;These pin definitions leave the the ESP32's **GPIO0** pin undefined (-1). If you wish to use this pin - **solder the pad on the bottom of the Bitsy Add-on&nbsp;** and **set `#define ESP32_GPIO0`** to the correct pin for your microcontroller. For the **ItsyBitsies it will be D10/10**

And then&nbsp; **before** &nbsp;you check the&nbsp;`status()`&nbsp;of the module, call the function&nbsp;`WiFi.setPins(SPIWIFI_SS, SPIWIFI_ACK, ESP32_RESETN, ESP32_GPIO0, &SPIWIFI);`

```
    // check for the WiFi module:
  WiFi.setPins(SPIWIFI_SS, SPIWIFI_ACK, ESP32_RESETN, ESP32_GPIO0, &amp;SPIWIFI);
  while (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    delay(1000);
  }
  
```

# Adafruit Airlift Bitsy Add-On - ESP32 WiFi Co-Processor

## Downloads

## Files

- [NINA-W102 ESP32 Module Datasheet](https://www.u-blox.com/sites/default/files/NINA-W10_DataSheet_%28UBX-17065507%29.pdf)
- [EagleCAD files on GitHub](https://github.com/adafruit/Adafruit-Airlift-Bitsy-Add-On-PCB)
- [Fritzing object in Adafruit Fritzing Library](https://github.com/adafruit/Fritzing-Library/blob/master/parts/Adafruit%20Airlift%20Bitsy%20Add-On.fzpz)

# Schematic
![](https://cdn-learn.adafruit.com/assets/assets/000/080/457/medium800/adafruit_products_schematic.png?1567623352)

# Fab Print
![](https://cdn-learn.adafruit.com/assets/assets/000/080/310/medium800/adafruit_products_fab_print.png?1567211961)


## Primary Products

### Adafruit AirLift Bitsy Add-On – ESP32 WiFi Co-Processor

[Adafruit AirLift Bitsy Add-On – ESP32 WiFi Co-Processor](https://www.adafruit.com/product/4363)
Give your ItsyBitsy project a _lift_ with the Adafruit AirLift Bitsy Add-On - a daughterboard that lets you use the powerful ESP32 as a WiFi co-processor. You probably have your favorite ItsyBitsy ([like the Itsy' M4](https://www.adafruit.com/product/3800)) that comes...

In Stock
[Buy Now](https://www.adafruit.com/product/4363)
[Related Guides to the Product](https://learn.adafruit.com/products/4363/guides)

## Featured Products

### Adafruit ItsyBitsy M4 Express featuring ATSAMD51

[Adafruit ItsyBitsy M4 Express featuring ATSAMD51](https://www.adafruit.com/product/3800)
What's smaller than a Feather but larger than a Trinket? It's an **Adafruit ItsyBitsy M4 Express** featuring the **Microchip ATSAMD51**! Small, powerful, with a ultra fast ATSAMD51 Cortex M4 processor running at 120 MHz - this microcontroller board is perfect...

In Stock
[Buy Now](https://www.adafruit.com/product/3800)
[Related Guides to the Product](https://learn.adafruit.com/products/3800/guides)
### Adafruit ItsyBitsy M0 Express - for CircuitPython & Arduino IDE

[Adafruit ItsyBitsy M0 Express - for CircuitPython & Arduino IDE](https://www.adafruit.com/product/3727)
What's smaller than a Feather but larger than a Trinket? It's an **Adafruit ItsyBitsy M0 Express**! Small, powerful, with a rockin' ATSAMD21 Cortex M0 processor running at 48 MHz - this microcontroller board is perfect when you want something very compact, but still...

In Stock
[Buy Now](https://www.adafruit.com/product/3727)
[Related Guides to the Product](https://learn.adafruit.com/products/3727/guides)
### Adafruit ItsyBitsy 32u4 - 3V 8MHz

[Adafruit ItsyBitsy 32u4 - 3V 8MHz](https://www.adafruit.com/product/3675)
What's smaller than a Feather but larger than a Trinket? It's an Itsy Bitsy! Small, powerful, Arduino-compatible - this microcontroller board is perfect when you want something very compact, but still with a bunch of pins.

Itsy Bitsy is only 1.4" long by 0.7" wide, but...

In Stock
[Buy Now](https://www.adafruit.com/product/3675)
[Related Guides to the Product](https://learn.adafruit.com/products/3675/guides)
### Stacking Headers for Feather - 12-pin and 16-pin female headers

[Stacking Headers for Feather - 12-pin and 16-pin female headers](https://www.adafruit.com/product/2830)
These two **Female Stacking Headers** alone are, well, lonely. But pair them with any of our [Feather](https://www.adafruit.com/categories/777) boards and you're in business!

What do they do? They stack. Put the headers through your Feather and then you can...

Out of Stock
[Buy Now](https://www.adafruit.com/product/2830)
[Related Guides to the Product](https://learn.adafruit.com/products/2830/guides)
### Adafruit LiIon/LiPoly Backpack Add-On for Pro Trinket/ItsyBitsy

[Adafruit LiIon/LiPoly Backpack Add-On for Pro Trinket/ItsyBitsy](https://www.adafruit.com/product/2124)
If you have an ItsyBitsy or Pro Trinket you probably know it's the perfect little size for a portable project. This LiPoly backpack makes it really easy to do! Instead of wiring 2 or 3 boards together to make a charging system, this little PCB sits on top of the PCB and allows a...

In Stock
[Buy Now](https://www.adafruit.com/product/2124)
[Related Guides to the Product](https://learn.adafruit.com/products/2124/guides)

## Related Guides

- [Introducing ItsyBitsy 32u4](https://learn.adafruit.com/introducting-itsy-bitsy-32u4.md)
- [Introducing ItsyBitsy M0 Express](https://learn.adafruit.com/introducing-itsy-bitsy-m0.md)
- [Infinity Mirror Collar](https://learn.adafruit.com/infinity-mirror-collar.md)
- [Rotary Encoder in CircuitPython](https://learn.adafruit.com/rotary-encoder.md)
- [DotStar Belly Dance Fans](https://learn.adafruit.com/dotstar-belly-dance-fans.md)
- [Animated Scrolling "Mario Clouds" TFT Jewelry](https://learn.adafruit.com/scrolling-mario-clouds-tft-jewelry.md)
- [Motorized Turntable](https://learn.adafruit.com/motorized-turntable-circuitpython.md)
- [Watchmen's Sister Night NeoPixel Goggles](https://learn.adafruit.com/watchmen-sister-night-circuitpython-neopixel-goggles.md)
- [Ray Gun Blaster](https://learn.adafruit.com/ray-gun-blaster.md)
- [ItsyBitsy Keybow Mechanical Keypad](https://learn.adafruit.com/itsybitsy-keybow-mechanical-keypad.md)
- [Sensor Plotting with Mu and CircuitPython](https://learn.adafruit.com/sensor-plotting-with-mu-and-circuitpython.md)
- [Portable Trellis Sound Board](https://learn.adafruit.com/portable-trellis-sound-board.md)
- [Neopixel Cosmic Turtle Necklace](https://learn.adafruit.com/neopixel-led-magnetic-pendant-necklace.md)
- [Introducing Adafruit ItsyBitsy M4](https://learn.adafruit.com/introducing-adafruit-itsybitsy-m4.md)
- [Trinket “Question Block” Sound Jewelry](https://learn.adafruit.com/trinket-question-block-sound-jewelry.md)
- [Portable Mini Timelapse Camera](https://learn.adafruit.com/portable-mini-timelapse-camera.md)
- [MakeCode Arcade with SAMD51 M4](https://learn.adafruit.com/makecode-arcade-with-samd51-m4.md)
