Now we're going to take a look at the code we'll use for our data logging project.
Copy and paste the following into your code.py, or copy the file to your Feather CIRCUITPY drive and rename it to code.py to get started.
# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries # # SPDX-License-Identifier: MIT import time import analogio import board import storage import adafruit_am2320 vbat_voltage = analogio.AnalogIn(board.D9) i2c = board.I2C() # uses board.SCL and board.SDA # i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller am2320 = adafruit_am2320.AM2320(i2c) SD_CS = board.D10 spi = board.SPI() try: import sdcardio sd_card = sdcardio.SDCard(spi, SD_CS) except ImportError: import adafruit_sdcard import digitalio cs = digitalio.DigitalInOut(SD_CS) sd_card = adafruit_sdcard.SDCard(spi, cs) vfs = storage.VfsFat(sd_card) storage.mount(vfs, "/sd_card") def get_voltage(pin): return (pin.value * 3.3) / 65536 * 2 print("Logging temperature and humidity to log file") initial_time = time.monotonic() while True: try: with open("/sd_card/log.txt", "a") as sdc: temperature = am2320.temperature humidity = am2320.relative_humidity battery_voltage = get_voltage(vbat_voltage) current_time = time.monotonic() time_stamp = current_time - initial_time print("Seconds since current data log started:", int(time_stamp)) print("Temperature:", temperature) print("Humidity:", humidity) print("VBat voltage: {:.2f}".format(battery_voltage)) print() sdc.write( "{}, {}, {}, {:.2f}\n".format( int(time_stamp), temperature, humidity, battery_voltage ) ) time.sleep(3) except OSError: pass except RuntimeError: pass
Setup
First we import the necessary libraries for our code.
Next, we create the battery voltage object. This will later allow us to log the voltage output from the battery, which can tell us when the battery is getting low.
Then we setup I2C and the AM2320 sensor object.
Next we setup the SD card. First we assign SD_CS = board.D10
which assigns the SD card chip select pin to the D10 pin. Next, we setup the SPI object. Then we create the chip select object and provide it with the pin we assigned. Next we create the SD Card object, and provide it the SPI and chip select (cs) objects we created. Then we create the file system object that creates the logging space on the SD card for CircuitPython to use. Last, we tell CircuitPython to mount the file system and to mount it at /sd_card
.
We have one helper function in our code, the get_voltage()
function. By default, analog readings will range from 0 (minimum) to 65535 (maximum). This helper will convert the 0-65535 reading from pin.value
and convert it a 0-3.3V voltage reading. This allows us to read the battery voltage. It logs to the file along with the data from our sensor so we know when our battery is getting low.
Then we print
to the serial console that we're logging temperature. This shows up once, the first time the code runs.
And last, we set initial_time = time.monotonic()
. We use time.monotonic()
to give us a time, in seconds, since we began logging. We need an initial time to compare to, so we assign this variable at the beginning. For more information about how time.monotonic()
is used, check out the Passing Time section of the Hacking Ikea Lamps with Circuit Playground Express guide.
Main Loop
We start with while True:
.
Notice that the bulk of the code is under a try
, followed by an except
. The sensor can intermittently fail to provide a reading. To avoid the code hanging if this occurs, we've included the try
and except
code. This allows the code to continue, regardless of the error. For more information about try
and except
, check out the try
and except
section of the LED Trampoline guide.
Then we have with open("/sd_card/log.txt", "a") as sdc:
. We open a file called log.txt on our mounted SD card filesystem, and the "a"
tells it to append to the end of the file each time, instead of overwriting it every time you restart the code. Using with
, we set the open
code to sdc
so we can use the write
attribute later to write to the file.
Now we assign a series of variables. We're going to be logging the temperature, the humidity, the battery voltage, and the seconds since we last began logging. First we assign temperature and humidity to their values: temperature = am2320.temperature
, humidity = am2320.relative_humidity
. Next we assign battery_voltage
to the get_voltage()
helper: battery_voltage = get_voltage(vbat_voltage)
. Last, we set time.monotonic()
to current_time
, and then create our time_stamp
by subtracting initial_time
from current_time
.
Then we print
the value of each of our variables on different lines. We have added int()
to time_stamp
. As we are taking time readings every 3 seconds, we chose to work with whole integers instead of decimals. We have also included a string format for the battery voltage. {:.2f}".format(battery_voltage)
allows us to print
the battery voltage results with 2 decimal places. Then we include a printed blank line so the results are easier to read in the serial console.
Now we use our sdc
object to write
data to our log file. We want our log file to be a series of comma separated values (CSV). So, we use another string format to print each variable, separated by a comma, exactly as we printed
them to the serial console above. The \n
causes it to do a new line each time so each set of values is on its own line.
Then we have a time.sleep(3)
so we are only taking a reading every 3 seconds.
We end with the except
parts of our try
and except
code.
It's time to start logging!
Text editor powered by tinymce.