Connect to WiFi
OK, now that you have your 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:

Update to CircuitPython 9.2.x or later to use this example.
# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT from os import getenv import board import busio from digitalio import DigitalInOut import adafruit_connection_manager import adafruit_requests from adafruit_esp32spi import adafruit_esp32spi # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD ssid = getenv("CIRCUITPY_WIFI_SSID") password = getenv("CIRCUITPY_WIFI_PASSWORD") print("ESP32 SPI webclient test") TEXT_URL = "http://wifitest.adafruit.com/testwifi/index.html" JSON_URL = "http://wifitest.adafruit.com/testwifi/sample.json" # If you are using a board with pre-defined ESP32 Pins: esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) # If you have an AirLift Shield: # esp32_cs = DigitalInOut(board.D10) # esp32_ready = DigitalInOut(board.D7) # esp32_reset = DigitalInOut(board.D5) # If you have an AirLift Featherwing or ItsyBitsy Airlift: # esp32_cs = DigitalInOut(board.D13) # esp32_ready = DigitalInOut(board.D11) # esp32_reset = DigitalInOut(board.D12) # If you have an externally connected ESP32: # NOTE: You may need to change the pins to reflect your wiring # esp32_cs = DigitalInOut(board.D9) # esp32_ready = DigitalInOut(board.D10) # esp32_reset = DigitalInOut(board.D5) # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) 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) 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)) for ap in esp.scan_networks(): print("\t%-23s RSSI: %d" % (ap.ssid, ap.rssi)) 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")) ) print("Ping google.com: %d ms" % esp.ping("google.com")) # esp._debug = True print("Fetching text from", TEXT_URL) r = requests.get(TEXT_URL) print("-" * 40) print(r.text) print("-" * 40) r.close() print() print("Fetching json from", JSON_URL) r = requests.get(JSON_URL) print("-" * 40) print(r.json()) print("-" * 40) r.close() print("Done!")
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.
>>> 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:
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.
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
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.
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.)
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. It is a lot like the regular Python library named requests. 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.
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.
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 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.
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT import os import adafruit_connection_manager import board import busio from adafruit_esp32spi import adafruit_esp32spi from digitalio import DigitalInOut import adafruit_requests # Get WiFi details, ensure these are setup in settings.toml ssid = os.getenv("CIRCUITPY_WIFI_SSID") password = os.getenv("CIRCUITPY_WIFI_PASSWORD") # If you are using a board with pre-defined ESP32 Pins: esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) # If you have an externally connected ESP32: # esp32_cs = DigitalInOut(board.D9) # esp32_ready = DigitalInOut(board.D10) # esp32_reset = DigitalInOut(board.D5) # If you have an AirLift Featherwing or ItsyBitsy Airlift: # esp32_cs = DigitalInOut(board.D13) # esp32_ready = DigitalInOut(board.D11) # esp32_reset = DigitalInOut(board.D12) spi = busio.SPI(board.SCK, board.MOSI, board.MISO) radio = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) print("Connecting to AP...") while not radio.is_connected: try: radio.connect_AP(ssid, password) except RuntimeError as e: print("could not connect to AP, retrying: ", e) continue print("Connected to", str(radio.ap_info.ssid, "utf-8"), "\tRSSI:", radio.ap_info.rssi) # Initialize a requests session pool = adafruit_connection_manager.get_radio_socketpool(radio) ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio) requests = adafruit_requests.Session(pool, ssl_context) JSON_GET_URL = "https://httpbin.org/get" # Define a custom header as a dict. headers = {"user-agent": "blinka/1.0.0"} print("Fetching JSON data from %s..." % JSON_GET_URL) with requests.get(JSON_GET_URL, headers=headers) as response: print("-" * 60) json_data = response.json() headers = json_data["headers"] print("Response's Custom User-Agent Header: {0}".format(headers["User-Agent"])) print("-" * 60) # Read Response's HTTP status code print("Response HTTP Status Code: ", response.status_code) print("-" * 60)
Your CIRCUITPY drive should now look similar to the following image:

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.
# SPDX-FileCopyrightText: 2019 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT import time from os import getenv import board import busio from digitalio import DigitalInOut import neopixel import rtc from adafruit_esp32spi import adafruit_esp32spi from adafruit_esp32spi.adafruit_esp32spi_wifimanager import WiFiManager # Get wifi details and more from a settings.toml file # tokens used by this Demo: CIRCUITPY_WIFI_SSID, CIRCUITPY_WIFI_PASSWORD ssid = getenv("CIRCUITPY_WIFI_SSID") password = getenv("CIRCUITPY_WIFI_PASSWORD") print("ESP32 local time") TIME_API = "http://worldtimeapi.org/api/ip" # If you are using a board with pre-defined ESP32 Pins: esp32_cs = DigitalInOut(board.ESP_CS) esp32_ready = DigitalInOut(board.ESP_BUSY) esp32_reset = DigitalInOut(board.ESP_RESET) # If you have an externally connected ESP32: # esp32_cs = DigitalInOut(board.D9) # esp32_ready = DigitalInOut(board.D10) # esp32_reset = DigitalInOut(board.D5) # Secondary (SCK1) SPI used to connect to WiFi board on Arduino Nano Connect RP2040 if "SCK1" in dir(board): spi = busio.SPI(board.SCK1, board.MOSI1, board.MISO1) else: spi = busio.SPI(board.SCK, board.MOSI, board.MISO) esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset) """Use below for Most Boards""" status_pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2) """Uncomment below for ItsyBitsy M4""" # status_pixel = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2) """Uncomment below for an externally defined RGB LED (including Arduino Nano Connect)""" # import adafruit_rgbled # from adafruit_esp32spi import PWMOut # RED_LED = PWMOut.PWMOut(esp, 26) # GREEN_LED = PWMOut.PWMOut(esp, 27) # BLUE_LED = PWMOut.PWMOut(esp, 25) # status_pixel = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED) wifi = WiFiManager(esp, ssid, password, status_pixel=status_pixel) the_rtc = rtc.RTC() response = None while True: try: print("Fetching json from", TIME_API) response = wifi.get(TIME_API) break except OSError as e: print("Failed to get data, retrying\n", e) continue json = response.json() current_time = json["datetime"] the_date, the_time = current_time.split("T") year, month, mday = [int(x) for x in the_date.split("-")] the_time = the_time.split(".")[0] hours, minutes, seconds = [int(x) for x in the_time.split(":")] # We can also fill in these extra nice things year_day = json["day_of_year"] week_day = json["day_of_week"] is_dst = json["dst"] now = time.struct_time( (year, month, mday, hours, minutes, seconds, week_day, year_day, is_dst) ) print(now) the_rtc.datetime = now while True: print(time.localtime()) time.sleep(1)
Further Information
For more information on the basics of doing networking in CircuitPython, see this guide:
Page last edited
Text editor powered by tinymce.