How about a version that works over Bluetooth? You know, so you could like control it from your phone? Sure, we can do that. Here's a version of the code that let's you use the Adafruit Bluefruit LE Connect App to send text and color. Now, instead of pre-defined messages and colors, you can use the BLE Connect App to send them.


First, make sure you have these libraries copied over to the /lib directory on the board's CIRCUITPY drive following this guide page:

Make sure you have at least version 2.2.0 of the Adafruit Display Text library.


Here's the BLE version of the code. We'll talk about how to interact with it next.

This code uses a custom font file and a BMP file for the heart image. To get those as well as the code, click the Project Zip link in the embedded code listing below. This will download all the files you need at once.

In addition to the code, be sure to copy the Multicolore_36.bdf and heart_bw.bmp file to you CIRCUITPY folder.

# SPDX-FileCopyrightText: 2020 Carter Nelson for Adafruit Industries
# SPDX-License-Identifier: MIT

# Display stuff
import displayio
import adafruit_imageload
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text import label
from adafruit_gizmo import tft_gizmo
# BLE stuff
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from import UARTService
from adafruit_bluefruit_connect.packet import Packet
from adafruit_bluefruit_connect.color_packet import ColorPacket

#---| User Config |--------------------------------------------------
BLE_NAME = "Candy Heart"
#---| User Config |--------------------------------------------------

# Setup BLE radio and service
ble = BLERadio()
uart = UARTService()
advertisement = ProvideServicesAdvertisement(uart) = BLE_NAME #pylint: disable=protected-access

# Create the TFT Gizmo display
display = tft_gizmo.TFT_Gizmo()

# Load the candy heart BMP
bitmap, palette = adafruit_imageload.load("/images/heart_bw.bmp",

heart = displayio.TileGrid(bitmap, pixel_shader=palette)

# Set up message text
font = bitmap_font.load_font("/fonts/Multicolore_36.bdf")
line1 = label.Label(font, text="?"*LINE1_MAX)
line2 = label.Label(font, text="?"*LINE2_MAX)
line1.anchor_point = (0.5, 0)    # middle top
line2.anchor_point = (0.5, 1.0)  # middle bottom
line1.anchored_position = (120, 85)
line2.anchored_position = (120, 175)
line1.color = line2.color = MESSAGE_COLOR

# Set up group and add to display
group = displayio.Group()
display.root_group = group

def update_heart(message, heart_color):
    # turn off auto refresh while we change some things
    display.auto_refresh = False
    # set message text
    text1, _, text2 = message.partition(MESSAGE_DELIMITER)
    line1.text = text1[:LINE1_MAX] if len(text1) > LINE1_MAX else text1
    line2.text = text1[:LINE2_MAX] if len(text2) > LINE2_MAX else text2
    # update location for new text bounds
    line1.anchored_position = (120, 85)
    line2.anchored_position = (120, 175)
    # set heart color
    palette[1] = heart_color
    # OK, now turn auto refresh back on to display
    display.auto_refresh = True

# Initial update
text = "TEXT,ME"
color = 0x00FFFF
update_heart(text, color)

# Loop forever
while True:
    # advertise and wait for connection
    while not ble.connected:

    # connected

    # receive and handle BLE traffic
    while ble.connected:
        if uart.in_waiting:
            raw_bytes =
            if raw_bytes[0] == ord('!'):
            # BLE Connect Control Packet
                packet = Packet.from_bytes(raw_bytes)
                if isinstance(packet, ColorPacket):
                    print("color = ", color)
                    color = packet.color
            # Just plain text
                text = raw_bytes.decode("utf-8").strip()
                print("text = ", text)
            update_heart(text, color)

    # disconnected
Be sure you click the "Download Project Zip" link to get all the files and not just the code. You'll get the heart bitmap and the font file too.

Bonus CLUE Versions

The Adafruit CLUE uses the same TFT display as the Gizmo. This makes it pretty easy to adapt the code for use on the CLUE. You'll find CLUE versions of the code in the project zip. Looks for the two files that names start with clue.

This guide was first published on Feb 09, 2020. It was last updated on Jul 19, 2024.

This page (BLE Code) was last updated on Jul 19, 2024.

Text editor powered by tinymce.