Here is the code from a couple of the examples that are included with the library. To run the examples, you will need to have your FunHouse set up with CircuitPython and a secrets.py file created. You can find detailed instructions in the Adafruit FunHouse guide.

Simple Test

This example uses of the top level FunHouse layer and makes use of the graphics and peripherals. The focus of this example is the usage of the attached peripherals. The code starts out with a few imports.

import board
from digitalio import DigitalInOut, Direction, Pull
from adafruit_funhouse import FunHouse

After that, the FunHouse library is initialized with a couple of parameters. The DotStars could have been supplied for status, but then we wouldn't have the DotStar available for programmatic use. You could also provide an external NeoPixel, DotStar or RGB LED.

The parameters given were the default background color to use and the scale so everything can automatically scale up.

funhouse = FunHouse(
    default_bg=0x0F0F00,
    scale=2,
)
I2C is initialized inside the peripherals layer in order to make use of the environmental sensors. To use I2C for the STEMMA QT port, you can access the I2C object at funhouse.peripherals.i2c.

Next up is a convenience function to allow setting all the DotStar LED colors in a single line.

funhouse.peripherals.set_dotstars(0x800000, 0x808000, 0x008000, 0x000080, 0x800080)

After that is the external sensor setup for ports A0 through A2. This sets them to be digital inputs using digitalio, but analogio could have been used as well.

# sensor setup
sensors = []
for p in (board.A0, board.A1, board.A2):
    sensor = DigitalInOut(p)
    sensor.direction = Direction.INPUT
    sensor.pull = Pull.DOWN
    sensors.append(sensor)

Here's a function to set the color of a specific label index to an on or off color depending on the conditional value. This makes the code much shorter and easier to read.

def set_label_color(conditional, index, on_color):
    if conditional:
        funhouse.set_text_color(on_color, index)
    else:
        funhouse.set_text_color(0x606060, index)

The following section creates all the labels and stores the index of the labels in variables. This will make accessing specific labels very easy further down in the program. A new parameter that was recently added is the ability to set the initial text of the label, but that comes at a cost. The library will attempt to draw each label as the value is filled in and this has the appearance of if sluggishly initializing. To get around that, we called the show() method of the funhouse.display object.

By passing None as the value, this informs displayio to not show any layers. At the end, passing funhouse.splash, which is the layer that everything is drawn to, causes displayio to draw all the newly created labels at the same time.

# Create the labels
funhouse.display.show(None)
slider_label = funhouse.add_text(
    text="Slider:", text_position=(50, 30), text_color=0x606060
)
capright_label = funhouse.add_text(
    text="Touch", text_position=(85, 10), text_color=0x606060
)
pir_label = funhouse.add_text(text="PIR", text_position=(60, 10), text_color=0x606060)
capleft_label = funhouse.add_text(
    text="Touch", text_position=(25, 10), text_color=0x606060
)
onoff_label = funhouse.add_text(text="OFF", text_position=(10, 25), text_color=0x606060)
up_label = funhouse.add_text(text="UP", text_position=(10, 10), text_color=0x606060)
sel_label = funhouse.add_text(text="SEL", text_position=(10, 60), text_color=0x606060)
down_label = funhouse.add_text(
    text="DOWN", text_position=(10, 100), text_color=0x606060
)
jst1_label = funhouse.add_text(
    text="SENSOR 1", text_position=(40, 80), text_color=0x606060
)
jst2_label = funhouse.add_text(
    text="SENSOR 2", text_position=(40, 95), text_color=0x606060
)
jst3_label = funhouse.add_text(
    text="SENSOR 3", text_position=(40, 110), text_color=0x606060
)
temp_label = funhouse.add_text(
    text="Temp:", text_position=(50, 45), text_color=0xFF00FF
)
pres_label = funhouse.add_text(
    text="Pres:", text_position=(50, 60), text_color=0xFF00FF
)
funhouse.display.show(funhouse.splash)

Finally, is the main loop. We'll break this down into a couple of different sections.

First calling the funhouse.set_text() function will set the text. You can just pass in the indices that were stored a bit earlier to make it easy to read. This changes the labels for a couple of the environmental sensors and also prints out some values to the console output.

funhouse.set_text("Temp %0.1F" % funhouse.peripherals.temperature, temp_label)
funhouse.set_text("Pres %d" % funhouse.peripherals.pressure, pres_label)

print(funhouse.peripherals.temperature, funhouse.peripherals.relative_humidity)

In the next section, the set_label_color function that was defined above is used to highlight any sensors that are considered on or True.

There is also a section that reads the slider value, which is between 0-1.0 when touched and None if it is not touched. The slider value is used to set the brightness of the DotStar LEDs.

set_label_color(funhouse.peripherals.captouch6, onoff_label, 0x00FF00)
set_label_color(funhouse.peripherals.captouch7, capleft_label, 0x00FF00)
set_label_color(funhouse.peripherals.captouch8, capright_label, 0x00FF00)

slider = funhouse.peripherals.slider
if slider is not None:
    funhouse.peripherals.dotstars.brightness = slider
    funhouse.set_text("Slider: %1.1f" % slider, slider_label)
set_label_color(slider is not None, slider_label, 0xFFFF00)

set_label_color(funhouse.peripherals.button_up, up_label, 0xFF0000)
set_label_color(funhouse.peripherals.button_sel, sel_label, 0xFFFF00)
set_label_color(funhouse.peripherals.button_down, down_label, 0x00FF00)

set_label_color(funhouse.peripherals.pir_sensor, pir_label, 0xFF0000)
set_label_color(sensors[0].value, jst1_label, 0xFFFFFF)
set_label_color(sensors[1].value, jst2_label, 0xFFFFFF)
set_label_color(sensors[2].value, jst3_label, 0xFFFFFF)

Full Example Code

Go ahead and click Download Project Bundle to download the full example and the required libraries. Rename funhouse_simpletest.py to code.py and copy all the files over to your FunHouse to run the Simple Test example.

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2021 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
import board
from digitalio import DigitalInOut, Direction, Pull
from adafruit_funhouse import FunHouse

funhouse = FunHouse(
    default_bg=0x0F0F00,
    scale=2,
)

funhouse.peripherals.set_dotstars(0x800000, 0x808000, 0x008000, 0x000080, 0x800080)

# sensor setup
sensors = []
for p in (board.A0, board.A1, board.A2):
    sensor = DigitalInOut(p)
    sensor.direction = Direction.INPUT
    sensor.pull = Pull.DOWN
    sensors.append(sensor)


def set_label_color(conditional, index, on_color):
    if conditional:
        funhouse.set_text_color(on_color, index)
    else:
        funhouse.set_text_color(0x606060, index)


# Create the labels
funhouse.display.show(None)
slider_label = funhouse.add_text(
    text="Slider:", text_position=(50, 30), text_color=0x606060
)
capright_label = funhouse.add_text(
    text="Touch", text_position=(85, 10), text_color=0x606060
)
pir_label = funhouse.add_text(text="PIR", text_position=(60, 10), text_color=0x606060)
capleft_label = funhouse.add_text(
    text="Touch", text_position=(25, 10), text_color=0x606060
)
onoff_label = funhouse.add_text(text="OFF", text_position=(10, 25), text_color=0x606060)
up_label = funhouse.add_text(text="UP", text_position=(10, 10), text_color=0x606060)
sel_label = funhouse.add_text(text="SEL", text_position=(10, 60), text_color=0x606060)
down_label = funhouse.add_text(
    text="DOWN", text_position=(10, 100), text_color=0x606060
)
jst1_label = funhouse.add_text(
    text="SENSOR 1", text_position=(40, 80), text_color=0x606060
)
jst2_label = funhouse.add_text(
    text="SENSOR 2", text_position=(40, 95), text_color=0x606060
)
jst3_label = funhouse.add_text(
    text="SENSOR 3", text_position=(40, 110), text_color=0x606060
)
temp_label = funhouse.add_text(
    text="Temp:", text_position=(50, 45), text_color=0xFF00FF
)
pres_label = funhouse.add_text(
    text="Pres:", text_position=(50, 60), text_color=0xFF00FF
)
funhouse.display.show(funhouse.splash)

while True:
    funhouse.set_text("Temp %0.1F" % funhouse.peripherals.temperature, temp_label)
    funhouse.set_text("Pres %d" % funhouse.peripherals.pressure, pres_label)

    print(funhouse.peripherals.temperature, funhouse.peripherals.relative_humidity)
    set_label_color(funhouse.peripherals.captouch6, onoff_label, 0x00FF00)
    set_label_color(funhouse.peripherals.captouch7, capleft_label, 0x00FF00)
    set_label_color(funhouse.peripherals.captouch8, capright_label, 0x00FF00)

    slider = funhouse.peripherals.slider
    if slider is not None:
        funhouse.peripherals.dotstars.brightness = slider
        funhouse.set_text("Slider: %1.1f" % slider, slider_label)
    set_label_color(slider is not None, slider_label, 0xFFFF00)

    set_label_color(funhouse.peripherals.button_up, up_label, 0xFF0000)
    set_label_color(funhouse.peripherals.button_sel, sel_label, 0xFFFF00)
    set_label_color(funhouse.peripherals.button_down, down_label, 0x00FF00)

    set_label_color(funhouse.peripherals.pir_sensor, pir_label, 0xFF0000)
    set_label_color(sensors[0].value, jst1_label, 0xFFFFFF)
    set_label_color(sensors[1].value, jst2_label, 0xFFFFFF)
    set_label_color(sensors[2].value, jst3_label, 0xFFFFFF)

Once it is running, start touching the capacitive touch pads, buttons, and whatever else you can think of to see the example in action.

MQTT Example

The next example demonstrates how to use the new built-in MQTT functionality with Adafruit IO, though the MQTT functionality can be used with a standard MQTT server as well. To run this, make sure you have added your Adafruit IO information to your secrets.py file. If you're not sure how, you can check out this page in the Adafruit FunHouse guide.

This time for imports, there's just the top level FunHouse object and the time module.

import time
from adafruit_funhouse import FunHouse

For initializing the FunHouse library, by passing None as the default background, this causes displayio to keep the console up on the display.

funhouse = FunHouse(default_bg=None)
funhouse.peripherals.set_dotstars(0x800000, 0x808000, 0x008000, 0x000080, 0x800080)

Next up are the handler functions. These allow the script to tell the library what to do when certain events occur. The different events are the connect, disconnect, subscribe, unsubscribe, and message events. These are the events common to both the Mini MQTT library and the Adafruit IO MQTT library.

In the connect handler, it will subscribe to the buzzer and neopixel topics. You can change these to whatever suits you, but make sure the names match the feed IDs in the message handler.

Subscribing to a topic will cause the library to listen to the MQTT server for these topics and respond with the message handler whenever it hears something. The library will listen during the loop() function, which will be covered in more detail a little lower in the code. To read more about MQTT Topics, you can check out the MQTT Topics section of our All the Internet of Things Protocols guide.

def connected(client):
    print("Connected to Adafruit IO! Subscribing...")
    client.subscribe("buzzer")
    client.subscribe("neopixels")


def subscribe(client, userdata, topic, granted_qos):
    print("Subscribed to {0} with QOS level {1}".format(topic, granted_qos))


def disconnected(client):
    print("Disconnected from Adafruit IO!")


def message(client, feed_id, payload):
    print("Feed {0} received new value: {1}".format(feed_id, payload))
    if feed_id == "buzzer":
        if int(payload) == 1:
            funhouse.peripherals.play_tone(2000, 0.25)
    if feed_id == "neopixels":
        print(payload)
        color = int(payload[1:], 16)
        funhouse.peripherals.dotstars.fill(color)

The next section will initialize the MQTT library. If you are using Adafruit IO, you will want to call the init_io_mqtt(), otherwise you will want to call the init_mqtt() function. To work properly, one of the two functions must be called, which tells the library which underlying libraries to use.

The remaining lines assign the above handlers to their respective properties.

# Initialize a new MQTT Client object
funhouse.network.init_io_mqtt()
funhouse.network.on_mqtt_connect = connected
funhouse.network.on_mqtt_disconnect = disconnected
funhouse.network.on_mqtt_subscribe = subscribe
funhouse.network.on_mqtt_message = message

The next section will connect to the MQTT server. The library does not automatically connect, so you will need to do this. The reason it doesn't automatically connect is to give you the opportunity to set up whatever you want prior to this.

The next couple of lines set the initial state of the sensorwrite_timestamp and last_pir state variables. The reason the last_pir variable is set to None as opposed to the initial value of the PIR sensor is so that it will always publish it's state on connection regardless of the value.

print("Connecting to Adafruit IO...")
funhouse.network.mqtt_connect()
sensorwrite_timestamp = time.monotonic()
last_pir = None

The last block of code is the main loop. We'll break this up into sections as well. As part of the loop, the mqtt_loop() will get called during each iteration. This allows the MQTT library to respond appropriately to any messages. By default it has a 1 second timeout, but you can shorten that for your needs. This will make your script more responsive, but it may also fail to respond to all messages if the traffic is pretty busy.

Right after the loop, we read the temperature and barometric pressure and print that to the serial console.

funhouse.network.mqtt_loop()

print("Temp %0.1F" % funhouse.peripherals.temperature)
print("Pres %d" % funhouse.peripherals.pressure)

During the main loop, we check that 10 seconds has elapsed. If it has, then we publish the temperature, humidity, and pressure to their respective feeds on Adafruit IO.

We also check to see if the PIR sensor has either changed since the last time we checked or if we haven't checked at all. In either case, we publish the current value to its feed and update the last_pir variable.

# every 10 seconds, write temp/hum/press
if (time.monotonic() - sensorwrite_timestamp) > 10:
    funhouse.peripherals.led = True
    print("Sending data to adafruit IO!")
    funhouse.network.mqtt_publish("temperature", funhouse.peripherals.temperature)
    funhouse.network.mqtt_publish(
        "humidity", int(funhouse.peripherals.relative_humidity)
    )
    funhouse.network.mqtt_publish("pressure", int(funhouse.peripherals.pressure))
    sensorwrite_timestamp = time.monotonic()
    # Send PIR only if changed!
    if last_pir is None or last_pir != funhouse.peripherals.pir_sensor:
        last_pir = funhouse.peripherals.pir_sensor
        funhouse.network.mqtt_publish("pir", "%d" % last_pir)
    funhouse.peripherals.led = False

Full Code Example

Go ahead and click Download Project Bundle to download the full example and the required libraries. Rename funhouse_adafruit_io_mqtt.py to code.py and copy all the files over to your FunHouse to run the Simple Test example. Make sure your secrets.py file includes your Adafruit IO information.

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
# SPDX-FileCopyrightText: Copyright (c) 2021 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import time
from adafruit_funhouse import FunHouse

funhouse = FunHouse(default_bg=None)
funhouse.peripherals.set_dotstars(0x800000, 0x808000, 0x008000, 0x000080, 0x800080)

# pylint: disable=unused-argument
def connected(client):
    print("Connected to Adafruit IO! Subscribing...")
    client.subscribe("buzzer")
    client.subscribe("neopixels")


def subscribe(client, userdata, topic, granted_qos):
    print("Subscribed to {0} with QOS level {1}".format(topic, granted_qos))


def disconnected(client):
    print("Disconnected from Adafruit IO!")


def message(client, feed_id, payload):
    print("Feed {0} received new value: {1}".format(feed_id, payload))
    if feed_id == "buzzer":
        if int(payload) == 1:
            funhouse.peripherals.play_tone(2000, 0.25)
    if feed_id == "neopixels":
        print(payload)
        color = int(payload[1:], 16)
        funhouse.peripherals.dotstars.fill(color)


# pylint: enable=unused-argument

# Initialize a new MQTT Client object
funhouse.network.init_io_mqtt()
funhouse.network.on_mqtt_connect = connected
funhouse.network.on_mqtt_disconnect = disconnected
funhouse.network.on_mqtt_subscribe = subscribe
funhouse.network.on_mqtt_message = message

print("Connecting to Adafruit IO...")
funhouse.network.mqtt_connect()
sensorwrite_timestamp = time.monotonic()
last_pir = None

while True:
    funhouse.network.mqtt_loop()

    print("Temp %0.1F" % funhouse.peripherals.temperature)
    print("Pres %d" % funhouse.peripherals.pressure)

    # every 10 seconds, write temp/hum/press
    if (time.monotonic() - sensorwrite_timestamp) > 10:
        funhouse.peripherals.led = True
        print("Sending data to adafruit IO!")
        funhouse.network.mqtt_publish("temperature", funhouse.peripherals.temperature)
        funhouse.network.mqtt_publish(
            "humidity", int(funhouse.peripherals.relative_humidity)
        )
        funhouse.network.mqtt_publish("pressure", int(funhouse.peripherals.pressure))
        sensorwrite_timestamp = time.monotonic()
        # Send PIR only if changed!
        if last_pir is None or last_pir != funhouse.peripherals.pir_sensor:
            last_pir = funhouse.peripherals.pir_sensor
            funhouse.network.mqtt_publish("pir", "%d" % last_pir)
        funhouse.peripherals.led = False

Once it is running, you will notice it printing the temperature and pressure to the display. Every 10 seconds it should say Sending data to adafruit IO! If you log into Adafruit IO and create a couple of feeds called buzzer and neopixels, you can try out the subscribe functionality.

To get it to react, you add a 1 to the buzzer feed or add a color value such as #FF0000 for Red to the neopixels feed. You should hear a tone played for a brief period for the buzzer feed and you should see the DotStars all light up to the color value you provided.

This guide was first published on Apr 26, 2021. It was last updated on 2021-05-01 13:46:09 -0400.

This page (Basic Examples) was last updated on Nov 28, 2021.

Text editor powered by tinymce.