Sunteți pe pagina 1din 4

Arduino + SD

1 of 4

http://www.alfonsomartone.itb.it/kfmdxc.html

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):
"pin 13" (PB5): SCK (slave clock input, master clock output: sadly this Arduino pin
has a SMD LED which now we cannot use anymore for software debugging); goes to
"pin 5" of the SD-card;
"pin 12" (PB4): MISO (master in, slave out: the only "input" pin of these four); goes to
"pin 7" of the SD-card (its data output);
"pin 11" (PB3): MOSI (master out, slave in); goes to "pin 2" of the SD-card (its data
input);
"pin 10" (PB2): SS- (slave select, active low); goes to "pin 1" of the SD-card (its
chip-select);
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:
SCK goes to Arduino's SCK (see above)
CS goes to SSDI goes to MOSI
DO goes to MISO
GND and GND1 go to Arduino's ground
VCC goes to Arduino's 3.3V source
other SD-card pins are not needed (I am not that in a hurry to waste two Arduino
pins to just check that the SD-card has not been locked on its write-protect switch).
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

03-Oct-14 3:19 PM

Arduino + SD

2 of 4

http://www.alfonsomartone.itb.it/kfmdxc.html

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
/dev/disk2s1

1K-blocks
994432

Used
0

Avail Capacity
994432
0%

Mounted on
/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.

03-Oct-14 3:19 PM

Arduino + SD

3 of 4

http://www.alfonsomartone.itb.it/kfmdxc.html

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:
have a FAT-formatted SD-card containing one large single file
have an Arduino application accessing the file (read/write) using only single sector
read/write operations, without having to deal with the FAT structure
access later the large file (modified by Arduino application) on the desktop
computer.
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!).

03-Oct-14 3:19 PM

Arduino + SD

4 of 4

http://www.alfonsomartone.itb.it/kfmdxc.html

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

FROM AROUND THE WEB

Hen learns to
count to seven
BWNToday

Girl, 11, accused


of being pregnant
really has 19
pound tumor

Angry man throws Man avoids jail


his feces at police after mistakenly
officers (video)
picking up wrong
BWNToday
girl from school

BWNToday

BWNToday

World Toilet Day


celebrated in 53
countries

The Breast Milk


Baby now on sale
at U.S. retailers

Car key penetrates Hotel proud to be


mans foot during named world's
karate class
worst hotel

BWNToday

BWNToday

BWNToday

Postal worker
claims she threw
money in the
garbage
BWNToday

Others tried it and


loved it
Glispa

BWNToday
Ads By OffersWizard

03-Oct-14 3:19 PM

S-ar putea să vă placă și