This project's code utilizes the Azure IoT Library which currently does not work with AirLift hardware, such as the Adafruit PyPortal. As a result, this project does not currently work (but may in the future).

For a more updated guide using CircuitPython and Microsoft Azure IoT, visit

Add CircuitPython Code and Project Assets

In the embedded code element below, click on the Download Project Bundle button, and save the .zip archive file to your computer.

Then, uncompress the .zip file, it will unpack to a folder named PyPortal_Azure_Plant_Monitor.

Copy the contents of the PyPortal_Azure_Plant_Monitor directory to your PyPortal's CIRCUITPY drive.

# SPDX-FileCopyrightText: 2019 Brent Rubell for Adafruit Industries
# SPDX-FileCopyrightText: 2020 Jim Bennett for Adafruit Industries
# SPDX-License-Identifier: MIT

PyPortal Azure IoT Plant Monitor
Log plant vitals to Microsoft Azure IoT Central with
your PyPortal

Authors: Brent Rubell for Adafruit Industries, 2019
       : Jim Bennett for Microsoft, 2020
import time
import json
import board
import busio
from digitalio import DigitalInOut
from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
import neopixel
import rtc
from adafruit_azureiot import IoTCentralDevice
from adafruit_seesaw.seesaw import Seesaw

# gfx helper
import azure_gfx_helper

# init. graphics helper
gfx = azure_gfx_helper.Azure_GFX(is_celsius=True)

# Get wifi details and more from a file
    from secrets import secrets
except ImportError:
    print("WiFi secrets are kept in, please add them there!")

# PyPortal ESP32 Setup
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)

# Set up the WiFi manager with a status light to show the WiFi connection status
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
print("WiFi connecting...")
print("WiFi connected!")

# Time setup, needed to authenticate with Azure IoT Central
# get_time will raise ValueError if the time isn't available yet so loop until
# it works.
now_utc = None
while now_utc is None:
        now_utc = time.localtime(esp.get_time()[0])
    except ValueError:
rtc.RTC().datetime = now_utc

# Soil Sensor Setup
i2c_bus = busio.I2C(board.SCL, board.SDA)
ss = Seesaw(i2c_bus, addr=0x36)

# Create an instance of the Azure IoT Central device
device = IoTCentralDevice(
    socket, esp, secrets["id_scope"], secrets["device_id"], secrets["key"]

# Connect to Azure IoT Central

# Hide the splash screen and show the telemetry values

while True:
        # read moisture level
        moisture_level = ss.moisture_read()
        # read temperature
        temperature = ss.get_temp()
        # display soil sensor values on pyportal

        print("Sending data to Azure")
        gfx.display_azure_status("Sending data...")

        # send the temperature and moisture level to Azure
        message = {"Temperature": temperature, "MoistureLevel": moisture_level}

        gfx.display_azure_status("Data sent!")
        print("Data sent!")
    except (ValueError, RuntimeError, ConnectionError, OSError) as e:
        print("Failed to get data, retrying\n", e)

    # Sleep for 10 minutes before getting the next value

This is what the final contents of the CIRCUITPY drive will look like:


First make sure you are running the latest version of Adafruit CircuitPython for your board.

Before continuing make sure your board's lib folder has the following files and folders copied over.

  • adafruit_azureiot
  • adafruit_binascii
  • adafruit_bitmap_font
  • adafruit_bus_device
  • adafruit_display_text
  • adafruit_esp32spi
  • adafruit_logging
  • adafruit_minimqtt
  • adafruit_ntp
  • adafruit_requests
  • adafruit_seesaw
  • neopixel

Install an editor

This guide requires you to edit and interact with CircuitPython code. While you can use any text editor of your choosing, two recommended editors are Visual Studio Code and Mu.

Visual Studio Code is a free, open source code editor with a huge range of extensions to support multiple languages and technologies. It runs on Windows, MacOS, and Linux.

After installing Visual Studio Code, you will need to install the Python extension if you want intellisense and code completion. You can read about this in the the Python in Visual Studio Code documentation.

Mu is a simple code editor that works with the Adafruit CircuitPython boards. It's written in Python and works on Windows, MacOS, Linux and Raspberry Pi. The serial console is built right in, so you get immediate feedback from your board's serial output!

Secrets File Setup

First, use Visual Studio Code or Mu to open up a file on your CIRCUITPY drive. Next, you're going to edit the file to enter your local WiFi credentials along with data about your Azure IoT Central Device.

Make the following changes to the code below in the file:

  • ReplaceMY_WIFI_SSID with the name of your WiFi SSID
  • ReplaceMY_WIFI_PASSWORD with your WiFi's password
  • ReplaceMY_AZURE_IOT_CENTRAL_ID_SCOPE with the ID Scope of your Azure IoT Central device from the connection dialog.
  • ReplaceMY_AZURE_IOT_CENTRAL_DECVICE_IDwith the Device ID of your Azure IoT Central device from the connection dialog.
  • Replace MY_AZURE_IOT_CENTRAL_PRIMAEY_KEY with the Primary Key of your Azure IoT Central device from the connection dialog.
# 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' : 'MY_WIFI_SSID',
    'password' : 'MY_WIFI_PASSWORD',
    'id_scope' : 'MY_AZURE_IOT_CENTRAL_ID_SCOPE',
    'device_id' : 'MY_AZURE_IOT_CENTRAL_DEVICE_ID',

You can then close, saving the updated file onto the device.


Setting up the PyPortal with the Azure IoT Central is finished! You do not need to repeat this process again unless you change your IoT Central device.

This guide was first published on May 24, 2019. It was last updated on Jun 13, 2024.

This page (Code Setup ) was last updated on Jun 13, 2024.

Text editor powered by tinymce.