Show Posts
Pages: 1 ... 4 5 [6]
76  Forum 2005-2010 (read only) / Exhibition / SD/MMC From the ground up on: February 20, 2009, 05:23:32 am
A number of people have asked if the information in the thread "SD card read/write with Arduino" be summarised for newcomers.

Well here it is. After reading this you should be able to:
  • Add an SD/MMC card to your Arduino.
  • Read data from and write data to it using the uFat and DevicePrint libraries.
  • Understand a few of the issues related to the process.
This is my own personal take on the subject and I can only offer descriptions of and advice on using the code which I developed, so apologies if this comes over like an advert at times - it's truly not meant to be. I hope that opinions and advice about other code available will be added in subsequent posts and that this thread can be a focal point for those wising to take advantage of the work that has been contributed by the Arduino community at large.

On with the show.

MMC cards are a microcontroller's best friend. They can speak a serial protocol called SPI which is natively supported in the microcontroller hardware. I love 'em. You only need 4 IO lines to transmit commands and data to the card and receive data back. These connections go by a number of names but this is the set which will service you best:

/CS  (not card select)
CLK  (clock)
MOSI (master out, slave in)
MISO (master in, slave out)


Master in all cases is the Arduino. Digital pins 10 through 13 are the dedicated SPI connections. If your application already uses these you'll have to move things around! All the SD/MMC enabled boards I've seen use these pins. The information here should be applicable to anyone's SD/MMC enabled hardware.

Here's the MMC pinout...



...and here's how it needs to be connected:

MMC   Arduino
 1       10
 2       11
 3      gnd
 4      3v3
 5       13
 6      gnd
 7       12


MMC Cards require between 2.7 and 3.6 volts to operate. Low power varieties are also available that work down to 1.8V, though these are special and more rare. You can power a card from the Arduino's 3v3 output if it's available on your particular Arduino variety. There will need to be some level conversion on the /CS, CLK and MOSI lines, as these output 5V. As the Arduino regards 2.4V and above as a logic high, no level conversion needs to be done on the MISO line. There are some boards out there which operate at 3.3V natively, and for these boards all lines may be connected directly.

We do any neccessary 5V level conversion in the simplest way possible: with a voltage divider. There is great information elsewhere, linked below, so I won't go into any more detail than this:

VDD --[R1]-- v --[R2]-- GND

The voltage v can be calculated by using the following formula:

v = (VDD*R2) / (R1+R2)

In most cases you should use R1 = 1K8 and R2 = 3K3. Tapping the voltage at the centre of the resistor/resistor connection yields ~ 3.24V. Actual values will vary a little depending on the accuracy of the resistors.

Some cards can cope with voltages out of the specified range, and some cannot. I have cards which have functioned happily as high as 4.3V, and one in particular which developed a high fever followed by sudden explosive death when faced with the same levels... Ahem. The less said about that the better.

The product standard dictates the signal levels that you should aim for in your circuit.

Input HIGH voltage:
  • min:  0.625 * VDD
  • max:  VDD + 0.3
Input LOW voltage:
  • min:  VSS - 0.3
  • max:  0.25 * VDD[/tt]
Here is what I consider to be the gold standard schematic produced by agent_orange, to be found with other good stuff at the start of the parent thread.



There are 3 kinds of socket available. MMC, SD and floppy-drive edge connector smiley-grin
  • MMC sockets have 7 connectors and map 1:1 to the diagram above.
  • SD sockets can have up to 12 or 13 pins, but only the main 7 need to be used. The remainder are for detection of card insertion and write protect status of compatible SD cards. agent_orange's schematic shows a socket of this type.
  • Floppy edge-connector sockets are best for MMC cards (SD cards are thicker with ridges protecting the contacts) but are undoubtedly the cheapest! Check out the ingenious hack at Up All Night Robotics, linked below.
There are many excellent introductions to the SPI protocol and I don't think that a discussion of it here would benefit anyone except the most inquisitive. There are a couple of links at the end of the post which should satisfy these curious cats.

It might not even help to discuss the MMC's command protocol over and above the fact that data transfers happen in 512 byte blocks. This can be changed, but I don't think there's a compelling reason to do this, especially as this most usually matches the sector size of the card.

<Next>
77  Forum 2005-2010 (read only) / Exhibition / Re: Serial Data Logger to SD card on: May 07, 2009, 01:00:59 pm
You're right. I've updated the original post.

Thanks smiley-wink
78  Forum 2005-2010 (read only) / Exhibition / Re: Serial Data Logger to SD card on: May 07, 2009, 04:34:16 am
Hi Garrett,

All I can offer in terms of advice is:

* Get things working one component at a time. Serial reception, then storage. Attempting to troubleshoot 2 systems at once is going to give you a big headache!

* Concentrate on the types of data you're receiving, and working out the simplest conversion. It's very important that you understand the data types and how the compiler manages the conversion between them.

Here's some code that buffers data for you. You'll need to experiment with the buffer size to achieve a steady data flow. You will need to write as much data as you can without missing the incoming data.

If you can afford 512 bytes, then do so as this is the unit size of data transfer for mmc/sd. I assume the library has a special case for this block size - if it doesn't then consider changing to one that does. I can't help with specifics as I'm not familiar with this library.

Once this code works for you, then add the record-enable code around it.

Code:

int bufferIdx = 0;
byte buffer[512];

void loop(void)
{
  while(Serial.available())
  {
    byte val = (byte)Serial.read();
    if (bufferIdx == 512)
    {
      FileLogger::append("GPS.txt", buffer, 512);
      bufferIdx = 0;
    }
    buffer[bufferIdx] = val;
    ++bufferIdx;
  }
}


Hope this helps,

Charlie


PS: Why do you think uFat can't write to large files? uFat can address every sector on a card, as long as the file being written to is pre-allocated. It may not be the ideal solution for all tasks, but when you need tiny code it's unbeatable IMHO smiley-wink

**edited to fix code**
79  Forum 2005-2010 (read only) / Exhibition / Re: Motion activated water cannon on: February 20, 2009, 09:56:07 am
I know two little boys who'll love this! Top marks!
Pages: 1 ... 4 5 [6]