Go Down

Topic: sd card (Read 5 times) previous topic - next topic

carl47

This class was written for the Arduino library.
It reads and writes directly to sectors on a sd card.

It has only two functions:

SDCARD.readblock(sector number); //read 512 bytes from this sector
SDCARD.writeblock(sector number); //write 512 bytes to this sector

The 512 bytes are read/write from a buffer which must be declared:

volatile unsigned char buffer[512] ;  //contains the 512 bytes to read/write

This class was written for my Arduino 2009 weather station.
I want to log up to 10 sensors for an extended period when the Arduino is not
connected to the computer.
To save a sample every  second over 12 months requires:

total bytes = 2 x 10 x 60 x 60 x 24 x 365 = 640 Mb

I use a 1.0Gb card.

The functions can both return a error value:

error = SDCARD.writeblock(sector);
error = SDCARD.readblock(sector);

If the card read/write does not work due to card failure or removal
the error will be greater than 0.
In my application this would mean the program can no longer operate.
In this case I send an error message instead of the normal samples
from the weater station.

This class does not use a FAT. Data is read/write to a sector direct.

The sd card circuit, the library and other files are at the site given below.
Download sdcardlibrary.zip

http://sourceforge.net/projects/arduinoweather/files/

If you have a 3.3v arduino the level change circuits will not be needed.

An example program to read/write to one sector is:

Code: [Select]
/* Connect sd card as shown in circuit diagram.
  Copy SDCARD folder into arduino-0017/hardware/libraries.
  This code will write/read directly to a sector on the sd card
    sector number 0 to 1980000 for a 1.0GB card.
*/

#include <SDCARD.h>
volatile unsigned char buffer[512] ;  // this 512 bytes read from or written to sd card
unsigned long sector = 99999;  // the sector we will write or read from
int error = 0;  //the error will be 0 if the sd card works

void setup()                    // run once, when the sketch starts
{
Serial.begin(9600);                     // initialize serial communication with computer
}

void loop()                     // run over and over again
{
  if (Serial.available() > 0)   // do nothing if have not received a byte by serial
  {
   int inByte = Serial.read();
   if (inByte == 'r')  // send a "r" to start the read / write sector process
   {
     int i = 0;  //general purpose counter
       for(i=0;i<512;i++)
     buffer[i]=199;      //fill the buffer with a number between 0 and 255
     
      error = SDCARD.writeblock(sector);  //write the buffer to this sector on the sd card
     
      if (error !=0)
    {
        Serial.print("sd card write error... code =  ");
        Serial.println(error);      
    }//end of if we have an error
     
     error = SDCARD.readblock(sector);  //read into the buffer this sector in sd card

        if (error !=0)
    {
        Serial.print("sd card read error... code =  ");
        Serial.println(error);      
    }//end of if we have an error
     else
    {
      int number =0;
      for(i=0; i<512; i++) //read 512 bytes
    {
      number = buffer[i];    //convert to integer      
      if(((i % 8) == 0) & ( i != 0))  
      Serial.println("");   //write 8 then start a new line
      Serial.print(number);
      Serial.print("  ");   //tab to next number
    }//end of read 512 bytes
    }//end of else we have no error
   } //end of received "r"
  }//end of serial available
}//end of loop

walterr

I like your approach. How much program memory does your library take up?

carl47

The read and write functions together use 1010 bytes of program memory.

This is a very small size because the sdcard library is written using the KISS principle.

However it does lead to limitations:
Cant use MMC cards.
Cant use old(ver.1 cards)- about before 2006.
Cant use HC sd cards(>2 GB)

Also you can see that it uses 512 bytes of RAM.

For the arduino 2009 this alocation of flash(32k) and ram(2k) is not a problem for my application

carl47

I added another example to my sd card class.
This is a program to check every byte on the sd card.

Code: [Select]
/* Connect sd card as shown in circuit diagram.
  Copy SDCARD folder into arduino-0017/hardware/libraries.
  This code will write/read directly to a sector on the sd card
    sector number 0 to about 1980000 for a 1.0GB card.
  This program writes 199 to every byte on the sd card.
  It will only stop when it gets read/write or memory error.
  We hope that is after the very last byte of the sd card.
*/

#include <SDCARD.h>
volatile unsigned char buffer[512] ;  // this 512 bytes read from or written to sd card
unsigned long sector = 0;  // the sector we will write or read from
int error = 0;  //the error will be 0 if the sd card works
unsigned long errormillis = 0;        // the time when error occured

void setup()                    // run once, when the sketch starts
{
Serial.begin(9600);                     // initialize serial communication with computer
}

void loop()                     // run over and over again
{
 for (sector=0; sector<4000000 ; sector++)
 {
     int i = 0;  //general purpose counter
       for(i=0;i<512;i++)
     buffer[i]=199;      //fill the buffer with a number between 0 and 255
     
      error = SDCARD.writeblock(sector);  //write the buffer to this sector on the sd card

      if (error != 0)
        errormillis = millis();   //remember the time had error
      while (error !=0)  //we stay in this loop
    {
        Serial.print("sd card write error... code =  ");
        Serial.println(error);
        Serial.print("write error at sector=  ");
        Serial.println(sector);
        sendtime();
        delay(1000);   //send every second      
    }//end of if we have an error
   
       i = 0;  //general purpose counter
       for(i=0;i<512;i++)
     buffer[i]=0;      //clear the buffer
     
     error = SDCARD.readblock(sector);  //read into the buffer this sector in sd card

        if (error != 0)
        errormillis = millis();   //remember the time had error
        while (error !=0)   //we stay in this loop
    {
        Serial.print("sd card read error... code =  ");
        Serial.println(error);
        Serial.print("read error at sector=  ");
        Serial.println(sector);
        sendtime();
        delay(1000);   //send every second      
    }//end of if we have an error
   
     
      for(i=0; i<512; i++) //read 512 bytes
    {
     if (buffer[i] != 199)
     errormillis = millis();   //remember the time had error
     while (buffer[i] != 199)  //we stay in this loop
     {
        Serial.print("memory error at byte =  ");
        Serial.println(i);
        Serial.print("memory error at sector=  ");
        Serial.println(sector);
        sendtime();
        delay(1000);   //send every second      
     }//end of we have a memory error
    }//end of read 512 bytes
   
    if (sector % 100 ==0)
    {
      errormillis = millis();   //remember the time
      Serial.print("we have no errors up to sector =  ");
      Serial.println(sector);
      sendtime();
    }//end of ever 10 sectors
 }//end of 4000000 sectors done
}//end of loop

void sendtime()
{
        Serial.print("elapsed time hours= ");
        Serial.print(errormillis/3600000);
        Serial.print("  elapsed time minutes= ");
        Serial.print((errormillis/60000) % 60);
        Serial.print("  elapsed time seconds= ");
        Serial.println((errormillis/1000) % 60);
}//end of send the time


My 1.0GB sd card had its first error at sector 1984000.
That is after 1,015,808,000 bytes which must be the highest
number of bytes available on the card.

Each read or write takes 44 msec on the Arduino 2009.
The full program run took 49 hours and 24 minutes.
This is 89 msec for each write, read and check.

If anyone has tried my sd card class, some feedback would be appreciated.
:)

stolken

Hey,
It look very nice and well commented but I have a question :
I use a sd card shield I bought from nuelectronics.
MOSI, MISO, CLK pins are the same as your, but the chip select pin is not PB2 like in your shematics. The chip select is wired to PD5 pin, how can I fix it ?
Sorry for my bad english ...  :-[

Go Up