Once you've finished setting up your Feather RP2040 with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the Download Project Bundle button in the window below. It will download as a zipped folder.

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

import time
import board
import digitalio
import adafruit_scd4x
import adafruit_sdcard
import busio
import storage
import adafruit_pcf8523

#  setup for I2C
i2c = board.I2C()
#  setup for SCD40
scd4x = adafruit_scd4x.SCD4X(i2c)
#  setup for RTC
rtc = adafruit_pcf8523.PCF8523(i2c)
#  start measuring co2 with SCD40
scd4x.start_periodic_measurement()
#  list of days to print to the text file on boot
days = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")

# SPI SD_CS pin
SD_CS = board.D10

#  SPI setup for SD card
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
cs = digitalio.DigitalInOut(SD_CS)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
try:
    storage.mount(vfs, "/sd")
    print("sd card mounted")
except ValueError:
    print("no SD card")

#  to update the RTC, change set_clock to True
#  otherwise RTC will remain set
#  it should only be needed after the initial set
#  if you've removed the coincell battery
set_clock = False

if set_clock:
    #                     year, mon, date, hour, min, sec, wday, yday, isdst
    t = time.struct_time((2021,  10,   31,   00,  00,  00,    0,   -1,    -1))

    print("Setting time to:", t)
    rtc.datetime = t
    print()

#  variable to hold RTC datetime
t = rtc.datetime

time.sleep(1)

#  initial write to the SD card on startup
try:
    with open("/sd/co2.txt", "a") as f:
        #  writes the date
        f.write('The date is {} {}/{}/{}\n'.format(days[t.tm_wday], t.tm_mday, t.tm_mon, t.tm_year))
        #  writes the start time
        f.write('Start time: {}:{}:{}\n'.format(t.tm_hour, t.tm_min, t.tm_sec))
        #  headers for data, comma-delimited
        f.write('CO2,Time\n')
        #  debug statement for REPL
        print("initial write to SD card complete, starting to log")
except ValueError:
    print("initial write to SD card failed - check card")

while True:
    try:
        #  variable for RTC datetime
        t = rtc.datetime
        #  append SD card text file
        with open("/sd/co2.txt", "a") as f:
            #  read co2 data from SCD40
            co2 = scd4x.CO2
            #  write co2 data followed by the time, comma-delimited
            f.write('{},{}:{}:{}\n'.format(co2, t.tm_hour, t.tm_min, t.tm_sec))
            print("data written to sd card")
        #  repeat every 30 seconds
        time.sleep(30)
    except ValueError:
        print("data error - cannot write to SD card")
        time.sleep(10)

Upload the Code and Libraries to the Feather RP2040

After downloading the Project Bundle, plug your Feather RP2040 into the computer's USB port. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called CIRCUITPY. Unzip the folder and copy the following items to the Feather RP2040's CIRCUITPY drive. 

  • lib folder
  • code.py

Your Feather RP2040 CIRCUITPY drive should look like this after copying the lib folder and the code.py file.

How the CircuitPython Code Works

The SCD-40 and RTC are controlled over I2C. The SCD-40 begins measuring CO2 levels with start_periodic_measurement().

#  setup for I2C
i2c = board.I2C()
#  setup for SCD40
scd4x = adafruit_scd4x.SCD4X(i2c)
#  setup for RTC
rtc = adafruit_pcf8523.PCF8523(i2c)
#  start measuring co2 with SCD40
scd4x.start_periodic_measurement()

The SD card is accessed using SPI. board.D10 is used for the SD_CS pin on the RP2040 boards.

# SPI SD_CS pin
SD_CS = board.D10

#  SPI setup for SD card
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
cs = digitalio.DigitalInOut(SD_CS)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")

Set the Time

The RTC is set using the set_clock variable. If set_clock is True, then the date and time is set to reflect what is entered in the time.struct_time() function. If set_clock is False, then the RTC is not reset.

#  to update the RTC, change set_clock to True
#  otherwise RTC will remain set
#  it should only be needed after the initial set
#  if you've removed the coincell battery
set_clock = False

if set_clock:
    #                     year, mon, date, hour, min, sec, wday, yday, isdst
    t = time.struct_time((2021,  10,   31,   00,  00,  00,    0,   -1,    -1))

    print("Setting time to:", t)
    rtc.datetime = t
    print()

Write Data

Before the loop, some data is written to the SD card's text file to assist in separating the data from different logging sessions. First, the date is written, followed by the time. Then, header labels are added, which will be useful when importing the data into a spreadsheet.

#  initial write to the SD card on startup
with open("/sd/co2.txt", "a") as f:
    #  writes the date
    f.write('The date is {} {}/{}/{}\n'.format(days[t.tm_wday], t.tm_mday, t.tm_mon, t.tm_year))
    #  writes the start time
    f.write('Start time: {}:{}:{}\n'.format(t.tm_hour, t.tm_min, t.tm_sec))
    #  headers for data, comma-delimited
    f.write('CO2,Time\n')
    #  debug statement for REPL
    print("initial write to SD card complete, starting to log")

In the loop, the CO2 level from the SCD-40, along with the current time, is written to the SD card's text file every 30 seconds. 

while True:
    #  variable for RTC datetime
    t = rtc.datetime
    #  append SD card text file
    with open("/sd/co2.txt", "a") as f:
        #  read co2 data from SCD40
        co2 = scd4x.CO2
        #  write co2 data followed by the time, comma-delimited
        f.write('{},{}:{}:{}\n'.format(co2, t.tm_hour, t.tm_min, t.tm_sec))
    #  repeat every 30 seconds
    time.sleep(30)

This guide was first published on Oct 27, 2021. It was last updated on 2021-10-27 11:53:07 -0400.

This page (Coding the Disconnected CO2 Data Logger) was last updated on Dec 01, 2021.

Text editor powered by tinymce.