Go Down

Topic: Can you help me solve problem with Ethernet reads then an SDFat file operation (Read 958 times) previous topic - next topic

advsoftware

Hi,

I need to know if this is a bug or a hardware related issue.

I am programming a sketch for the Mega (onbaord SD and ethernet) and have an issue after I call the ethernet client.read function more than once and then do an SDFat file operation.

It appears that if you call the ethernet client.read() more than once the SD card is not longer available.

Not matter what file operation I do I get :

Can't access SD card. Do not reformat.
No card, wrong chip select pin, or SPI problem?
SD errorCode: 0X1,0XFF

Error will occur after you connect with telnet to 10.1.1.25 and type READ

Code below reproduces the problem and I have included the output from the sketch below the code.

The loop will call the  ReadWriteTCPIP function that will read the incoming ethernet characters and store them in a global string. When the string contains the letters "READ" the SD file operation will occur. It fails on the  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();. But it can be any file operation.

Code: [Select]
#include <String.h>
#include <SPI.h>
#include <Ethernet.h>
#include <SdFat.h>


//// set up variables using the SD utility library functions:
Sd2Card card;
SdFat sd;
SdVolume volume;
SdBaseFile root;
SdFile currfile;

// change this to match your SD shield or module;
const int chipSelect = 53; 

byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEF};
int TcpipPort = 23;//2189;
EthernetServer server1(TcpipPort);
byte TcpipAddress[] = {
  10,1,1,10};
//  192,168,253,3};
byte ServerIPAddress[] = {
  10,1,1,25};
//  192,168,253,50};
byte GatewayIPAddress[] = {
  10,1,1,1};
//  192,168,253,1};
EthernetClient client1;

String inbuffer(512);
String TCPinput = "";
boolean bTCPClient;

void setup() {
  //Debug to serial monitor
  Serial.begin(115200);

  // Setup SD Card
  SDCardSetup();
 
  //InitializeTCPIP
  InitializeTCPIP();

}

void loop() {
   
      ReadWriteTCPIP();
      }

//
void InitializeTCPIP()
{
  // Setup IP address of the server you're connecting to:
  bTCPClient = false;
       Serial.println("Configuring TcpipAddress");
  IPAddress remoteserver(TcpipAddress);
       Serial.println("Configuring ServerIPAddress");
  Ethernet.begin(mac, ServerIPAddress);
       Serial.println("Starting TCPIP Server");
  server1.begin();
       Serial.println("...Started");
       Serial.println("Now Telnet 10.1.1.25 and type in capitals READ");
}

// SD Card Setup
void SDCardSetup()
{
   pinMode(53, OUTPUT);     // change this to 53 on a mega

  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  //if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card is inserted?");
    Serial.println("* Is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    return;
  }
  else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.print("\nCard type: ");
  switch(card.type()) {
  case SD_CARD_TYPE_SD1:
    Serial.println("SD1");
    break;
  case SD_CARD_TYPE_SD2:
    Serial.println("SD2");
    break;
  case SD_CARD_TYPE_SDHC:
    Serial.println("SDHC");
    break;
  default:
    Serial.println("Unknown");
    break;
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(&card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  if (volumesize < 0X800000) {
    volumesize *= 512;                        // SD card blocks are always 512 bytes
    Serial.print("Volume size (bytes): ");
    Serial.println(volumesize);
    volumesize /= 1024;
  }
  else {
    volumesize /= 2;
  }
  Serial.print("Volume size (Kbytes): ");
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);

  root.openRoot(&volume);

  // list all files in the card with date and size
  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.ls(LS_R | LS_DATE | LS_SIZE);
}

void ReadWriteTCPIP()
{
// Serial.println("ReadWriteTCPIP");
  SdFile currfile;
  String tagdata = "";

  // listen for incoming clients
  client1 = server1.available();

  if (client1)
  {
    // If client is connected.
    if(client1.connected())
    {
      Serial.println("Client Connected");
      int Count = 0;
      int x = 0;
      if (client1.available())
      {
        Serial.println("Receiving for incoming data (1st Time SD Works");
        Serial.println("Second time through here reading a char the next SD operation will fail.");
[color=red]       char c = client1.read();[/color]
        TCPinput.concat(c);
   
    Serial.println(TCPinput);
        if  (TCPinput.indexOf("READ") >= 0)   //")
        {
   [color=red] Serial.println("Do File Operation that will fail");
          //Find Oldest SDRam Queue File
          // open next file in root.  The volume working directory, vwd, is root
          if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();[/color]
         
          if (currfile.openNext(sd.vwd(), O_READ ))
          {
    Serial.println("Sending File");
            tagdata = "";
            if ((currfile.isOpen() != true) && (currfile.isFile()==true) ) //&& (TCPinput.indexOf("READ POLL") >= 0)
            {
              //while (currfile.available()) AND (input != "")
              while (((tagdata += currfile.read())>=0) && (TCPinput != ""));

              tagdata.concat("<OK>");

              client1.println(tagdata);
    Serial.println("Sent OK");
              //Serial.println("Removing File");
              //currfile.remove();
              currfile.close();
    Serial.println("Closed File");
            }
            else
            {
    Serial.println("Close File Dir of non file");
                 currfile.close();
            }
          }
          else// NoFiles so Nothing to send to server
    Serial.println("TCPIP Nothing to send");
        }
      }
    }
  }
}


Output from the test sketch:

Wiring is correct and a card is present.

Card type: SD2

Volume type is FAT16

Volume size (bytes): 2030960640
Volume size (Kbytes): 1983360
Volume size (Mbytes): 1936

Files found on the card (name, date and size in bytes):
13164620.TXT   2000-01-01 01:00:00 17145
13164826.TXT   2000-01-01 01:00:00 7
13164929.TXT   2000-01-01 01:00:00 7
13171646.TXT   2000-01-01 01:00:00 9
Configuring TcpipAddress
Configuring ServerIPAddress
Starting TCPIP Server
...Started
Now Telnet 10.1.1.25 and type in capitals READ
Client Connected
Receiving for incoming data (1st Time SD Works
Second time through here reading a char the next SD operation will fail.
R
Client Connected
Receiving for incoming data (1st Time SD Works
Second time through here reading a char the next SD operation will fail.
RE
Client Connected
Receiving for incoming data (1st Time SD Works
Second time through here reading a char the next SD operation will fail.
REA
Client Connected
Receiving for incoming data (1st Time SD Works
Second time through here reading a char the next SD operation will fail.
READ
Do File Operation that will fail
Can't access SD card. Do not reformat.
No card, wrong chip select pin, or SPI problem?
SD errorCode: 0X1,0XFF

Thanks in advance.

advsoftware

Problem solved.

You need to use the digitalWrite to set pin 4 low on the Mega with the freetronics ethernet when you want to use the SD card and set the ethernet pin 10 high. Then the opposite before using the ethernet. I created a couple of functions to do this and call them where required.

Also very important to set the PIN modes for both to OUTPUT before doing any intialization of the SD or the Ethernet.

I hope this helps someone, and avoids the 3 days of searching spent on this problem.

  pinMode(10,OUTPUT);     // Ethernet Pin select  must be set to OUTPUT
  pinMode(4, OUTPUT);      // SD Pin select  must be set to OUTPUT

void SetTCPIPMode()
{
//set its SS pin (10) Low, and the SD card's SS (4) pin High
digitalWrite(10, LOW);       // select ethernet mode
digitalWrite(4, HIGH);       // deselect SD mode
}

void SetSDCardMode()
{
//set its SS pin (10) HIGH, and the SD card's SS (4) pin LOW
digitalWrite(4, LOW);       // select SD mode
digitalWrite(10, HIGH);       // deselect ethernet mode
}

Go Up