Power reduction with sync() when logging to SD

Status
Not open for further replies.

mborgerson

Well-known member
While working on a project to build a low-power data logger using a Teensy3.6, I discovered something a bit counter-intuitive. I found that calling the sync() function after writing a block of data to the output file reduced the overall power drain by a factor of three! This is counter-intuitive because I thought that the sync() function would require an extra write to the SD card after updating the file directory. Apparently, the power reduction occurs because something in the sync() function puts the SD card into a low-power mode—which doesn’t automatically occur at the end of a block write.

The program uses Teensy 3.6 at 24 or 48MHz clock writing to SanDisk Ultra 128GB microSD card. The Teensy records its own current consumption by reading an ADC channel that is connected to the output of a MAX471 High-Side current sensor. The current sensor outputs a voltage according to this conversion function: mA = 200 * VSensor, or 1.0Volts = 200mA. The Teensy ADC is set to use the internal 1.2V reference to avoid issues with changes in the 3.3V rail that might be caused the the peak SDC currents of about 150mA. The program also records the output of an ElapsedMicroseconds timer to monitor possible sampling jitter. The current sensor is sampled at 10KHz.

All the tests were run using the EXFat file system from SDFat 2.0B (Thanks, Bill Greiman—EXFat with pre-allocation is just what I needed for reducing power consumption on very large data file logging). The file system was set up to use the hardware 4-bit SDIO interface.

Two storage algorithms were tested:

The first is a standard queued input algorithm. The ADC and timing data are collected in an interrupt handler called by and interval timer. The collected data is put into an input queue in the interrupt handler. The main program loop monitors the input queue length, and when data is available, it pulls the data from the queue and writes it directly to the output file. The file system internals handle buffering the 8-byte records into 512-byte blocks and writing the blocks as required. This algorithm is used quite often in data logging examples found in the Teensy example files. The queue is necessary because file writes can take up to 160mSec when the card needs to erase a block, then write the new data.
Other SD cards may take even longer. The 32KB queue I used would handle delays up to 400mSec.

The second algorithm uses two large (32 or 64KByte) Ping-Pong buffers. The interrupt handler writes the collected data into one buffer, while the main loop writes the data from the other buffer as a single large block to the output file. This algorithm requires more RAM than the queue algorithm, but is more efficient in writing to the SD card as it can use multi-block writes. The algorithm is also more efficient in that data doesn’t have to be moved after the interrupt handler puts it in the buffer. The file writes in the main loop are simply passed a pointer to the buffer and the number of bytes to be written.

For both algorithms, an asm(“WFI\n”) instruction was added at the end of the foreground loop to minimize CPU power consumption by putting the CPU to sleep until the it was awakened by then next interrupt (generally the 10KHz ADC interval timer).

The test program collected 100 seconds of data in each file. in some cases, 10 files were collected for each test to evaluate variability in the average current.

Here are the results of the tests:

Code:
Algorithm				mA with no sync()		mA with sync()	
————————————————————————————————————
Queue               24mHz                           44.66                          *(1)		
Ping-Pong 32KB 24Mhz                           43.60                       14.31			    
Ping-Pong 64KB 24Mhz                           43.94                       13.91

Queue               48MHz                        52.48                         *(1)
Ping-Pong 32KB 48MHz                         52.65                       18.94
Ping-Pong 64KB 48MHz                         51.75                       18.36

*(1) Calling sync() after every file write (at 10KHz) is a BAD IDEA! It causes queue overruns
and other problems

Some other observations:

* Thanks to the time spent with the CPU asleep, boosting the CPU speed from 24 to 48MHz only adds about 5mA to the current drain. This would add lots more clock cycles for things like digital filters, more channels, etc.— but at the cost of more current drain.

* USB connections get pretty flaky at 24MHz. Quite often, neither my PC host program nor the Arduino Serial Monitor will connect to the Teensy. Connections are never a problem at 48MHz.

* Switching to a slower, 8GB SanDisk card, reduced average power consumption in the PP tests by about 1mA, but peak power drain was cut by more than a factor of two: from about 140mA to about 55mA. I suspect the reduction is due to lower erase currents for the smaller erase blocks on the 8GB card. Building an efficient power supply for a logger that has a 10:1 variation in current drain can be challenging. (Think large capacitors and quick transient response.)

* A modified test which eliminated all use of the USB serial port reduced power drain in the PP tests by about another 1-2mA. (I don’t have a USB cable long enough to connect to a logger moored at 100m depth in the equatorial Pacific!) I suspect that turning off other peripherals might have similar effects.
 
Status
Not open for further replies.
Back
Top