Go Down

Topic: Run multiple SD cards on a single SPI bus. (Read 2 times) previous topic - next topic

GoForSmoke

I'm probably doing something wrong but I dunno what at this point.

I have 2 SD modules sharing power, ground, MOSI, MISO, and SCK, each with separate CS.

I want to be able to keep both open even if only 1 runs at a time.

With CD library you get an SDClass object instantiated for you, SD, that can handle 1 SD card.
So I made another that I called SD2. And I made 2 File objects so they'd each have their file info but I get the feeling either there's more or I went about this all wrong.

It runs. But it only sees the card on CS 10 even when I went and coded the CS pins to change.
There's primitive user i/o; d0 or d1 is supposed to select device, fwhoot makes the current file name whoot.txt, s## changes the state to ## where currently 2 checks for file exist and 3 opens file both using the current name and device except it always gets the same chip!


Code: [Select]

#include <SPI.h>

#include <SD.h>

#define CARD_0_CS 10
#define CARD_1_CS 9

SDClass SD2;
SDClass *sdcard = &SD;

#define BUFF_SIZE 512
byte buff[ BUFF_SIZE ];
byte *BP = buff;
int  count = 0;
int  numret = 0;

byte state = 0; // controls what operation is run
byte parstate = 0;
byte flag = 0;  // general use True/False
byte B;         // single byte buffer
char fname[ 14 ] = "text.txt";
File sdfile[ 2 ];    // File objects
byte CSpin = CARD_0_CS;
byte  i = 0;

int readSerialNum( byte SB )
{
  static  int total;

  if (( SB == ' ' ) || ( SB == 13 ) || ( SB == 10 ))
  {
    return total;
  }

  if (( SB < '0' ) || ( SB > '9' ))
  {
    total = 0; // initialize by SB == 0
    return  -1;
  }

  if ( total >= 3176 )
  {
    total = 0;
    return  -2;
  }

  total *= 10;
  total += ( SB - '0' );

  return  0;
}



void setup(void)
{
  Serial.begin( 9600 );
  pinMode( 10, OUTPUT );
  digitalWrite( 10, LOW );
  pinMode( 9, OUTPUT );
  digitalWrite( 9, HIGH );

  flag = SD.begin( CARD_0_CS ); // test if card is recognized
  Serial.print( "Card 0 status " );
  Serial.println( flag, DEC ); // show success as 1, fail as 0

  flag = SD2.begin( CARD_1_CS ); // test if card is recognized
  Serial.print( "Card 1 status " );
  Serial.println( flag, DEC ); // show success as 1, fail as 0

  Serial.println( "\nFinished\n"  );
}

void loop(void)
{
  switch ( state ) 
  {
  case 0 :
    {
      parstate = 0;
    }
    break;

  case 2 : // exists()
    {
      flag = sdcard->exists( fname );
      if ( CSpin == 10 )
      {
        Serial.print( "Card 0 " );
      }
      else
      {
        Serial.print( "Card 1 " );
      }
      Serial.print( fname );
      Serial.print( " exists? T/F " );
      Serial.println( flag, DEC ); // show success as 1, fail as 0
      state = 0;
    }
    break;

  case 3 : // open()
    {
      i = ( CSpin == 10 ) ? 0 : 1;
      sdfile[ i ] = sdcard->open( fname, FILE_READ );
      if ( CSpin == 10 )
      {
        Serial.print( "Card 0 " );
      }
      else
      {
        Serial.print( "Card 1 " );
      }
      Serial.print( fname );
      Serial.print( " opens? T/F " );
      Serial.println( flag, DEC ); // show success as 1, fail as 0
      state = 0;
    }
    break;

  case 4 : // close()
    break;

  }

  if ( Serial.available())
  {
    state = 255;

    B = Serial.read();

    switch ( parstate )
    {
    case 0 :
      {
        switch ( B )
        {

        case 'd' : // set device
          {
            parstate = 3; // d for set device CS pin 4 or 5
          }
          break;

        case 'f' : // set filename
          {
            *fname = 0;
            count = 0;
            parstate = 2; // f for set file name, next get name
          }
          break;

        case 's' :  // set state
          {
            readSerialNum( 0 );
            parstate = 1; // s for set state, next get value
          }
          break;

        }
      }
      break;

    case 1 :
      {
        numret = readSerialNum( B );

        if ( numret > 0 )
        {
          state = numret;
          Serial.print( "\nState changed to " );
          Serial.println( state, DEC );
          parstate = 0;
        }
        else if ( numret == -1 )
        {
          Serial.println( "\nNon-numeric in number." );
          state = 0;
        }
        else if ( numret == -2 )
        {
          Serial.println( "\nNumber too big." );
          state = 0;
        }
      }
      break;

    case 2 :
      {
        if (( B == ' ' ) || ( B == 13 ) || ( B == 10 ))
        {
          strcat( fname, ".txt" );
          Serial.print( "\nFile name set to " );
          Serial.println( fname );
          state = 0;
        }
        else if ( count > 7 )
        {
          Serial.println( "\nFile name too long." );
          state = 0;
        }
        else
        {
          fname[ count++ ] = B;
          fname[ count ] = 0;
        }

      }
      break;

    case 3 : // set device
      {
        if ( B == '0' )
        {
          sdcard = &SD;
          CSpin = 10;
          digitalWrite( 9, HIGH );
          digitalWrite( 10, LOW );
          Serial.println( "\ndevice set to 0, CS now 10" );
        }
        else if ( B == '1' )
        {
          sdcard = &SD2;
          CSpin = 9;
          digitalWrite( 10, HIGH );
          digitalWrite( 9, LOW );
          Serial.println( "\ndevice set to 1, CS now 9" );
        }
        state = 0;
      }
      break;
    }
  }

}



I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.


GoForSmoke

Got it to work with SdFat and the needed config file change, with my jumper lashup.
2 cards and starting with 460 bytes free ram! Not to mention 2 512 byte buffers on hand when either is not being used.

The SD modules have 2x8 rows of pins, it took me 7 female to male jumpers to connect 1 module and I have only 10 and wanted to run dual SD's. So I looked at a floppy cable and the headers have the right holes for pins and I notice that the end with the twist has > 16 wires from one end that don't twist. In fact the cable is 16 + 2 + 16 wires wide. So I plugged 1 module to one side of one end of the cable and the other module into the opposite side at the other end. The header in the middle is perfect for jumpering to a breadboard where I have the UNO pins broken out. I have a big bag of breadboard-breadboard jumpers.

The whole thing could be a lot cleaner, I have 2 sets of 3 lines to share and the CS to not.
Pity it works.


I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.


GoForSmoke

There is soldering wires to a micro-SD adapter too. Even with proper leveling the parts cost wouldn't come to much. Run around 3.3V and it's straight wire isn't it?

With 2 cards I can keep 2 files open, perform read and write without open-close-repeat and seek-setting, I dunno what else just nothing good.

Read or write, the operation proceeds by the clock. IIUC I should be able to write any size block 1 byte at a time as they come in, that there is no requirement to pre-buffer blocks, that the SD runs by the SCK and doesn't have time limits on data except for upper limits on speed.

I could serve data as a stream device even to block devices.. don't have to have lots of buffer.

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Go Up