main index Note: my Arduino-related pages start here!

Why? Arduino has 512 bytes EEPROM (which does not loose its contents at power off) and 1024 bytes RAM (which contents are lost at power off). To get more storage, a SD-card solution (MMC, secure-digital, micro-SD, etc) is the cheapest way to have a few gigabytes of storage for data logging.

Using a secure-digital (SD) card with the Arduino is quite easy, as long as we use its "slow" mode (via SPI and without interrupts) and only read/write single sectors (no "burst" modes).

Hardware: we only need four pins (3 out, 1 in):

The three output pins should not output more than 3.3V (to not to damage the SD-card logic): this will require a few resistors to get the Arduino's 5V down to 3.3V (or something near that).

I scavenged a SD-card slot from a dead digital camera. The SD slot has 9 pins, named: CS (card select), DI (data in), GND (ground), VCC (3.3V), SCK (system clock), GND1 (another ground), DO (data out), IRQ (interrupt request), WP (write protect). We only need these pins:

As said, only DO pin can be connected to a 5V Arduino.
ARRGH. Except for Arduino Pro Mini (which works on 3.3V), almost all original Arduino boards work on 5V. I have an Arduino Diecimila (5V on ports, but also exposes a 3.3Vcc source) and two Arduino Mini (5V only!) and no Arduino Pro Mini (3.3V for everything, which would save me some resistor soldering). It would be nice to buy some Arduno SuperMini having 3.3V logic and a Micro-SD slot...!

Software: we do not need to have an entire filesystem handling, as long as we are able to read and write single sectors. That is, if you want to see the SD-card as a filesystem, you will have to handle all common operations (create a file, read data, browse a directory, input/output buffering...).

While there exists a number of ready-made solutions, I chose to not to use any of the, because it's far more convenient use only entire-sectors operations, which require minimum code and do not hide time lags (generally you cannot predict when some buffered read/write will access to the SD-card, neither you can exactly predict when it will have also to update the filesystem structure, etc).

This way, a 512 Mb SD-card will be seen as an array of a million sectors (well, somewhat less, because manufacturers round down "megabytes" to "1,000,000" bytes for their convenience).

Note: as usual, "sector" means a 512 bytes block.

First, let's mount the SD/microSD card in its reader to learn about its characteristics, using the df command (Linux and Mac):

Filesystem     1K-blocks  Used    Avail Capacity  Mounted on
/dev/disk2s1      994432     0   994432     0%    /Volumes/MYSDCARD

This is a 1Gb card, having 994,432 kilobytes free after formatting.

Note: I had to manually erase some files/directories which Mac OS X creates for "Trashcan" support when unmounting (I had to issue the command rm -rf /Volumes/MYSDCARD/.Trash* /Volumes/MYSDCARD/._.Trash*).

Note: common Linux distributions will mount under /media or /mnt (verify using df command).

Card speed: let's test the writing time of 50,000 sectors:
time ruby -e '50000.times { |n| print "x"*512 }' > /Volumes/MYSDCARD/datafile.bin

That is: 50,000 times (the n goes from 0 to 49,999) print out a string of 512 "x" characters, and send them to the datafile.bin file. The filesystem will have more than 50,000 write operations because the root directory and the file allocation structure will be updated as well (before, during and after file write operation).

The time command terminated in some 28.5 seconds of "real" time (user and system times were largely smaller: most of the time was for "waiting" the card to complete single operations). I can guess the card is able to write almost 1700-2000 sectors per second. This helps me to figure out that on this card, a sector write is completed in less than a millisecond (remember that operating systems use all fastest features: interrupt-driven, block writes, etc). I won't care about more speed because a "less than millisecond" time for a sector write is acceptable for most applications.

Filesystem transparency

One advantage of the FAT filesystems is that the "reserved" sectors (boot, maps, root directory) are allocated at the beginning.

So, if we create a file that occupies all available space, we will see it as a large number of consecutive sectors, which first sector is just a few sectors after the beginning of the partition.

This way allows us to:

If the Arduino does not skip those "reserved" sectors, then the SD-card will have to be read in "raw mode" (without filesystem), for example using the dd utility. If there is a large file, and the Arduino only writes the sectors allocated by that file without modifying the rest of the file system, then the SD-card contents will be readable by any computer that can access it.

In order to see how many sectors to skip, let's first try the "hard" way:
time ruby -e '50000.times { |n| print [n+0x33000000].pack("N")*128 }' > /Volumes/MYSDCARD/datafile.bin

Note: n goes from 0 to 49,999; for every n, build an array containing the 32-bit value n+0x33000000, and then pack the array in MSB-first (4 bytes string) and repeat it 128 times (thus the first sector will contain 33-00-00-00-33-00-00-00... the second sector 33-00-00-01... and so on).

Guess you will want to learn some basics of the Ruby language, the most convenient object-oriented scripting language ever created!

I am still stalled on a (supposedly hardware or soldering) problem: I cannot get to the "idle" state; the R1_IDLE_STATE never appears (even after ten times more than the typical maximum of 512 loops it is still zero).

More news soon (I hope!).

Click here for helicopters!

home page - send e-mail - continua (next page)