Pages: [1] 2 3 ... 13   Go Down
Author Topic: SD card read/write with Arduino  (Read 101006 times)
0 Members and 2 Guests are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I started a topic in the development section a while ago about getting an excellent sd/mmc card library (http://www.roland-riegel.de/sd-reader/index.html) working in Arduino. After lots of tinkering, and some help from another user (strohhalm who found some fixes in the german forum for the roland-reigel library) it seems to work ok. FAT reading and writing will have to wait until some larger memory arduinos are available as it uses almost all of the memory, leaving no space for further code.

The schematic uses some resistors in a voltage divider to drop down the arduino 5v logic to the sd cards 3v3 logic. So all outgoing signals from the arduino are dropped to 3v3. Incoming signals to the arduino are fine because 3v3 is above logic 1 for arduino. The 3v3 voltage supply from the decimelia was used to supply power to the sd card.
 
The schematic (all top resistors are 1.8k, all bottom resistors are 3.3k):



The circuit built on a prototype board. I desoldered an sdcard socket from a broken memory card reader and then soldered pins onto the bottom. There is a thermistor connected to analog1 with some resistors for testing purposes. (The other stuff is a real time clock and its parts)



I've cutout all the unnecessary files from the roland reigel library and applied the fixes to leave just raw sd card reading and writing. This lets you write and read byte values from an sd card. It's very simple to use. I haven't tried to convert it to a cpp library. Copy the files into the library directory in the arduino build environment. (e.g. for me it is arduino-0011/hardware/libraries/SDcard ). Once you do that and restart the build environment you should be able to select SDcard as an added library and it will add the necessary includes.

The library can be downloaded here: http://www.mediafire.com/?2belzmmnzml
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is the code for a very basic data logger which shows how to use the library. When the library starts it reads the card info and prints it out. It takes samples from analog in 1 and writes them to the sd card when you send an 's' over serial.  You can read back the sd card by sending an 'r'. Sending 'q' stops sampling.

I haven't done much testing about read and write speeds or buffer size, in this example I'm only storing 2 bytes in a temporary buffer and then writing them to the card.  

Code:
#include <sd-reader_config.h>
#include <sd_raw.h>
#include <sd_raw_config.h>





int print_disk_info();
int sample();
int readDisk();

byte incomingByte;
void printWelcome();
long int address;
byte tempBytes[2];


void setup()
{
  
  Serial.begin(9600);
  delay(1000);

  printWelcome();
  if(!sd_raw_init())
  {
     Serial.println("MMC/SD initialization failed");      
  }
  print_disk_info();
}



void loop()
{
    int i;    
    
    if(Serial.available()>0)
    {
         incomingByte=Serial.read();
    
       switch(incomingByte)
       {
           case 114:
                     readDisk();
                     break;
           case 115:
                     sample();
                     break;
           default:
                     break;
       }
    }    
}

int sample()
{
    int i,j;
    int temp;
    byte low;
    byte high;
    byte inByte;
    
    Serial.println();
    Serial.println();
    Serial.println("Sampling..");
    for(i=0;i<500;i=i+2)
    {
        if(Serial.available()>0)
        {
            inByte=Serial.read();
            if(inByte==113) return 0;
        }
        temp=analogRead(0);
        Serial.print(temp,DEC);
        Serial.print(" ");
        
        //Convert int to 2 bytes
        low=temp&0xFF;
        high=temp>>8;
       // Serial.print(temp,DEC);
        //Serial.print(low,DEC);
        //Serial.print(high,DEC);
    
        tempBytes[0]=low;
        tempBytes[1]=high;
        
        if(!sd_raw_write(i,tempBytes,2))
        {
          Serial.print("Write error");
        }
        //sd_raw_sync();
        delay(5000);
        
  Serial.println();
      
    }
    
    return 1;
}


int readDisk()
{
    byte low;
    byte high;
    byte info[2];
    int i;
    int  result;
    Serial.println();
    for(i=0;i<50;i=i+2)
    {
        sd_raw_read(i,info,2);
  
        //Serial.print(info[0],DEC);
        //Serial.print(" ");
        //Serial.print(info[1],DEC);
        low=info[0];
        high=info[1];
        result=high<<8;
        //result<<8;
        Serial.print(" ");
        Serial.print(result+low,DEC);
        Serial.print(" ");
    }
  
}

void printWelcome()
{
    Serial.println("------------------------");
    Serial.println("Data sampling system");
    Serial.println("send r to read disk");
    Serial.println("send s to start sampling");
    Serial.println("send q to stop sampling");
    Serial.println("Ready.....");
    Serial.println("-------------------------");
}


int print_disk_info()
{
 

    struct sd_raw_info disk_info;
    if(!sd_raw_get_info(&disk_info))
    {
        return 0;
    }

    
    Serial.println();
    Serial.print("rev:    ");
    Serial.print(disk_info.revision,HEX);
    Serial.println();
    Serial.print("serial: 0x");
    Serial.print(disk_info.serial,HEX);
    Serial.println();
    Serial.print("date:   ");
    Serial.print(disk_info.manufacturing_month,DEC);
    Serial.println();
    Serial.print(disk_info.manufacturing_year,DEC);
    Serial.println();
    Serial.print("size:   ");
    Serial.print(disk_info.capacity,DEC);
    Serial.println();
    Serial.print("copy:   ");
    Serial.print(disk_info.flag_copy,DEC);
    Serial.println();
    Serial.print("wr.pr.: ");
    Serial.print(disk_info.flag_write_protect_temp,DEC);
    Serial.print('/');
    Serial.print(disk_info.flag_write_protect,DEC);
    Serial.println();
    Serial.print("format: ");
    Serial.print(disk_info.format,DEC);
    Serial.println();
    Serial.print("free:   ");
  
    return 1;
}




« Last Edit: March 30, 2008, 06:05:03 am by agent_orange » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 56
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Will this work on the atmega8 ?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 35
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

excellent, given the fat / sketch size limitation ... could you fit the sd/fat library on a atmega, then interface that chip with simple commands via i2c?

like have a master arduino and a slave arduino, the slave only handling sd/fat interactions.
Logged

Norway
Offline Offline
Sr. Member
****
Karma: 0
Posts: 370
R-Doo-Inoo in the making :3
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

would this be a good project for the dual core in this same section?
Logged

B-dui in creation.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 40
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You have plenty of space if you don't use the fat library and just the raw sd card commands. Its just like having a 1G eeprom that is easy to use  smiley. Probably the best thing to do would be to wait until the atmega328p chip is available and works in the arduino and then you would have more than enough for the fat library and any code you want.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 207
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's good work, Mr Orange, and thanks for sharing.

Regards,

Mike
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm having some trouble getting it working on a arduino Mini04. Everything worked when I tested it out on the Diecimila, but I'm getting the "MMC/SD initialization failed" message on the Mini.

Any ideas?

Regardless of my troubles, this is great!
Logged

Grenoble/Lyon - France
Offline Offline
Sr. Member
****
Karma: 0
Posts: 363
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Really nice! I was hoping to see something like that, that will really help me debugging my projects. For instance, for the monome clone, I can finally dump the serial received (well, I could have done it to the eeprom) as the serial communications isn't with the arduino IDE but with monomeserial, so I can't see real time what is received. This way, I save it, upload a new sketch, read the SD, and hopefully finish to implement the monome protocol ^^

Thanks again ^^
Logged


0
Offline Offline
Jr. Member
**
Karma: 1
Posts: 79
Combat, please!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could also use my uFat library.

It's a kind of halfway-house solution between a full-fat and a fat-free solution. (Sorry couldn't resist it.) Basically you get to read and write sectors within files that you pre-allocate on a PC.

It's a really simple interface. 1. Get the base sector for a named file on the card. 2. Use it!

Naturally there's a couple of minor restrictions, but that's how trade-offs work, right smiley-wink

Read more about uFat here: http://arduinonut.blogspot.com/2008/04/ufat.html

I'll be happy to help with any queries. PM or mail me.

Charlie
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 239
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

if you just want to log data (and not necessarily read it) i have an sdlogging library that saves to fat16 formatted SD cards.  i use it to log GPS & sensor data: http://www.ladyada.net/make/gpsshield/download.html
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 3
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you want fat support, couldn't you theoretically throw it on the first portion of the SD card itself and then access it that way? I'm not intelligent enough to implement such a thing, but I thought I'd throw it out there. Would you have to modify the Arduino bootloader in order to get it to read a sketch from a foreign memory source? Is it even possible?
Logged

Seattle
Offline Offline
Newbie
*
Karma: 0
Posts: 46
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

 Hi Charlie - your uFAT library looks interesting, but I haven't been successful with it so far.

Has anyone else gotten it working?

I have an SD setup just as described at the top of this thread. I am able to demonstrate 'raw' SD I/O successfully using the SD raw library and the demonstration sampling app with two different SD cards.

I have downloaded and built mmc1.rar and it compiles and upload successfully. You don't directly state the pinouts, but they appear the same as the schematic above from the code. It correctly detects the presence of the SD card (or its removal), but it never gets past mmc::initialize.

I'd love to get this working - any ideas for me to try?

Thanks, harry
http://www.creatrope.com/blog/make/uduino-arduino-board-support/

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mr. Orange-

I had no trouble getting your code up and running in 15 minutes - happily logging, saving, and reading the input to analog1.

However, after hitting the arduino reset button, I found that the read function returns junk(from the SD card).

Shouldn't the SD card retain data after a power cycle? or, is it a function of the code that you so nicely supplied to get me started - and I just don't understand it, yet?
Logged

Seattle
Offline Offline
Newbie
*
Karma: 0
Posts: 46
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi - I wanted you to know that I got the mmc1.rar code for uFAT working, just as advertised. My problem was that a makeshift 3.3v supply from a voltage divider seemed to work for the raw SD write, but not for the full uFAT mmc code.  

I cobbled together a 'real' variable power supply capable of producing 3.3v from http://www.ladyada.net/library/equipt/diypsupp.html, which worked flawlessly and the uFAT code worked correctly.

A few 'tricks':

Your card must be formatted FAT16, not FAT32. Under windows, if you see FAT32 and FAT, the 'FAT' is FAT16 and the partition must be less than 2G.

It hasn't been explicitly mentioned but the wiring for uFAT is indeed the same as the raw SD write above.

The demonstration file that uFAT writes to is fred.txt . If you just create fred.txt in windows be sure you really get fred.txt and not fred.txt.txt!  If necessary, enter the command shell and mv fred.txt.txt to fred.txt.

To answer ducttapepro6, I verified that the newly written files are 'static' on the SD card using uFAT as one would expect.
Logged

Pages: [1] 2 3 ... 13   Go Up
Jump to: