This is basically the same idea as the Arduino sketch - just read the values and send over serial in a loop. There are CircuitPython libraries for the SCD40 and BME280, which makes this easy to implement.

Install CircuitPython

This is covered in the Trinkey QT2040 main guide:

The required libraries will be included with the project bundle download along with project code below.

Enable USB CDC Data

We could probably just send the data using the typical serial ouput via the typical print() command. However, here we show how to enable and use the secondary USB CDC serial port available in CircuitPython:

As mentioned in that guide, this requires a special boot.py file to be located in the CIRCUITPY folder. Well, not too special, it's just a few lines of code:

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

import usb_cdc
usb_cdc.enable(data=True)

Copy that code and save it to CIRCUITPY/boot.py.

CircuitPython Code

Here is the project code. To get code and necessary libraries, click on the Download Project Bundle link below, and uncompress the .zip file. Once the sensors are connected and the modified boot.py has been put in place, simply save the project code as CIRCUITPY/code.py:

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

import time
import board
import usb_cdc
import adafruit_scd4x
from adafruit_bme280 import basic as adafruit_bme280
import neopixel

#--| User Config |-----------------------------------
DATA_FORMAT = "JSON"    # data format, CSV or JSON
DATA_RATE = 5           # data read rate in secs
BEAT_COLOR = 0xADAF00   # neopixel heart beat color
BEAT_RATE = 1           # neopixel heart beat rate in secs, 0=none
#----------------------------------------------------

# check that USB CDC data has been enabled
if usb_cdc.data is None:
    print("Need to enable USB CDC serial data in boot.py.")
    while True:
        pass

# setup stuff
i2c = board.I2C()  # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C()  # For using the built-in STEMMA QT connector on a microcontroller
scd = adafruit_scd4x.SCD4X(i2c)
scd.start_periodic_measurement()
bme = adafruit_bme280.Adafruit_BME280_I2C(i2c)
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)

# CSV output
def send_csv_data(values):
    usb_cdc.data.write("{}, {}, {}, {}\n".format(*values).encode())

# JSON output
def send_json_data(values):
    usb_cdc.data.write('{'.encode())
    usb_cdc.data.write('"CO2" : {},'.format(values[0]).encode())
    usb_cdc.data.write('"pressure" : {},'.format(values[1]).encode())
    usb_cdc.data.write('"temperature" : {},'.format(values[2]).encode())
    usb_cdc.data.write('"humidity" : {}'.format(values[3]).encode())
    usb_cdc.data.write('}\n'.encode())

# init time tracking
last_data = last_beat = time.monotonic()

# loop forever!
while True:
    current_time = time.monotonic()

    # data
    if current_time - last_data > DATA_RATE:
        data = (scd.CO2, bme.pressure, bme.temperature, bme.humidity)
        usb_cdc.data.reset_output_buffer()
        if DATA_FORMAT == "CSV":
            send_csv_data(data)
        elif DATA_FORMAT == "JSON":
            send_json_data(data)
        else:
            usb_cdc.data.write(b"Unknown data format.\n")
        last_data = current_time

    # heart beat
    if BEAT_RATE and current_time - last_beat > BEAT_RATE:
        if pixel[0][0]:
            pixel.fill(0)
        else:
            pixel.fill(BEAT_COLOR)
        last_beat = current_time

This guide was first published on Dec 22, 2021. It was last updated on Dec 22, 2021.

This page (CircuitPython Sender) was last updated on Mar 13, 2023.

Text editor powered by tinymce.