# Adafruit AirLift Shield - ESP32 WiFi Co-Processor

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/077/209/medium800/adafruit_products_4285-03.jpg?1560977584)

Give your Arduino project a&nbsp;_lift_&nbsp;with the [Adafruit AirLift Shield](https://www.adafruit.com/product/4285) - a shield that lets you use the powerful ESP32 as a WiFi or BLE co-processor. You probably have your favorite Arduino-compatible ([like the Metro M4](https://www.adafruit.com/product/3382)&nbsp;or the classic&nbsp;[Metro 328](https://www.adafruit.com/product/2488)) that comes with its own set of awesome peripherals and lots of libraries. But it doesn't have WiFi or BLE 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 it's using the latest TLS/SSL encryption (it has root certificates pre-burned in).

![](https://cdn-learn.adafruit.com/assets/assets/000/077/210/medium800/adafruit_products_4285_top_ORIG_2019_06.jpg?1560977609)

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. Send basic but powerful socket-based commands over 8MHz SPI for high speed data transfer. You can use any 3V or 5V Arduino, any chip from the ATmega328 and up (although the '328 will not be able to do very complex tasks or buffer a lot of data). It also works great with CircuitPython, a SAMD51/Cortex M4 minimum required since we need a bunch of RAM. All you need is the 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. You use a few control pins and the RXI and TXO pins to talk to the ESP32 when it's in BLE mode.

![](https://cdn-learn.adafruit.com/assets/assets/000/077/211/medium800/adafruit_products_4285_iso_ORIG_2019_06.jpg?1560977641)

We placed an ESP32 module on a shield with a separate 3.3V regulator, and a tri-state chip for MOSI so you can share the SPI bus with other shields. We also tossed on a micro SD card socket, you can use that to host or store data you get from the Internet. Arduinos based on the ATmega328 (like the UNO) cannot use both the WiFi module and SD library at the same time, they don't have enough RAM. Again, we recommend an M0 or M4 chipset for use with Arduino, M4 for CircuitPython!

![](https://cdn-learn.adafruit.com/assets/assets/000/077/212/medium800/adafruit_products_4285_kit_ORIG_2019_06.jpg?1560977668)

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](https://github.com/ladyada/Adafruit_CircuitPython_ESP32SPI). We also include some header so you can solder it in and plug right into your Arduino-compatible, but you can also pick up a set of stacking headers to stack above/below your board.

![](https://cdn-learn.adafruit.com/assets/assets/000/077/213/medium800/adafruit_products_4285-04.jpg?1560977724)

We've tested this with all our Metros and it should work just fine with them except the&nbsp;[Metro M4 Airlifts](https://www.adafruit.com/product/4000) (because they already have WiFi!). **For use in Arduino** , the '328 and '32u4 you can do basic connectivity and data transfer but they do not have a lot of RAM so we don't recommend them - use the Metro M0, M4 or similar, for best results!&nbsp; **For CircuitPython use** , a Metro M4 works best - the M0 series does not have enough RAM in CircuitPython.

[The firmware on board is a slight variant of the Arduino WiFiNINA core, which works great!](https://github.com/adafruit/nina-fw)&nbsp;At this time connection to Enterprise WiFi is not yet supported.

# Adafruit AirLift Shield - ESP32 WiFi Co-Processor

## Pinouts

![](https://cdn-learn.adafruit.com/assets/assets/000/077/228/medium800/adafruit_products_4285_top_ORIG_2019_06.jpg?1560980038)

There's a lot jam-packed into this shield! Let's take a look at what we've got going on.

## Power Pins
![](https://cdn-learn.adafruit.com/assets/assets/000/077/231/medium800/adafruit_products_4285-pwr.png?1560980420)

- **GND&nbsp;** - Common power/logic ground.
- **3V** &nbsp;- this is the output from the 3.3V regulator. The regulator can supply 500mA peak but half of that is drawn by the ESP32, and it's a fairly power-hungry chip.
- **5V** - This is the input to the regulator
- **IOr** - This is IORef, the IO voltage we will communicate with and is required.

## SPI Interface Pins
![](https://cdn-learn.adafruit.com/assets/assets/000/077/221/medium800/adafruit_products_4285-spi.png?1560979503)

Both ESP32 and SD card use SPI to send and receive data. These pins are labeled **CLK MISO MOSI** and have level shifting so you can use this shield with 3.3V or 5V microcontroller boards.

By default the 2x3 pin **ICSP** header on the right hand side is where the SPI signals are found.&nbsp;

## ESP32 Control Pins
 **Required Control Pins:**

- **BUSY&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, can be read by 3-5V logic. This pin&nbsp;_must_&nbsp;be connected.
- **RST** - 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. Level shifted so can be 3-5V logic

**Optional Control Pins:**

- **GPIO0** &nbsp;- this is the ESP32&nbsp; **GPIO0&nbsp;** pin, which is used to put it into bootloading mode. It is also used if you like when the ESP32 is acting as a server, to let you know data is ready for reading. IIt's not required for WiFi, but you'll need to connect it to use BLE mode. Solder the pad on the bottom of the shield to connect it.
- **RX&nbsp;** &&nbsp; **TX** - 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 shield to use these pins.

![adafruit_products_4285-esp.png](https://cdn-learn.adafruit.com/assets/assets/000/077/288/medium640/adafruit_products_4285-esp.png?1561125573)

## SD Card Interface
There's a lot of space available on this shield so we also stuck on a micro SD card holder, great for datalogging or storing data to transmit over WiFi.

In addition to the shared SPI pins, the **SD** (chip select) pin is also used. It can be re-assigned to any pin by cutting the trace underneath the board and rewiring. If the SD card is not used, the **SD** pin can be used for any other purpose

![adafruit_products_4285-sd.png](https://cdn-learn.adafruit.com/assets/assets/000/077/218/medium640/adafruit_products_4285-sd.png?1560979318)

## LEDs
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** ).

![adafruit_products_4285-led.png](https://cdn-learn.adafruit.com/assets/assets/000/077/216/medium640/adafruit_products_4285-led.png?1560979075)

## Prototyping Area
We have a big grid of prototyping holes and power rails if you want to make some custom circuitry!

![adafruit_products_4285-Proto.png](https://cdn-learn.adafruit.com/assets/assets/000/077/215/medium640/adafruit_products_4285-Proto.png?1560979022)

# Adafruit AirLift Shield - ESP32 WiFi Co-Processor

## Assembly

![](https://cdn-learn.adafruit.com/assets/assets/000/077/251/medium800/adafruit_products_4285-02.jpg?1561039961)

# Installing Standard Headers

The shield comes with 0.1" standard header. Standard header does not permit stacking but it is mechanically stronger and they're much less expensive too! If you want to stack a shield on top, do not perform this step as it is not possible to uninstall the headers once soldered in! Skip down to the bottom for the stacking tutorial

Break apart the 0.1" header into 6, 8 and/or 10-pin long pieces and slip the long ends into the headers of your Arduino.

![adafruit_products_DSC_3827.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/253/medium640/adafruit_products_DSC_3827.jpg?1561040103)

![adafruit_products_DSC_3829.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/254/medium640/adafruit_products_DSC_3829.jpg?1561040159)

Place the assembled shield on top of the header-ed Arduino so that all of the short parts of the header are sticking through the outer set of pads

![adafruit_products_DSC_3830.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/255/medium640/adafruit_products_DSC_3830.jpg?1561040202)

Solder each one of the pins into the shield to make a secure connection

![adafruit_products_DSC_3832_(1).jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/257/medium640/adafruit_products_DSC_3832_%281%29.jpg?1561040298)

![adafruit_products_DSC_3837_(1).jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/258/medium640/adafruit_products_DSC_3837_%281%29.jpg?1561041210)

![adafruit_products_DSC_3845.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/259/medium640/adafruit_products_DSC_3845.jpg?1561041503)

![adafruit_products_DSC_3862_(1).jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/261/medium640/adafruit_products_DSC_3862_%281%29.jpg?1561040594)

That's it! Now you can install the 2x3 header

![adafruit_products_DSC_3877.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/262/medium640/adafruit_products_DSC_3877.jpg?1561041557)

![adafruit_products_DSC_3886.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/263/medium640/adafruit_products_DSC_3886.jpg?1561041624)

Solder the 2x3 header so that it's pointing downwards

![adafruit_products_DSC_3878.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/264/medium640/adafruit_products_DSC_3878.jpg?1561042114)

![adafruit_products_DSC_3879_(1).jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/265/medium640/adafruit_products_DSC_3879_%281%29.jpg?1561040932)

![adafruit_products_DSC_3881.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/266/medium640/adafruit_products_DSC_3881.jpg?1561042038)

![adafruit_products_DSC_3885.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/267/medium640/adafruit_products_DSC_3885.jpg?1561042693)

## Stack Alert!

If you want to stack a shield on top of the WiFi Shield, you'll want to pick up some stacking headers and use those instead of the plain header shown here!

Wanna stack? This tutorial shows how to use the plain header to connect to an Arduino.&nbsp;[If you want to use stacking headers](https://www.adafruit.com/product/85 "Link: https://www.adafruit.com/product/85"), don't follow these steps!

![adafruit_products_85-00.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/268/medium640/adafruit_products_85-00.jpg?1561041201)

Start by sliding the 10 pin, 2 x 8 pin and 6-pin stacking headers into the outer rows of the shield from the top. Then flip the board over so its resting on the four headers. Pull on the legs if necessary to straighten them out.

![adafruit_products_DSC_3783.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/269/medium640/adafruit_products_DSC_3783.jpg?1561043248)

Tack one pin of each header, to get them set in place before more soldering. If the headers go crooked you can re-heat the one pin while re-positioning to straighten them up

![adafruit_products_DSC_3785.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/270/medium640/adafruit_products_DSC_3785.jpg?1561041265)

Once you've tacked and straightened all the headers, go back and solder the remaining pins for each header.

![adafruit_products_DSC_3787.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/271/medium640/adafruit_products_DSC_3787.jpg?1561043008)

![adafruit_products_DSC_3797.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/272/medium640/adafruit_products_DSC_3797.jpg?1561043286)

![adafruit_products_DSC_3813.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/273/medium640/adafruit_products_DSC_3813.jpg?1561043293)

![adafruit_products_DSC_3807_(1).jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/274/medium640/adafruit_products_DSC_3807_%281%29.jpg?1561043458)

Insert the 2x3 stacking header as shown.

![adafruit_products_DSC_3903.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/275/medium640/adafruit_products_DSC_3903.jpg?1561043500)

Solder into place.

![adafruit_products_DSC_3905.jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/276/medium640/adafruit_products_DSC_3905.jpg?1561043659)

![adafruit_products_DSC_3907_(1).jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/277/medium640/adafruit_products_DSC_3907_%281%29.jpg?1561043714)

![adafruit_products_DSC_3910_(1).jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/278/medium640/adafruit_products_DSC_3910_%281%29.jpg?1561043845)

![adafruit_products_DSC_3911_(1).jpg](https://cdn-learn.adafruit.com/assets/assets/000/077/279/medium640/adafruit_products_DSC_3911_%281%29.jpg?1561043850)

# Adafruit AirLift Shield - 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
To use the board's pins with the AirLift shield, copy the following lines into your code:

```python
esp32_cs = DigitalInOut(board.D10)
esp32_ready = DigitalInOut(board.D7)
esp32_reset = DigitalInOut(board.D5)
```

If you wish to use the GPIO0 pin on the ESP32 - solder the jumper on the back of the shield, highlighted below:

![](https://cdn-learn.adafruit.com/assets/assets/000/100/733/medium800/adafruit_products_4285-back-g0.png?1615838479)

Then, include the following code to use the pin:

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

## 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.D10)
esp32_ready = DigitalInOut(board.D7)
esp32_reset = DigitalInOut(board.D5)

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 Shield - ESP32 WiFi Co-Processor

## Internet Connect!

Once you have CircuitPython setup and libraries installed we can get your board connected to the Internet.&nbsp;

To get connected, you will need to start by creating a _secrets file_.

# What's a secrets file?

We expect people to share tons of projects as they build CircuitPython WiFi widgets. What we want to avoid is people accidentally sharing their passwords or secret tokens and API keys. So, we designed all our examples to use a **secrets.py** file, that is in your **CIRCUITPY** drive, to hold secret/private/custom data. That way you can share your main project without worrying about accidentally sharing private stuff.

Your **secrets.py** file should look like this:

```auto
# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it

secrets = {
    'ssid' : 'home ssid',
    'password' : 'my password',
    'timezone' : "America/New_York", # http://worldtimeapi.org/timezones
    'github_token' : 'fawfj23rakjnfawiefa',
    'hackaday_token' : 'h4xx0rs3kret',
    }

```

Inside is a Python dictionary named secrets with a line for each entry. Each entry has an entry name (say `'ssid'`) and then a colon to separate it from the entry key `'home ssid'` and finally a comma ,

At a minimum you'll need the `ssid` and `password` for your local WiFi setup. As you make projects you may need more tokens and keys, just add them one line at a time. See for example other tokens such as one for accessing github or the hackaday API. Other non-secret data like your timezone can also go here, just cause its called secrets doesn't mean you can't have general customization data in there!

For the correct time zone string, look at&nbsp;[http://worldtimeapi.org/timezones](http://worldtimeapi.org/timezones)&nbsp;and remember that if your city is not listed, look for a city in the same time zone, for example Boston, New York, Philadelphia, Washington DC, and Miami are all on the same time as New York.

Of course, don't share your **secrets.py** - keep that out of GitHub, Discord or other project-sharing sites.

# Connect to WiFi

OK now you have your secrets setup - you can connect to the Internet using the ESP32SPI and the Requests modules.

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).&nbsp; Our introduction guide has&nbsp;[a great page on how to install the library bundle](https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries)&nbsp;for both express and non-express boards.

Remember for non-express boards like the, you'll need to manually install the necessary libraries from the bundle:

- **adafruit\_bus\_device**
- **adafruit\_esp32\_spi**
- **adafruit\_requests**
- **neopixel**

**Before continuing make sure your board's lib folder or root filesystem has the above files copied over.**

Next[&nbsp;connect to the board's serial REPL](https://learn.adafruit.com/welcome-to-circuitpython/the-repl) so you are at the CircuitPython&nbsp; **\>\>\>** &nbsp;prompt.

Into your **lib** folder. Once that's done, load up the following example using Mu or your favorite editor:

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

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

Warning: 

Then go down to this line

`esp.connect_AP(b'MY_SSID_NAME', b'MY_SSID_PASSWORD')`

and change `MY_SSID_NAME` and `MY_SSID_PASSWORD` to your access point name and password, keeping them within the '' quotes. (This example doesn't use the secrets' file, but its also very stand-alone so if other things seem to not work you can always re-load this. You should get something like the following:

![](https://cdn-learn.adafruit.com/assets/assets/000/072/013/medium800/circuitpython_image.png?1551237163)

In order, the example code...

Initializes the ESP32 over SPI using the SPI port and 3 control pins:

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

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

Tells our `requests` library the type of socket we're using (socket type varies by connectivity type - we'll be using the `adafruit_esp32spi_socket` for this example). We'll also set the interface to an&nbsp;`esp` object. This is a little bit of a hack, but it lets us use `requests` like CPython does.

```auto
requests.set_socket(socket, esp)
```

Verifies 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:", [hex(i) for i in esp.MAC_address])
```

Performs a scan of all access points it can see and prints out the name and signal strength:

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

Connects to the AP we've defined here, then prints out the local IP address, attempts 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)

```auto
    print("Connecting to AP...")
esp.connect_AP(b'MY_SSID_NAME', b'MY_SSID_PASSWORD')
print("Connected to", str(esp.ssid, 'utf-8'), "\tRSSI:", esp.rssi)
print("My IP address is", esp.pretty_ip(esp.ip_address))
print("IP lookup adafruit.com: %s" % esp.pretty_ip(esp.get_host_by_name("adafruit.com")))
print("Ping google.com: %d ms" % esp.ping("google.com"))
  
```

OK now we're getting to the really interesting part. With a SAMD51 or other large-RAM (well, over 32 KB) device, we can do a lot of neat tricks. Like for example we can implement an interface a lot like [requests](http://docs.python-requests.org/en/master/) - which makes getting data _really really easy_

To read in all the text from a web URL call `requests.get` - you can pass in `https` URLs for SSL connectivity

```auto
TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html"
print("Fetching text from", TEXT_URL)
r = requests.get(TEXT_URL)
print('-'*40)
print(r.text)
print('-'*40)
r.close()
```

Or, if the data is in structured JSON, you can get the json pre-parsed into a Python dictionary that can be easily queried or traversed. (Again, only for nRF52840, M4 and other high-RAM boards)

```auto
JSON_URL = "http://api.coindesk.com/v1/bpi/currentprice/USD.json"
print("Fetching json from", JSON_URL)
r = requests.get(JSON_URL)
print('-'*40)
print(r.json())
print('-'*40)
r.close()
```

# Requests

We've written a [requests-like](https://requests.readthedocs.io/en/master/) library for web interfacing named&nbsp;[Adafruit\_CircuitPython\_Requests](https://github.com/adafruit/Adafruit_CircuitPython_Requests). This library allows you to send HTTP/1.1 requests without "crafting" them and provides helpful methods for parsing the response from the server.

Here's an example of using Requests to perform GET and POST requests to a server.

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

The code first sets up the ESP32SPI interface. Then, it initializes a `request` object using an ESP32 `socket` and the `esp` object.

```auto
import board
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests

# If you have an externally connected ESP32:
esp32_cs = DigitalInOut(board.D9)
esp32_ready = DigitalInOut(board.D10)
esp32_reset = DigitalInOut(board.D5)

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

print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(b'MY_SSID_NAME', b'MY_SSID_PASSWORD')
    except RuntimeError as e:
        print("could not connect to AP, retrying: ",e)
        continue
print("Connected to", str(esp.ssid, 'utf-8'), "\tRSSI:", esp.rssi)

# Initialize a requests object with a socket and esp32spi interface
requests.set_socket(socket, esp)
```

Make sure to set the ESP32 pinout to match your AirLift breakout's connection:

```auto
esp32_cs = DigitalInOut(board.D9)
esp32_ready = DigitalInOut(board.D10)
esp32_reset = DigitalInOut(board.D5)
```

## HTTP GET with Requests
The code makes a HTTP GET request to Adafruit's WiFi testing website -&nbsp;[http://wifitest.adafruit.com/testwifi/index.html](http://wifitest.adafruit.com/testwifi/index.html).

To do this, we'll pass the URL into&nbsp;`requests.get()`. We're also going to save the response&nbsp;_from_&nbsp;the server into a variable named&nbsp;`response`.

While we requested data from the server, we'd what the server responded with. Since we already saved the server's&nbsp;`response`, we can read it back. Luckily for us, **requests&nbsp;automatically decodes the server's response into human-readable text,** you can read it back by calling&nbsp;`response.text`.

Lastly, we'll perform a bit of cleanup by calling&nbsp;`response.close()`. This closes, deletes, and collect's the response's data.&nbsp;

```auto
    print("Fetching text from %s"%TEXT_URL)
response = requests.get(TEXT_URL)
print('-'*40)

print("Text Response: ", response.text)
print('-'*40)
response.close()
  
```

While some servers respond with text, some respond with json-formatted data consisting of attribute–value pairs.

**CircuitPython\_Requests can convert a JSON-formatted response from a server into a CPython `dict.` object.**

We can also fetch and parse&nbsp; **json** data. We'll send a HTTP get to a url we know returns a json-formatted response (instead of text data).&nbsp;

**Then, the code calls&nbsp;`response.json()` to convert the response to a CPython `dict`.&nbsp;**

```auto
    print("Fetching JSON data from %s"%JSON_GET_URL)
response = requests.get(JSON_GET_URL)
print('-'*40)

print("JSON Response: ", response.json())
print('-'*40)
response.close()
  
```

## HTTP POST with Requests
Requests can also **POST data to a server by calling the `requests.post` method, passing it a `data` value.**

```auto
data = '31F'
print("POSTing data to {0}: {1}".format(JSON_POST_URL, data))
response = requests.post(JSON_POST_URL, data=data)
print('-'*40)

json_resp = response.json()
# Parse out the 'data' key from json_resp dict.
print("Data received from server:", json_resp['data'])
print('-'*40)
response.close()
```

 **You can also post json-formatted data to a server by passing `json` data into the `requests.post` method.**

```auto
json_data = {"Date" : "July 25, 2019"}
print("POSTing data to {0}: {1}".format(JSON_POST_URL, json_data))
response = requests.post(JSON_POST_URL, json=json_data)
print('-'*40)

json_resp = response.json()
# Parse out the 'json' key from json_resp dict.
print("JSON Data received from server:", json_resp['json'])
print('-'*40)
response.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.

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

# WiFi Manager

That simpletest example works but its a little finicky - you need to constantly check WiFi status and have many loops to manage connections and disconnections. For more advanced uses, we recommend using the WiFiManager object. 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 the WiFi manager and also how to POST data with some extra headers:

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

You'll note here we use a secrets.py file to manage our SSID info. The wifimanager is given the ESP32 object, secrets and a neopixel for status indication.

Note, you'll need to add a some additional information to your secrets file so that the code can query the Adafruit IO API:

- `aio_username`
- `aio_key`

You can go to your adafruit.io View AIO Key link to get those two values and add them to the secrets file, which will now look something like this:

```auto
# This file is where you keep secret settings, passwords, and tokens!
# If you put them in the code you risk committing that info or sharing it

secrets = {
    'ssid' : '_your_ssid_',
    'password' : '_your_wifi_password_',
    'timezone' : "America/Los_Angeles", # http://worldtimeapi.org/timezones
    'aio_username' : '_your_aio_username_',
    'aio_key' : '_your_aio_key_',
    }
```

Next, **set up an Adafruit IO feed named `test`**

- If you do not know how to set up a feed, [follow this page and come back when you've set up a feed named `test`.](https://learn.adafruit.com/adafruit-io-basics-feeds/creating-a-feed)

We can then have a simple loop for posting data to Adafruit IO without having to deal with connecting or initializing the hardware!

Take a look at your **test** feed on Adafruit.io and you'll see the value increase each time the CircuitPython board posts data to it!

![](https://cdn-learn.adafruit.com/assets/assets/000/072/042/medium800/circuitpython_feedstest.jpg?1551303629)

# Adafruit AirLift Shield - 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 ESP32 Shield Wiring

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

## 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 AirLift Firmware](https://learn.adafruit.com/upgrading-esp32-firmware/upgrade-external-esp32-airlift-firmware-2)
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 Shield - ESP32 WiFi Co-Processor

## Arduino WiFi

You can use an AirLift with Arduino. Unlike CircuitPython, it will work with just about any Arduino board, even a classic Arduino UNO. However, if you want to use libraries like Adafruit IO Arduino, 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&nbsp; **Sketch-\>Include Library -\> Add .ZIP library...**

![](https://cdn-learn.adafruit.com/assets/assets/000/077/182/medium800/adafruit_products_image.png?1560964562)

And select the zip you just downloaded.

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

## Arduino Microcontroller Pin Definition

Next, you'll need to need to modify the pin definition above for the AirLift Shield. Replace the configuration in the sketch with the pinouts below:

```auto
#define SPIWIFI       SPI  // The SPI port
#define SPIWIFI_SS    10   // Chip select pin
#define ESP32_RESETN  5    // Reset pin
#define SPIWIFI_ACK   7    // a.k.a BUSY or READY pin
#define ESP32_GPIO0   6
```

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-5VDC 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 Example

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. The only change you'll want to make is at the&nbsp; **top** &nbsp;of the sketches, add:

```auto
#define SPIWIFI       SPI  // The SPI port
#define SPIWIFI_SS    10   // Chip select pin
#define ESP32_RESETN  5    // Reset pin
#define SPIWIFI_ACK   7    // a.k.a BUSY or READY pin
#define ESP32_GPIO0   6
```

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);`&nbsp;like so:

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

# Adafruit AirLift Shield - ESP32 WiFi Co-Processor

## Downloads

## Files
- [ESP32 WROOM32 Datasheet](https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32_datasheet_en.pdf)
- [EagleCAD files on GitHub](https://github.com/adafruit/Adafruit-Airlift-Shield-PCB)
- [Fritzing object in Adafruit Fritzing Library](https://github.com/adafruit/Fritzing-Library/blob/master/parts/Adafruit%20Airlift%20Shield.fzpz)

## Schematic
![](https://cdn-learn.adafruit.com/assets/assets/000/077/283/medium800/adafruit_products_schematic.png?1561074083)

## Fab Print
![](https://cdn-learn.adafruit.com/assets/assets/000/077/284/medium800/adafruit_products_fab_print.png?1561074095)


## Primary Products

### Adafruit AirLift Shield - ESP32 WiFi Co-Processor

[Adafruit AirLift Shield - ESP32 WiFi Co-Processor](https://www.adafruit.com/product/4285)
Give your Arduino project a _lift_ with the Adafruit AirLift Shield - a shield that lets you use the powerful ESP32 as a WiFi co-processor. You probably have your favorite Arduino-compatible ([like the Metro M4](https://www.adafruit.com/product/3382) or the classic <a...></a...>

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

## Related Guides

- [Networking in CircuitPython](https://learn.adafruit.com/networking-in-circuitpython.md)
- [MQTT in CircuitPython](https://learn.adafruit.com/mqtt-in-circuitpython.md)
- [Upgrading AirLift ESP32 Firmware](https://learn.adafruit.com/upgrading-esp32-firmware.md)
- [Adafruit AirLift Shield - ESP32 WiFi Co-Processor](https://learn.adafruit.com/adafruit-airlift-shield-esp32-wifi-co-processor.md)
- [Using the Adafruit Library with Fritzing](https://learn.adafruit.com/using-the-adafruit-library-with-fritzing.md)
- [Adafruit INA260 Current + Voltage + Power Sensor Breakout](https://learn.adafruit.com/adafruit-ina260-current-voltage-power-sensor-breakout.md)
- [Adafruit PCA9546 4-Channel STEMMA QT Multiplexer](https://learn.adafruit.com/adafruit-pca9546-4-channel-stemma-qt-multiplexer.md)
- [Adafruit SPI Flash SD Card](https://learn.adafruit.com/adafruit-spi-flash-sd-card.md)
- [Adafruit DPS310 Precision Barometric Pressure and Altitude Sensor](https://learn.adafruit.com/adafruit-dps310-precision-barometric-pressure-sensor.md)
- [Adafruit LM73100 Ideal Diode Breakout](https://learn.adafruit.com/adafruit-lm73100-ideal-diode-breakout.md)
- [PyPortal Weather Station](https://learn.adafruit.com/pyportal-weather-station.md)
- [Adafruit Music Maker Shield](https://learn.adafruit.com/adafruit-music-maker-shield-vs1053-mp3-wav-wave-ogg-vorbis-player.md)
- [OSHWA Project Display With Adafruit MagTag](https://learn.adafruit.com/oshwa-project-display-with-adafruit-magtag.md)
- [Build an ESP8266 Mobile Robot](https://learn.adafruit.com/build-an-esp8266-mobile-robot.md)
- [Adafruit LTC4311 I2C Extender / Active Terminator](https://learn.adafruit.com/adafruit-ltc4311-i2c-extender-active-terminator.md)
