Arduino Fast Serial Data Logger

 

The OP has likely solved this problem by now, but I know that others will be in the same position, so I am answering for them. I routinely record ten channels of biological sensors including one of 16-bit sound at 8 kHz (plus the associated FFT data) to an SD card using arduino-compatible systems, so I doubt very much that the SD card writing per se is the problem. Throughput to an SD card is a function of several variables. To maximize write throughput you need to write full blocks of data at the correct block size, since partial blocks take the same amount of time as full blocks.

Arduino serial data loggerFast

You also need to be ready with more data as soon as the SD card is ready to take more, otherwise precious cycles slip away from you. You need to ensure that your writes are non-blocking (don't try to write more than the buffer can receive) so your loop can process and queue up new data while the SD card is doing its thing. You need to read any timing-sensitive sensors using interrupt service routines that write their data either to a circular buffer or to one of a group of two or three buffers that are cycled between being filled and being emptied. Printing debug statements to the serial port can take many tens of milliseconds in a loop that otherwise may take only a few microseconds.

Arduino

An Arduino and Ethernet shield are used as an Arduino web server data logger that periodically logs data to a file on the SD card. The logged data can be viewed on a web page. In the Arduino sketch for this project, the value from analog input A5 is logged to file together with the time in milliseconds from the millis function. I need to log about 60-80 bytes of data every 5ms. I am acquiring the data using an Arduino Mega (AVR 1280 @ 5.0V and 16.0Mhz), connected to various SPI devices. One of the SPI devices has a 'data ready' pin which goes low for 0.5ms at 200Hz indicating that it's data is ready to be acquired via SPI.

If you write more than the serial port buffer can hold, the call will be blocking and you will be at the mercy of the PC that's reading the serial port. This will always be bad enough to mess up the program you're trying to debug. I've encountered situations where this introduced delays of up to 10 seconds (the PC was misbehaving, but still.). A quick improvement to printing debug statements is to maintain a loop counter and only print a debug statement every N loops.

The program in the original question uses a naive strategy in the sense that it acquires some amount of data and then immediately tries to write it to the SD card, waiting until the write is complete before trying to acquire new data. This will never work at high data rates for the reasons given above. If you use this approach, you are likely wasting 90% of your program cycles in waiting for the SD write and the Serial port write. If either one takes too long, you will miss the next data acquisition window. My advice: your first step is to research and find or write a circular buffer library.

Then set a timer to call an interrupt service routine that acquires data and puts it into the circular buffer. Write a loop routine that checks to see whether the SD card is available for writing, and then takes just enough data out of the circular buffer to fit in a single block write for your SD card (look at the documentation for the card adaptor and the card). At that point you will know whether your system can keep up with your needs. It's possible that your SD card writing itself is OK but your Arduino is having trouble keeping up either because it's too slow or because you don't have enough room for a sufficiently large circular buffer.

I doubt this because I've recorded and played back audio at 8 KHz on the Uno, but then I don't know what else you need to accomplish in your program. If you do determine that the Arduino itself is too slow or has insufficient memory, take a look at the Teensy series of boards. They are entirely compatible with Arduino libraries and IDE but they run hundreds of times faster than the Uno at a larger data width, plus they have oodles of RAM and a gazillion pins. They're also much smaller than the Arduino form factor and the community that uses them is very knowledgeable. If it turns out that SD card write throughput is OK but that it requires more buffering than you have on-board, you can add an SPI ram breakout board for more fast buffering space. Finally, if the amount of data you need to collect is so large and so continuous that you simply can't buffer it long enough to get it written out to SD, or if the SD card truly can't keep up, or if the data is larger than any available SD card, you may consider sending your data off the board in near-real-time.

I send 10 hours of nightly data from a Teensy over a USB virtual serial port to the PC at about 3Mbps, and others have done better. Ethernet output is also available and can be at least an order of magnitude greater. Why not write a simple program and try to write values like 1, 2, 3. 100 to the SD card with a 1 second delay between writes. Then read the values back and send them via serial link to your PC screen. This way you can make sure that you are writing and reading values in the correct way.

Arduino Data Logger Temperature

Once this works, you can reduce the delay and see what is the minimum delay between writes that the SD card will support. It might be advisable to also write a program to fill the SD card with 100 values = 0 to clear it before the next test.