This guide is obsolete. See our guides for AirLift for current WiFi co-processor hardware and software:

One of the powers of Python is the built-in data parsing capabilities. Stuff that's really hard in C, like json parsing, comes with the larger builds of CircuitPython, making it really easy to get IoT projects going.

For example, we can connect to internet API's and parse out the data we want very fast.

In this demo, we'll use the coinbase API for the current Bitcoin pricing. This is one of the few API's we found that doesn't require a key, so it's very fast to test and use.

You can check the output by visiting and seeing the output, which will look something like

{"time":{"updated":"Dec 16, 2018 22:43:00 UTC","updatedISO":"2018-12-16T22:43:00+00:00","updateduk":"Dec 16, 2018 at 22:43 GMT"},"disclaimer":"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from","chartName":"Bitcoin","bpi":{"USD":{"code":"USD","symbol":"$","rate":"3,227.6983","description":"United States Dollar","rate_float":3227.6983},"GBP":{"code":"GBP","symbol":"£","rate":"2,561.0302","description":"British Pound Sterling","rate_float":2561.0302},"EUR":{"code":"EUR","symbol":"€","rate":"2,855.5609","description":"Euro","rate_float":2855.5609}}}

You can explore this data to see exactly where the info you want is, using tools like (there's plenty of these kinds of sites, just search for a 'json viewer' or 'json explorer')

After pasting in the JSON data

You can navigate through it.

So for example, the USD conversion data is in bpi->USB->rate_float

In our code, once we get the URL data response, we can parse it and extract that entry with bitcoin = json["bpi"]["USD"]["rate_float"]

Here's the full example. Note we use a try block for json parsing in case the data comes back to us weird or its somehow not valid json data.

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

This example will access an API, grab a number like hackaday skulls, github
stars, price of bitcoin, twitter followers... if you can find something that
spits out JSON data, we can display it!
import gc
import time
import board
import busio
from digitalio import DigitalInOut
from digitalio import Direction
import neopixel
from adafruit_ht16k33 import segments
import adafruit_requests as requests
import adafruit_espatcontrol.adafruit_espatcontrol_socket as socket
from adafruit_espatcontrol import adafruit_espatcontrol

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

#              CONFIGURATION
TIME_BETWEEN_QUERY = 60  # in seconds

# Some data sources and JSON locations to try out

# Bitcoin value in USD
DATA_LOCATION = ["bpi", "USD", "rate_float"]

# Github stars! You can query 1ce a minute without an API key token
# if 'github_token' in secrets:
#    DATA_SOURCE += "?access_token="+secrets['github_token']
# DATA_LOCATION = ["stargazers_count"]

# Youtube stats
# CHANNEL_ID = "UCpOlOeQjj7EsVnDh3zuCgsA" # this isn't a secret but you have to look it up
# DATA_SOURCE = "" \
#              + CHANNEL_ID +"&key="+secrets['youtube_token']
# try also 'viewCount' or 'videoCount
# DATA_LOCATION = ["items", 0, "statistics", "subscriberCount"]

# Subreddit subscribers
# DATA_LOCATION = ["data", "subscribers"]

# Hackaday Skulls (likes), requires an API key
# DATA_SOURCE = ""+secrets['hackaday_token']
# DATA_LOCATION = ["skulls"]

# Twitter followers
# DATA_SOURCE = "" + \
# "screen_names=adafruit"
# DATA_LOCATION = [0, "followers_count"]

# Debug Level
# Change the Debug Flag if you have issues with AT commands
debugflag = False

if board.board_id == "challenger_rp2040_wifi":
    RX = board.ESP_RX
    TX = board.ESP_TX
    resetpin = DigitalInOut(board.WIFI_RESET)
    rtspin = False
    uart = busio.UART(TX, RX, baudrate=11520, receiver_buffer_size=2048)
    esp_boot = DigitalInOut(board.WIFI_MODE)
    esp_boot.direction = Direction.OUTPUT
    esp_boot.value = True
    status_light = None
    pixel_pin = board.NEOPIXEL
    num_pixels = 1
    pixel_type = "RGBW/GRBW"
    RX = board.ESP_TX
    TX = board.ESP_RX
    resetpin = DigitalInOut(board.ESP_WIFI_EN)
    rtspin = DigitalInOut(board.ESP_CTS)
    uart = busio.UART(TX, RX, timeout=0.1)
    esp_boot = DigitalInOut(board.ESP_BOOT_MODE)
    esp_boot.direction = Direction.OUTPUT
    esp_boot.value = True
    status_light = None
    pixel_pin = board.A1
    num_pixels = 16
    pixel_type = "RGB/GRB"

# Create the connection to the co-processor and reset
esp = adafruit_espatcontrol.ESP_ATcontrol(
    uart, 115200, run_baudrate=921600, reset_pin=resetpin, rts_pin=rtspin, debug=False

requests.set_socket(socket, esp)
# display
    # Create the I2C interface.
    i2c = busio.I2C(board.SCL, board.SDA)
    # Attach a 7 segment display and display -'s so we know its not live yet
    display = segments.Seg7x4(i2c)

# neopixels
    pixels = neopixel.NeoPixel(
        pixel_pin, num_pixels, brightness=0.4, pixel_order=(1, 0, 2, 3)

# music!
    import audioio

    wave_file = open("coin.wav", "rb")  # pylint: disable=consider-using-with
    wave = audioio.WaveFile(wave_file)

# we'll save the value in question
last_value = value = None
the_time = None
times = 0

def chime_light():
    """Light up LEDs and play a tune"""
        for i in range(0, 100, 10):
            if pixel_type == "RGB/GRB":
                pixels.fill((i, i, i))
            elif pixel_type == "RGBW/GRBW":
                pixels.fill((i, i, i, i))
        with audioio.AudioOut(board.A0) as audio:
            while audio.playing:
        for i in range(100, 0, -10):
            if pixel_type == "RGB/GRB":
                pixels.fill((i, i, i))
            elif pixel_type == "RGBW/GRBW":
                pixels.fill((i, i, i, i))

while True:
        while not esp.is_connected:
            # secrets dictionary must contain 'ssid' and 'password' at a minimum

        the_time = esp.sntp_time

        # great, lets get the data
        print("Retrieving data source...", end="")
        r = requests.get(DATA_SOURCE)
        print("Reply is OK!")
    except (ValueError, RuntimeError, adafruit_espatcontrol.OKError) as e:
        print("Failed to get data, retrying\n", e)
    # print('-'*40,)
    # print("Headers: ", r.headers)
    # print("Text:", r.text)
    # print('-'*40)

    value = r.json()
    for x in DATA_LOCATION:
        value = value[x]
    if not value:
    print("Times:{0}. The Time:{1}. Value: {2}".format(times, the_time, value))
        print("INT Value:{0}".format(int(value)))

    if last_value != value:
        chime_light()  # animate the neopixels
        last_value = value
    times += 1

    # normally we wouldn't have to do this, but we get bad fragments
    r = value = None
    print("GC MEM:{0}".format(gc.mem_free()))  # pylint: disable=no-member
    print("Sleeping for: {0} Seconds".format(TIME_BETWEEN_QUERY))

To display it, we use a 7-segment display hooked up to the I2C port, such as this one:

What's better than a single LED? Lots of LEDs! A fun way to make a small display is to use an 8x8 matrix or a
Out of Stock

Or the all-in-one FeatherWing:

One segment? No way dude! 7-Segments for life!This is the Green Adafruit 0.56" 4-Digit 7-Segment Display w/ FeatherWing Combo Pack! We also have these...
In Stock

This guide was first published on Dec 16, 2018. It was last updated on Dec 16, 2018.

This page (AT: Bitcoin Price Demo) was last updated on Nov 29, 2021.

Text editor powered by tinymce.