SD-SPI problem when reopening a file

Dear all,

Thanks for reading this topic and maybe helping me by solving my problem.

Short introduction
I'm working on a device to test some filter units. I think I'm quite near to the goal of this project, but this time some very bad things happen when running the program. After hours and hours of googling (around 30 hours) I still didn't find anything, so there are two possible reasons why I can't find an answer:

  1. It's a very stupid problem and will not see the answer
  2. It's a very uncommon problem and because of this I can't find anything.
    It’s the first program of mine, which has such a big size, so everything is quite new for me, and I will be also pleased about other feedbacks of to this program.

What the program should do
I will run filters for a long term test and figure out its capacity. Therefore I run the device for a long term test by using defined dirt water. At the end there should be several tests on the same test bench, but now I only will test one. So something in the program are prepared to multiple tests at the time and something needs to get updated later.

Environment
I’m using the IDE version 1.6.5 combined with Notepad++ as external editor. The TFT-display and the SD card reader are the here shown device.
I use several tabs, for each subtask is one tab, for the special types (my own structs) and also one for all #defines . Some of this tasks are still empty, these aren’t implemented yet, but will follow soon. Further I’ve build my own class, FilterDummy. The “Dummy” is because it only returns random values this time for testing the software. I’m using an Arduino due.

Structure of the program
The program starts and do the following steps:

  1. Initialize some variables
  2. Initialize port 13, sometimes I use it for debugging
  3. Initialize the serial communication
  4. Initialize SPI for TFT-screen
  5. Initialize a que for events (later more)
  6. Initialize the TFT-screen (by running it’s routine the first time)
  7. Initialize the file system (figure out the number of the current test and generate new folder)
  8. Initialize all Interrupts
  9. Set the analogreadresolution to the maximum
  10. Initialize my array of objects from filterunits

After the initialization every interrupt just generate a short event (eg. Increase a count or add an event to my que of events). Every 0.1 s it refreshes the display if the que is empty. The program is only controlled by interrupts and the resulting events (and the periodically refreshment of the screen).

There are several finite state machines (FSM) for controlling the different states. One for the display states and one for the events.

My problem
When initializing the file system the program checks if the file “ReadMe.txt” exists, if not it generate a new one. In this file is a ongoing number for the current test (so the program will not overwrite the last test). If it exists, the program reads the number of the next test, increase the number in the file, and close it. A folder is generated with the number of the next test and a .csv file in it for each filter unit, which I like to check. So far the program works perfectly, the display shows the state, the files are made. Now the initialization of the filter is done, and the files should be extended. In the example I try to make new files, after pressing the green button in the state “START_SCREEN” (or even to open an existing file). This happens in the routine “void writeTestValue()”. Here fails the program. I weren’t able to figure out what’s the reason for this. I spent so much time, tried all things I read in the internet but was not able to figure out the problem. I saw that the files get initialized well the first time when running the SD library (also increasing the number, opening files and generating new files)

The code
Bellow I’ve attached the whole program including the following things:

  1. All tabs of the IDE
  2. The Output on the SD card, when restarting the program twice
  3. The oscilosope screens (later more)
    The code of the problematic routine is on the first post in the Topic (see note on bottom)

Some reasons
While looking for a solution I also analyzed the output of the SPI-interface on a oscilloscope. And I saw that there are two different situations:

  1. Situation:
    While initializing the SD.open() works perfectly, chip gets selected and read/write-access is done fine. the Here is the screen from the oscilloscope. The channels are the following:
    A: CS of SD-Card, Blue
    B: CS of TFT-screen, Red
    C: MOSI, Green
    D: MISO, Brown
    The trigger goes to the falling edge of CS from the SD-Card.

  2. Situation:
    After the setup routine by pressing the green button it should generate or open some files, here is a problem. The SPI interface will not communicate with the SD-Card, but I did everthing the same way like in the first sitatione, expected initializing the SD-card (by using SD.begin(PIN_CS_SD) ). I set Pin 13 to High, when entering the routing so it’s clearly visible in which timespan the routine is working (I added a little delayMicroseconds at the end. Here is the second screen shown.
    A: CS of SD-Card, Blue
    B: Pin 13, Red
    C: MOSI, Green
    D: MISO, Brown

Some conclusions

  1. The wiring should be correct, it works fine the first time
  2. I think the problem is in the file “FileSystem.Ino” or in the file “currentVersion.ino”
  3. Once I exclude the TFT-library (and commenting all this things out) and it still doesn’t work, so I conclude that it shouldn’t be a problem between this two different usages of the SPI-interface.

Thanks for reading this post, I would be really thankfull if someone knows the answer. I hope I haven’t overseen something while use google and the search functions, otherwise I will appologice for doing my investigations not properly.

Many Thanks and best regards
Jérôme

For a shortern reading (whithout downloading the whole code) I add the code to the first post in this Topic. By adding the code to this post, the lenght will exceed the maximal lenght for a post

AllFiles.zip (16.4 KB)

Here the code from the most problematic file, which is described on top.

//Includes all important functions and the statemachine for the filesystem

#include "Defines.h"
#include "Types.h"
#include <SD.h>

//Class variables
static File _dataFile [NUMBER_OF_FILTERS];
static int _numberOfCurrentTest=0;

//================================================================================================================//
//=========================Suchen der aktuellen Nummer und erstellen des Files====================================//
//================================================================================================================//

int initFile ()
{
	char _readFromFile [MAX_STREAM_LENGTH];
	char _numberInChars [3];
	String _tempString;
	int _index = 0;
	int _indexOfDoublepoint = 0;
	File _readMeFile;
	
	String _readInput;
		
	for(_index = 0; _index<MAX_STREAM_LENGTH;_index++)
	_readFromFile[_index] = '-';


	if(!SD.begin(PIN_CS_SD)) 
	{
		Serial.println("        Keine SD-Karte eingelegt");
		return 2;	 						//Return 2 if no SD-Card is available
	}
	
	if(SD.exists("ReadMe.txt"))
	{	
		_readMeFile = SD.open("ReadMe.txt", FILE_WRITE);
		_readMeFile.seek(0);		//jump to start of file
		_index = 0;
		while (_readMeFile.available() > 0)
		{
			_readFromFile[_index] = _readMeFile.read();
			if(_readFromFile[_index] == ':')
				_indexOfDoublepoint = _index;
			_index++;			
		}		
		_numberInChars[0] = _readFromFile[_indexOfDoublepoint+2];
		_numberInChars[1] = _readFromFile[_indexOfDoublepoint+3];
		_numberInChars[2] = _readFromFile[_indexOfDoublepoint+4];
		
		//Current number to int for generating the file
		_tempString = String(_numberInChars);
		_numberOfCurrentTest = _tempString.toInt();
		
		//Defective ReadMe file, after doublpoint no number is following
		if(_numberOfCurrentTest==0)
			return 1;
		
		//Increase the number, that nexttime the system will generate a new folder
		_tempString = String(_numberOfCurrentTest+1);
		_readMeFile.seek(_indexOfDoublepoint+2);
		_readMeFile.write(_tempString.charAt(0));
		_readMeFile.write(_tempString.charAt(1));
		_readMeFile.write(_tempString.charAt(2));
			
		_readMeFile.close(); 	
		Serial.println("        ReadMe.txt wurde aktuallisiert");
		return (generateFile());
	}
	
	else
	{	
		makeReadMeFile(_readMeFile);
		_numberOfCurrentTest = 100;	//When makeing the file the first number everytime is 100
		
 		if(SD.exists("ReadMe.txt"))	
		{
			Serial.println("        ReadMe.txt wurde erfolgreich erstellt");
			return (generateFile());	
		}			
		else return 2;			//The ReadMe wasn't created by the routine on top and didn't exist before this routine	 
	}		
	
	
} 

void makeReadMeFile(File _readMeFile)
{
	_readMeFile = SD.open("ReadMe.txt", FILE_WRITE);
	_readMeFile.println("Dieses File darf NICHT geloescht werden!");
	_readMeFile.println("                 =====");
	_readMeFile.println("Wird dieses File geloescht, beginnt die ");
	_readMeFile.println("Nummerierung der Messungen wieder bei 1");
	_readMeFile.println("und alles bisherige auf der SD-Karte");
	_readMeFile.println("wird ueberschrieben (und somit geloescht).");
	_readMeFile.println("Dieses File darf nicht manuell geaendert");
	_readMeFile.println("werden. Es darf keine weiteren Doppelpunkte");
	_readMeFile.println("enthalten! Dieses File darf nicht mehr als");
	_readMeFile.println("10000 Zeichen enthalten. Aenderungen an diesem");
	_readMeFile.println("");
	_readMeFile.println("Aenderungen an diesem File muessen im Programm");
	_readMeFile.println("vorgenommen werden, Andernfalls werden diese");
	_readMeFile.println("beim naechsten loeschen ueberschrieben mit dem");
	_readMeFile.println("herkoemmlichen File. Die File-Nummern duerfen");
	_readMeFile.println("nicht kleiner als 100 und nicht groesser");
	_readMeFile.println("als 999 sein!");
	_readMeFile.println("");
	_readMeFile.println("Die naechste Versuchsnummer ist: 101");
	_readMeFile.close();
}

//================================================================================================================//
//=========================================Erstellen der Files====================================================//
//================================================================================================================//

int generateFile ()
{
	String _folderName;		
	char _fileNameC[] = "Test_XXX/FilterX.csv";		//Names mustn't get modified, otherwise the loops will not work anymore!
	char _fileDirC[] = "Test_XXX";
	int _fileNumber;
	int _index;
	String _writingData;
	
	if (_numberOfCurrentTest>999||_numberOfCurrentTest <100)			//Max number of Files is 999 and minimum is 100
		return 4;
	Serial.println("        Nummer des Tests ist zuelaessig");
	_folderName = String("Test_"+String(_numberOfCurrentTest));		//Make folder for all filters of this Test
	
	//Generating array of char as String, because String.c_str() will not work with SD-Library together!
	for(_index = 0;_index<9;_index++)
		_fileDirC[_index] = _folderName.charAt(_index);
	_fileDirC[9] = '\0'; //determinate the string with NUL
	
 	if(SD.exists(_fileDirC))		
		return 3; 
			
	
  	if(SD.mkdir(_fileDirC))
	{
 		//Set the correct Dir to _fileNameC
		for(_index=5; _index<=7;_index++)
			_fileNameC[_index] = _fileDirC[_index];
		
		for(_index = 0;_index<NUMBER_OF_FILTERS;_index++)
		{
			_fileNameC[15] = (char)(_index+49);			//to convert the index to the asci code number+1 (for starting with filter1)
			_fileNameC[20] = '\0';
			_dataFile[_index] = SD.open(_fileNameC,FILE_WRITE);			
			_dataFile[_index].close();			
		} 		
	}
	else 
		return 5; 
	Serial.println("        Verzeichnisse und Dateien erfolgreich erstellt");
	return 0;
}

//================================================================================================================//
//=========================================Speichern der Werte====================================================//
//================================================================================================================//

//================================================================================================================//
//=========================================Diverses===============================================================//
//================================================================================================================//

void writeTestValue()
{
 	File myFile;
	Serial.println("Schreibfunktion erreicht");
	
	digitalWrite(13,HIGH);
	
	if(SD.exists("ReadMe.txt"))
	{
		myFile = SD.open("Filter1.txt",FILE_WRITE);
		Serial.println("Root File geoeffnet");
		myFile.println("Hallo;");
		Serial.println("Wert in File in Root geschrieben");
		myFile.close();
		Serial.println("File in Root geschlossen");
		
		Serial.println("Schreibfunktion in Ordner erreicht");
		myFile = SD.open("Test_100/Filter1.txt",FILE_WRITE);
		Serial.println("File geoeffnet");
		myFile.println("Hallo;");
		Serial.println("Wert geschrieben");
		myFile.close();
		Serial.println("File geschlossen");
	}
	else
		Serial.println("File existiert nicht");
	
	myFile = SD.open("Hallo.txt",FILE_WRITE);
	Serial.println("Root File Hallo eroeffnet");
	myFile.println("Hallo;");

	Serial.println("Wert in File in Root geschrieben");
	myFile.close();
	Serial.println("File in Root geschlossen"); 
	if(SD.exists("Hallo.txt"))
	{
		Serial.println("=========!!!!!!!!!File wurde erstellt!!!!!!!!!============");

	}
	delayMicroseconds(1000);
	digitalWrite(13,LOW);
	return;
}

One misstake found, forget to set in file Defines.h on line 25 the right value, correct would be:
#define PIN_TURBIDITY_SENSOR A0
but it still doesn't work

I've found the solution. It was a very stupid mistake and I don't know why the compiler haven't seen this mistaking and also I don't understand why the code limited have worked.

Mistake was building an Array of objects, I've wrote:

Filter filter[numberOfFilters]

instead of:

Filter* filter = new Filter[NUMBER_OF_FILTERS];

The object Filter and FilterDummy are quite the same (expected random return values).

Although there were no answers, I will thanks to everybody who have read this poste and spent some time for thinking about the solution :slight_smile:

Best regards
Jérôme