Your prototype records data. Will you still have it after the test?

A sensor can work perfectly on your desk and still leave you with nothing useful after a trial. The readings scroll past on a laptop, someone unplugs the board, and the record of what happened is gone. Once an environmental monitor, interactive device or other prototype leaves its development computer, saving the data becomes part of making the trial useful.

Start with two questions: which records do you need afterwards, and how much can you afford to lose? A recent embedded-systems discussion asks how to save a small amount of EEPROM and SD-card data after a moped's power is switched off. That is a much harder problem than reading a file back after a normal write, and keeping the two apart helps you choose a sensible first experiment.

On our bench we ran a set of MicroPython storage experiments on a Pico-based board: writing temperature readings to a file, rotating log files, writing to a microSD card on an expansion board, using a RAM filesystem, and reading an EEPROM file after its power was restored. Together they make a practical starting point for a prototype logging plan.

First, save one short run and read it back

The first test used the board's internal temperature sensor, so no external probe was needed. The program took ten readings, wrote each with its elapsed time to temperature_data.txt, closed the file and printed its contents. That checks the path from a reading to a saved record before you add a removable card or a logging library.

The code opens the file with open(..., "w"), writes each formatted line, calls os.sync() to request a filesystem sync, then closes the file and reopens it to read. Readings appeared at 1, 12, 23 and up to 99 ms, all 22.83 °C. That is a successful write-and-readback. The temperature is an internal chip reading and the times count from program start; neither is a calibrated room temperature with a calendar timestamp.

For a trial lasting hours, decide how a new run starts. Opening the same file in "w" mode clears it, so a restart silently replaces the evidence you wanted. A run identifier, or carefully managed append mode, prevents that. Add the device identity and the meaning of each column so a colleague can read the file without your development setup.

Give the log a budget, not just a filename

The next test used a small logger of our own that writes to the terminal or to a directory of files. A severity level filters routine messages, and a formatter adds the time and other context. The test generated messages at several levels and deliberately divided by zero so the traceback would be captured.

That matters when a trial produces both measurements and diagnostics. A temperature sample and "sensor disconnected" answer different questions. Keep enough context to relate them, but do not fill storage with routine debug output while the measurements you need are still arriving.

The logger caps the number of entries per file and rotates to a new one. Our output showed several files and the recorded exception. Rotation keeps each file easy to inspect, but the code sets no total storage budget and deletes nothing by any retention rule, so four small files can eventually become thousands. Before the prototype goes out, decide what happens when storage is nearly full: stop and show a clear status, keep the newest records, or keep the earliest. A device that quietly carries on while discarding the important part of the record is hard to learn from.

Two details need fixing before using this logger long term. Its filenames have one-second resolution, so two rotations in the same second can choose the same name. And the test set a fixed real-time-clock date. A useful trial record needs a deliberate time source or an explicit "time unknown" state, not a plausible date that was typed in.

Measure whether saving a record slows the prototype down

A file write is work the controller has to do. If the same loop also reads a fast signal or responds to a button, a long write delays that work. We timed the logging path and printed each duration. Selected values ranged from about 1.8 ms and 2.0 ms up to 43.2 ms and 81.7 ms. Those are observations from that implementation and run, not a guaranteed upper bound or an SD-card benchmark, and the log alone does not identify the cause of the longer pauses.

For a slow environmental trial, occasional pauses may be fine if you record when each sample was actually taken. For a responsive interactive device, they may need attention. Measure the combined application first. If you buffer records in RAM and write them in groups, decide explicitly how much recent data may be lost when power disappears.

Use the card slot when you need more room or a removable record

The microSD test used SPI1 with GP10 for clock, GP11 for data to the card, GP12 for data from the card and GP13 for chip select, all specific to our carrier. The card was accessed through the sdcard driver from micropython-lib, which our firmware did not include by default. Mounting it as a FAT filesystem at /sd gave ordinary file access:

sd = sdcard.SDCard(spi, cs)
os.mount(os.VfsFat(sd), "/sd")

We wrote and read a test file, created a subdirectory and renamed a file. The printed date in that output came from a hard-coded string, and the capacity figure multiplied by the block size twice, so treat only the file operations as the result. Plan how a tester gets the files out: a clear way to stop recording, close files and unmount before removal, and visible states for "no card," "write failed" and "recording stopped." We have not yet exercised those states.

A saved file and a RAM file are different things

MicroPython presents different storage through the same file operations. We built a small filesystem in a bytearray in RAM (50 blocks of 512 bytes, 25,600 bytes before overhead), wrote hello.txt and read it back. It looks like any other file, but it vanishes when that memory does. It is useful for temporary data, not for keeping a trial record through a power cut. MicroPython's filesystem documentation explains how RAM and persistent devices sit behind the same interface.

That distinction matters when testing persistence. Reading a file right after writing it is an initial check. A stronger test restarts the real device, mounts the existing storage without formatting it, and checks the saved contents. Reformatting at every startup destroys the record the test is meant to protect.

What the EEPROM power test shows, and what it does not

The last test placed a small FAT filesystem on a GraftSense AT24C256 EEPROM module. EEPROM keeps data without power, but this part holds 32 KiB, so we stored a small JSON configuration file, not a sensor log. The code used I2C0 on GP4 and GP5 at address 0x50; make sure your code and wiring agree on the bus before reuse. Our driver and block-device wrapper are teaching code with issues still to resolve, not a production persistence layer.

We wrote the file, closed it and read it back. Then, with the controller still running, we removed and restored power to the EEPROM module only. The program detected its return and printed the file again, and the contents matched.

That is evidence of retention after a completed write in that setup. It does not show what happens if power fails during an update or if the controller itself restarts, and the test formatted the EEPROM at startup, so a restart test must mount the existing filesystem instead. MicroPython's documentation warns that FAT can be corrupted by power failure during writes, and describes littlefs as more resistant with limits of its own. Adding flush() or switching filesystems is not a substitute for testing real power loss.

Turn these experiments into a useful trial

Before handing the prototype to someone else, agree on the record you expect back: device and run identifiers, sample times, units, important events and a clear marker for missing data. Run the whole application long enough to exercise rotation and the storage limit, including a restart and a file-export check.

Then test the interruptions the intended use can produce. A normal stop, a controller reset and power loss during recording are separate cases. Use expendable data, compare what survives and record the recovery behavior. The goal is to know how much recent data can be lost, and whether older files stay readable, before those limits affect a real trial.