|
1 | 1 |
|
| 2 | +## |
| 3 | +# @file mpy_sdcard_log.py |
| 4 | +# @brief This MicroPython file contains functions to manage SD card logging on SparkFun MicroPython |
| 5 | +# enabled boards. |
| 6 | +# |
| 7 | +# @details |
| 8 | +# This module provides functionality to mount an SD card, read data from sensors, and log |
| 9 | +# the data to a file on the SD card. |
| 10 | +# |
| 11 | +# @note This code is designed to work with compatible microcontrollers, such as the |
| 12 | +# SparkFun IoT RedBoard - ESP32, or the SparkFun IoT RedBoard - RP2350 |
| 13 | +# |
| 14 | +# @author SparkFun Electronics |
| 15 | +# @date March 2025 |
| 16 | +# @copyright Copyright (c) 2024-2025, SparkFun Electronics Inc. |
| 17 | +# |
| 18 | +# SPDX-License-Identifier: MIT |
| 19 | +# @license MIT |
| 20 | +# |
2 | 21 |
|
3 | 22 | import machine
|
4 | 23 | from machine import Pin, SPI
|
|
8 | 27 | import os
|
9 | 28 | import uos
|
10 | 29 | import time
|
| 30 | +import random |
| 31 | +import json |
11 | 32 |
|
12 | 33 | # Define the boards we support with this deme - This is a dictionary the key being
|
13 | 34 | # the board uname.machine value, and value a tuple that contains SPI bus number and CS ping number.
|
|
16 | 37 | "SparkFun IoT RedBoard ESP32 with ESP32": (2, 5)
|
17 | 38 | }
|
18 | 39 |
|
| 40 | +# ------------------------------------------------------------ |
| 41 | + |
19 | 42 |
|
20 | 43 | def mount_sd_card():
|
| 44 | + """ |
| 45 | + Mounts an SD card to the filesystem. |
| 46 | +
|
| 47 | + This function checks if the current board is supported, initializes the SPI bus and CS pin, |
| 48 | + creates the SD card object, and mounts the SD card to the filesystem. |
| 49 | +
|
| 50 | + Returns: |
| 51 | + bool: True if the SD card was successfully mounted, False otherwise. |
| 52 | +
|
| 53 | + """ |
21 | 54 |
|
22 | 55 | # is this a supported board?
|
23 | 56 | board_name = os.uname().machine
|
@@ -51,3 +84,170 @@ def mount_sd_card():
|
51 | 84 | print("SD Card mounted successfully")
|
52 | 85 |
|
53 | 86 | return True
|
| 87 | + |
| 88 | +# ------------------------------------------------------------ |
| 89 | + |
| 90 | + |
| 91 | +def read_data(observation): |
| 92 | + """ |
| 93 | + Simulates the collection of data and adds values to the observation dictionary. |
| 94 | +
|
| 95 | + This function generates simulated data for time, temperature, humidity, and pressure, |
| 96 | + and adds these values to the provided observation dictionary. If connecting to an actual |
| 97 | + sensor, you would take readings from the sensor and add them to the observation dictionary |
| 98 | + within this function. |
| 99 | +
|
| 100 | + Args: |
| 101 | + observation (dict): A dictionary to store the simulated sensor data. |
| 102 | +
|
| 103 | + Returns: |
| 104 | + bool: Always returns True to indicate successful data collection. |
| 105 | + """ |
| 106 | + |
| 107 | + # Note: If connecting to a actual sensor, you would take readings from the sensor and add them to the |
| 108 | + # observation dictionary here. |
| 109 | + |
| 110 | + # Add the time |
| 111 | + observation["time"] = time.time() |
| 112 | + |
| 113 | + # Add the temperature |
| 114 | + observation["temperature"] = random.randrange(-340, 1000)/10 |
| 115 | + |
| 116 | + # Add the humidity |
| 117 | + observation["humidity"] = random.randrange(0, 1000)/10. |
| 118 | + |
| 119 | + # Add the pressure |
| 120 | + observation["pressure"] = random.randrange(10, 1000)/10. |
| 121 | + |
| 122 | + # Success ! |
| 123 | + return True |
| 124 | + |
| 125 | +# ------------------------------------------------------------ |
| 126 | +# Setup the log file |
| 127 | +# This function opens the log file for writing |
| 128 | +# and returns the file object. |
| 129 | +# If the file cannot be opened, it returns None. |
| 130 | + |
| 131 | + |
| 132 | +def setup_log_file(filename): |
| 133 | + """ |
| 134 | + Sets up a log file on the SD card with the given filename. |
| 135 | +
|
| 136 | + This function attempts to open a file on the SD card for writing. If the file |
| 137 | + cannot be opened, an error message is printed and None is returned. |
| 138 | +
|
| 139 | + Args: |
| 140 | + filename (str): The name of the log file to be created on the SD card. |
| 141 | +
|
| 142 | + Returns: |
| 143 | + file object: A file object for the opened log file if successful, or None if an error occurred. |
| 144 | + """ |
| 145 | + |
| 146 | + try: |
| 147 | + fs = open("/sd/" + filename, "w") |
| 148 | + except Exception as e: |
| 149 | + print("[Error] Failed to open log file:", e) |
| 150 | + return None |
| 151 | + |
| 152 | + return fs |
| 153 | + |
| 154 | +# ------------------------------------------------------------ |
| 155 | + |
| 156 | + |
| 157 | +def log_data(filename, count=30, interval=50, to_console=True): |
| 158 | + """ |
| 159 | + Logs data to a specified file and optionally prints it to the console. |
| 160 | +
|
| 161 | + Parameters: |
| 162 | + filename (str): The name of the file to log data to. |
| 163 | + count (int, optional): The number of times to log data. Default is 30. |
| 164 | + interval (int, optional): The interval (in milliseconds) between each log entry. Default is 50. |
| 165 | + to_console (bool, optional): If True, prints the data to the console. Default is True. |
| 166 | +
|
| 167 | + Returns: |
| 168 | + None |
| 169 | + """ |
| 170 | + |
| 171 | + # Create the observation dictionary |
| 172 | + observation = {} |
| 173 | + |
| 174 | + # Open the log file |
| 175 | + fs = setup_log_file(filename) |
| 176 | + if fs is None: |
| 177 | + return |
| 178 | + |
| 179 | + # Loop for the number of times specified |
| 180 | + for i in range(count): |
| 181 | + |
| 182 | + observation.clear() |
| 183 | + observation["iteration"] = i |
| 184 | + |
| 185 | + # Read the data |
| 186 | + read_data(observation) |
| 187 | + |
| 188 | + # Write the data to the log file |
| 189 | + fs.write(json.dumps(observation) + "\n") |
| 190 | + |
| 191 | + if to_console: |
| 192 | + # Print the data to the console |
| 193 | + print(json.dumps(observation)) |
| 194 | + |
| 195 | + # Wait for the specified interval |
| 196 | + time.sleep(interval) |
| 197 | + |
| 198 | + # Close the log file |
| 199 | + fs.close() |
| 200 | + |
| 201 | +# ------------------------------------------------------------ |
| 202 | + |
| 203 | + |
| 204 | +def sdcard_log_example(filename="mpy_sdcard_log.txt", count=20, interval=2): |
| 205 | + """ |
| 206 | + Logs data to an SD card at specified intervals and prints the data to the console. |
| 207 | +
|
| 208 | + Args: |
| 209 | + filename (str): The name of the file to log data to. Defaults to "mpy_sdcard_log.txt". |
| 210 | + count (int): The number of iterations to log data for. Defaults to 20. |
| 211 | + interval (int): The interval in seconds between each log entry. Defaults to 2. |
| 212 | +
|
| 213 | + Returns: |
| 214 | + None |
| 215 | + """ |
| 216 | + |
| 217 | + print("Logging to: {filename}, every {interval} seconds for {count} iterations.\n".format( |
| 218 | + filename=filename, interval=interval, count=count)) |
| 219 | + # Mount the SD card |
| 220 | + if not mount_sd_card(): |
| 221 | + print("Failed to mount SD card") |
| 222 | + return |
| 223 | + |
| 224 | + print("\nLogging Data to SD Card and Console:") |
| 225 | + |
| 226 | + # Log the data |
| 227 | + log_data(filename, count=count, interval=interval, to_console=True) |
| 228 | + |
| 229 | + # Unmount the SD card |
| 230 | + uos.umount("/sd") |
| 231 | + |
| 232 | + print("\nSD Card unmounted successfully") |
| 233 | + |
| 234 | +# ------------------------------------------------------------ |
| 235 | +# Run method for the example |
| 236 | + |
| 237 | + |
| 238 | +def run(): |
| 239 | + """ |
| 240 | + Executes the SparkFun SD card logging example. |
| 241 | +
|
| 242 | + """ |
| 243 | + print("-----------------------------------------------------------") |
| 244 | + print("Running the SparkFun sd card logging example...") |
| 245 | + print("-----------------------------------------------------------") |
| 246 | + |
| 247 | + sdcard_log_example() |
| 248 | + print() |
| 249 | + print("Done!") |
| 250 | + |
| 251 | + |
| 252 | +# run the demo/example on load |
| 253 | +run() |
0 commit comments