I have also added print statements to see where it's hanging, and it seems like it is hanging at any point in the example code.
I have also added WiFi connected adafruit.io examples to upload the co2, temp, and humidity measurements and also experience cases of random hangs (without errors) on the Cortex M4, yet the ESP32 co-processor remains responsive on the WiFi network to pings.
Both Matrix Portals are running the same Bootloader
Code: Select all
UF2 Bootloader v1.23.1-adafruit.1-328-gf06693a SFHWRO
Model: Matrix Portal M4
Board-ID: SAMD51J19A-MatrixPortal-v0
Code: Select all
Firmware vers. bytearray(b'1.2.2\x00')
ESP Firmware Version: bytearray(b'1.7.3\x00')
Code: Select all
Adafruit CircuitPython 6.0.0-rc.0 on 2020-10-16; Adafruit Matrix Portal M4 with samd51j19
Adafruit CircuitPython 6.0.0 on 2020-11-16; Adafruit Matrix Portal M4 with samd51j19
Adafruit CircuitPython 6.1.0 on 2021-01-21; Adafruit Matrix Portal M4 with samd51j19
Adafruit CircuitPython 6.2.0 on 2021-04-05; Adafruit Matrix Portal M4 with samd51j19
Adafruit CircuitPython 7.0.0-alpha.1-164-g01979acd4 on 2021-04-20; Adafruit Matrix Portal M4 with samd51j19
In addition to the code from the RGB Matrix Portal Room CO2 Monitor example, I have tried code with the addition of Adafruit IO uploads, using http and mqtt.
Matrix Portal 1 HTTP feed example
Code: Select all
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# adafruit_circuitpython_adafruitio usage with an esp32spi_socket
# Matrix Portal 001 Example http feed: co2, temp, rh
import time
from random import randint
import board
import displayio
import busio
from digitalio import DigitalInOut
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_requests as requests
from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError
import adafruit_imageload
from adafruit_matrixportal.matrix import Matrix
import adafruit_scd30
# --| User Config |----
CO2_CUTOFFS = (1000, 2000, 5000)
UPDATE_RATE = 10
# ---------------------
# the sensor
scd30 = adafruit_scd30.SCD30(board.I2C())
# optional if known (pick one)
# scd30.ambient_pressure = 1013.25
# scd30.altitude = 0
# the display
matrix = Matrix(width=64, height=32, bit_depth=6)
display = matrix.display
#display.rotation = 90 # matrixportal up
display.rotation = 270 # matrixportal down
# current condition smiley face
smileys_bmp, smileys_pal = adafruit_imageload.load("/bmps/smileys.bmp")
smiley = displayio.TileGrid(
smileys_bmp,
pixel_shader=smileys_pal,
x=0,
y=0,
width=1,
height=1,
tile_width=32,
tile_height=32,
)
# current condition label
tags_bmp, tags_pal = adafruit_imageload.load("/bmps/tags.bmp")
label = displayio.TileGrid(
tags_bmp,
pixel_shader=tags_pal,
x=0,
y=32,
width=1,
height=1,
tile_width=32,
tile_height=16,
)
# current CO2 value
digits_bmp, digits_pal = adafruit_imageload.load("/bmps/digits.bmp")
co2_value = displayio.TileGrid(
digits_bmp,
pixel_shader=digits_pal,
x=0,
y=51,
width=4,
height=1,
tile_width=8,
tile_height=10,
)
# put em all together
splash = displayio.Group()
splash.append(smiley)
splash.append(label)
splash.append(co2_value)
# and show em
display.show(splash)
def update_display(value):
value = abs(round(value))
# smiley and label
if value < CO2_CUTOFFS[0]:
smiley[0] = label[0] = 0
elif value < CO2_CUTOFFS[1]:
smiley[0] = label[0] = 1
elif value < CO2_CUTOFFS[2]:
smiley[0] = label[0] = 2
else:
smiley[0] = label[0] = 3
# CO2 value
# clear it
for i in range(4):
co2_value[i] = 10
# update it
i = 3
while value:
co2_value[i] = value % 10
value = int(value / 10)
i -= 1
# Add a secrets.py to your filesystem that has a dictionary called secrets with "ssid" and
# "password" keys with your WiFi credentials. DO NOT share that file or commit it into Git or other
# source control.
# pylint: disable=no-name-in-module,wrong-import-order
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise
# 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)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
print("Connecting to AP...")
while not esp.is_connected:
try:
esp.connect_AP(secrets["ssid"], secrets["password"])
except RuntimeError as e:
print("could not connect to AP, retrying: ", e)
continue
print("Connected to", str(esp.ssid, "utf-8"), "\tRSSI:", esp.rssi)
socket.set_interface(esp)
requests.set_socket(socket, esp)
# Set your Adafruit IO Username and Key in secrets.py
# (visit io.adafruit.com if you need to create an account,
# or if you need your Adafruit IO key.)
aio_username = secrets["aio_username"]
aio_key = secrets["aio_key"]
# Initialize an Adafruit IO HTTP API object
io = IO_HTTP(aio_username, aio_key, requests)
try:
# Get the 'co2' feed from Adafruit IO
co2_feed = io.get_feed("mp1-co2")
except AdafruitIO_RequestError:
# If no 'co2' feed exists, create one
co2_feed = io.create_new_feed("mp1-co2")
try:
# Get the 'temp' feed from Adafruit IO
temp_feed = io.get_feed("mp1-temp")
except AdafruitIO_RequestError:
# If no 'temp' feed exists, create one
temp_feed = io.create_new_feed("mp1-temp")
try:
# Get the 'rh' feed from Adafruit IO
rh_feed = io.get_feed("mp1-rh")
except AdafruitIO_RequestError:
# If no 'rh' feed exists, create one
rh_feed = io.create_new_feed("mp1-rh")
while True:
print("hello")
# print("Firmware vers.", esp.firmware_version)
# protect against NaNs and Nones
# try:
data_is_go = scd30.data_available
if data_is_go:
print("Data Available!")
co2_read = scd30.CO2
temp_read = scd30.temperature
rh_read = scd30.relative_humidity
print("Read Complete!")
temp_F = temp_read * 1.8 + 32
print("Sending {0} to display...".format(co2_read))
update_display(co2_read)
print("Display complete!")
print("Sending {0} to co2 feed...".format(co2_read))
io.send_data(co2_feed["key"], co2_read)
print("Sending {0} to temp feed...".format(temp_F))
io.send_data(temp_feed["key"], temp_F)
print("Sending {0} to rh feed...".format(rh_read))
io.send_data(rh_feed["key"], rh_read)
print("Data Sent!")
# except:
# pass
print("Waiting {0}...".format(UPDATE_RATE))
time.sleep(UPDATE_RATE)
Code: Select all
Connected to {WiFi Networks Name} RSSI: -31
hello
Firmware vers. bytearray(b'1.7.3\x00')
Data Available!
Read Complete!
Sending 477.056 to display...
Display complete!
Sending 477.056 to co2 feed...
Sending 71.1359 to temp feed...
Sending 34.0454 to rh feed...
Data Sent!
Waiting 10...
Code: Select all
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# Matrix Portal 002 Example mqtt feed: co2, temp, rh, and onoff message reads
import time
import board
import busio
from digitalio import DigitalInOut
import neopixel
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
import adafruit_minimqtt.adafruit_minimqtt as MQTT
import adafruit_scd30
import adafruit_imageload
import displayio
from adafruit_matrixportal.matrix import Matrix
# --| User Config |----
CO2_CUTOFFS = (1000, 2000, 5000)
UPDATE_RATE = 10
# ---------------------
# the sensor
scd30 = adafruit_scd30.SCD30(board.I2C())
# optional if known (pick one)
# scd30.ambient_pressure = 1013.25
# scd30.altitude = 0
# the display
matrix = Matrix(width=64, height=32, bit_depth=6)
display = matrix.display
# display.rotation = 90 # matrixportal up
display.rotation = 270 # matrixportal down
# current condition smiley face
smileys_bmp, smileys_pal = adafruit_imageload.load("/bmps/smileys.bmp")
smiley = displayio.TileGrid(
smileys_bmp,
pixel_shader=smileys_pal,
x=0,
y=0,
width=1,
height=1,
tile_width=32,
tile_height=32,
)
# current condition label
tags_bmp, tags_pal = adafruit_imageload.load("/bmps/tags.bmp")
label = displayio.TileGrid(
tags_bmp,
pixel_shader=tags_pal,
x=0,
y=32,
width=1,
height=1,
tile_width=32,
tile_height=16,
)
# current CO2 value
digits_bmp, digits_pal = adafruit_imageload.load("/bmps/digits.bmp")
co2_value = displayio.TileGrid(
digits_bmp,
pixel_shader=digits_pal,
x=0,
y=51,
width=4,
height=1,
tile_width=8,
tile_height=10,
)
# put em all together
splash = displayio.Group()
splash.append(smiley)
splash.append(label)
splash.append(co2_value)
# and show em
display.show(splash)
def update_display(value):
value = abs(round(value))
# smiley and label
if value < CO2_CUTOFFS[0]:
smiley[0] = label[0] = 0
elif value < CO2_CUTOFFS[1]:
smiley[0] = label[0] = 1
elif value < CO2_CUTOFFS[2]:
smiley[0] = label[0] = 2
else:
smiley[0] = label[0] = 3
# CO2 value
# clear it
for i in range(4):
co2_value[i] = 10
# update it
i = 3
while value:
co2_value[i] = value % 10
value = int(value / 10)
i -= 1
### WiFi ###
# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise
# 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)
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_light = neopixel.NeoPixel(
board.NEOPIXEL, 1, brightness=0.2
) # Uncomment for Most Boards
"""Uncomment below for ItsyBitsy M4"""
# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
# Uncomment below for an externally defined RGB LED
# 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_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
### Feeds ###
# Setup a adafruit io feeds for publishing
co2_feed = secrets["aio_username"] + "/feeds/mp2-co2"
temp_feed = secrets["aio_username"] + "/feeds/mp2-temp"
rh_feed = secrets["aio_username"] + "/feeds/mp2-rh"
# Setup a feed named 'onoff' for subscribing to changes
onoff_feed = secrets["aio_username"] + "/feeds/mp2-onoff"
### Code ###
# Define callback methods which are called when events occur
# pylint: disable=unused-argument, redefined-outer-name
def connected(client, userdata, flags, rc):
# This function will be called when the client is connected
# successfully to the broker.
print("Connected to Adafruit IO! Listening for topic changes on %s" % onoff_feed)
# Subscribe to all changes on the onoff_feed.
client.subscribe(onoff_feed)
def disconnected(client, userdata, rc):
# This method is called when the client is disconnected
print("Disconnected from Adafruit IO!")
def message(client, topic, message):
# This method is called when a topic the client is subscribed to
# has a new message.
print("New message on topic {0}: {1}".format(topic, message))
# Connect to WiFi
print("Connecting to WiFi...")
wifi.connect()
print("Connected!")
# Initialize MQTT interface with the esp interface
MQTT.set_socket(socket, esp)
# Set up a MiniMQTT Client
mqtt_client = MQTT.MQTT(
broker="io.adafruit.com",
username=secrets["aio_username"],
password=secrets["aio_key"],
)
# Setup the callback methods above
mqtt_client.on_connect = connected
mqtt_client.on_disconnect = disconnected
mqtt_client.on_message = message
# Connect the client to the MQTT broker.
print("Connecting to Adafruit IO...")
mqtt_client.connect()
while True:
print("hello")
# Poll the message queue
mqtt_client.loop()
# See of scd30 is ready to read
data_is_go = scd30.data_available
if data_is_go:
print("Data Available!")
co2_reading = scd30.CO2
temp_reading = scd30.temperature
rh_reading = scd30.relative_humidity
print("Read Complete!")
temp_F = temp_reading * 1.8 + 32
print("Sending {0} to display...".format(co2_reading))
update_display(co2_reading)
print("Display complete!")
print("Sending co2 value: {0}...".format(co2_reading))
mqtt_client.publish(co2_feed, co2_reading)
print("Sending temp value: {0}...".format(temp_F))
mqtt_client.publish(temp_feed, temp_F)
print("Sending rh value: {0}...".format(rh_reading))
mqtt_client.publish(rh_feed, rh_reading)
print("Send Complete!")
print("Waiting %d..." % UPDATE_RATE)
time.sleep(UPDATE_RATE)
Code: Select all
hello
Data Available!
Read Complete!
Sending 660.055 to display...
Display complete!
Sending co2 value: 660.055...
Sending temp value: 70.9533...
Sending rh value: 36.9202...
Send Complete!
Waiting 10...
hello
Data Available!
Read Complete!
Sending 660.068 to display...
Display complete!
Sending co2 value: 660.068...
Sending temp value: 71.0013...
Sending rh value: 36.6913...
Send Complete!
Waiting 10...
hello
Data Available!
Read Complete!
Sending 661.549 to display...
Display complete!
Sending co2 value: 661.549...
Sending temp value: 71.0782...
Sending rh value: 36.9278...
Send Complete!
Waiting 10...
hello
Data Available!
Read Complete!
Sending 662.537 to display...
Display complete!
Sending co2 value: 662.537...
Sending temp value: 71.1023...
Sending rh value: 36.7813...
Send Complete!
Waiting 10...
Code: Select all
jeremy@WOPR ~ % ping 192.168.4.164
PING 192.168.4.164 (192.168.4.164): 56 data bytes
64 bytes from 192.168.4.164: icmp_seq=0 ttl=255 time=88.963 ms
64 bytes from 192.168.4.164: icmp_seq=1 ttl=255 time=90.206 ms
64 bytes from 192.168.4.164: icmp_seq=2 ttl=255 time=11.470 ms
64 bytes from 192.168.4.164: icmp_seq=3 ttl=255 time=31.201 ms
64 bytes from 192.168.4.164: icmp_seq=4 ttl=255 time=56.376 ms
64 bytes from 192.168.4.164: icmp_seq=5 ttl=255 time=77.759 ms
64 bytes from 192.168.4.164: icmp_seq=6 ttl=255 time=98.783 ms
64 bytes from 192.168.4.164: icmp_seq=7 ttl=255 time=117.541 ms
64 bytes from 192.168.4.164: icmp_seq=8 ttl=255 time=35.827 ms