Acquiring and storing data to SD card at high rate from 4 analog pins

I am working on a project to acquire speech data from 4 sensors and giving the data input to 4 analog pins of arduino uno. The acquired data needs to be stored into SD card. The problem I am facing is that I want 8 KHz sampling frequency for all the analog pins but due to writing latency to the SD card I am not able to sample data at 32 KHz. Could you please suggest a suitable method for the same.

How much data do you need to store per sample? I think the SD write becomes more efficient if you buffer the data and write it in larger chunks, but you only have limited memory to do the buffering. I think that 8KHz sampling of a single input is probably barely possible if you use the standard analogRead() function, and to get a fourfold increase you'd need to manage the analog reading at a lower level and perhaps reduce the resolution.

I read this a few days ago:

You may also consider moving the data to a 2nd atmega which is managing the SD card. The simplest approach is to simply use the atmega physical USART, but you could implement another interface, if necessary. There are a number of benefits and not needing to allocate 512 Bytes to the sector buffer is a big one.

I have used this often, the dedicated SD-Card Atmega can simply be a naked 328P build or in today's market, a $3 mini-clone. Just remember that the SD-card is 3.3 Volt logic.

Ray

Mr. B. , If I wanted to do that what would I use for a card reader since the only ones I have now are shields for an UNO ? .Would I plug the shield into the mega instead of the UNO ? I already have a bare 328 breadboarded and I don't have a mega. Could I just make ribbon cables with female headers to plug into my SD shield and then solder solid 20 or 22 gauge wire leads at the other end of the ribbon cable to plug into the breadboard ? I have a phoenix screw terminal shield for my UNO that I could use for the data acquisition unit and that would allow me to run the wires from the analog inputs on the UNO screw terminal shield and then run serial lines from the Tx & Rx to the breadboarded 328 that is connected to the SD shield. Is this a plausible setup or have I overlooked something ?

PeterH: How much data do you need to store per sample? I think the SD write becomes more efficient if you buffer the data and write it in larger chunks, but you only have limited memory to do the buffering. I think that 8KHz sampling of a single input is probably barely possible if you use the standard analogRead() function, and to get a fourfold increase you'd need to manage the analog reading at a lower level and perhaps reduce the resolution.

It would be best to store the entire 10 bit ADC sample but I may compromise with the resolution and store just 8 bit as that will save some time. I am not using standard analogRead() function. I was calling ADC interrupt asynchronously and reading the 8 bit ADCH register. I was able to read at the desired sampling speed, only problem is with SD card as it has writing high latency. In RAM I was only able to store some 200 values.

Caltoa:
I read this a few days ago:
http://forum.arduino.cc/index.php?topic=228549.0

Thank you for sharing this link. I will try working with this and see if it solves the purpose.

mrburnette: You may also consider moving the data to a 2nd atmega which is managing the SD card.

Pardon me but I could not get one basic idea behind this. If writing latency to the SD card is the problem, then how can moving the data to second atmega solve the problem, because the data will be read at a higher speed but will be stored at a slower rate. I feel for real time data acquisition incoming and outgoing data should be same.

I am very new to arduino and all this stuff so I could not get what you meant by not needing to allocate 512 Bytes to the sector buffer is a big advantage. So maybe could you please elaborate it a bit?.

Pardon me but...

The basic premise is that Arduino is single-threaded processing... only one routine can access the core at a time. Interrupts push the microprocessor registers and addresses onto the program stack before the ISR can execute, so while interrupts do help to ensure that certain things happen in a asynchronous manner, there is a small time delay and SRAM resources that must be allocated to this effort. Additionally, SD flash memory requires that a 512Byte buffer be allocated for every write operation, on the UNO, this is 25% of the total SRAM. And there are additional SRAM requirements.

Hardware serial is asynchronous and a rather light-weight Arduino implementation in software. If one moves the SD-card off to a separate Atmega328P which is dedicated to receive, buffer, write to SD a minimum of 25% SRAM is returned to the main Arduino and a significant amount of microcontroller bandwidth. From a software architecture point-of-view, the main data-acquisition uC really knows nothing about the SD-card... it simply streams a log-file out the serial port at the highest rate that can be accepted by the downstream processor... the exact rate will depend on the quality of the SD card, so testing would be required. A previous link by Caltoa suggests that newly released forum SD routines can process very fast.

If you implement "Streaming.h" (requires no uC resources... just another way of saying Serial.print()) then you can easily write your program output syntax and test on the Arduino monitor (or TeraTerm or your favorite serial monitor) and simply connect the downstream SD-writer for logging. Logically, this simplifies the conceptual programming. It is, however, no always the right thing to do, if you must do read and write operations on the SD... the concept works best for write-only. We simply abstract the SD-card to a terminal device. All of the uC SRAM is dedicated to the SD write routines, so multi-buffering on the incoming datastream is possible, but hopefully that would not be necessary.

There is latency in this operation, although it can be characterized with testing. If one of the data elements is a timestamp, then latency in the write-to-SD is inconsequential.

Ray

Link to Streaming.h http://arduiniana.org/libraries/streaming/

Link to SD off-loading (this is a dedicated 9600 BAUD routine and is dated, but it will give you an idea) http://forum.arduino.cc/index.php?topic=154864.0

Link to understanding Arduino SRAM allocations (must read): http://learn.adafruit.com/memories-of-an-arduino/you-know-you-have-a-memory-problem-when-dot-dot-dot

Things to know about SD cards: http://arduino-info.wikispaces.com/SD-Cards

Thanks everybody for their suggestions. The code shared by Caltoa worked perfectly fine.

see Reply#4 of this post: (40,000 samples /per second) (edit pins to add the other three) http://forum.arduino.cc/index.php?topic=232914.msg1679019#msg1679019