I’m having some problems writing data to an SD card. I used some of SD and realtime clock sample code from revision 1.06 of the Beginners Guide as the basis of a simple data logger to test a thermocouple circuit that I’ve been working on. The code is shown below:
using System;
using System.Threading;
using System.Text;
using System.IO;
using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using GHIElectronics.NETMF.IO;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
namespace FEZ_Domino_Application1
{
public class Program
{
public static void Main()
{
// Assume that the SD card is inserted and create a new storage device
PersistentStorage sdPS = new PersistentStorage("SD");
// Mount the file system
sdPS.MountFileSystem();
// Read the root directory from the card and get the file handle
string rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory;
FileStream FileHandle = new FileStream(rootDirectory + "\\data.txt", FileMode.Append);
byte[] data;
// Set up an analog input channel
AnalogIn thermocouple = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An5);
// Set the scale so that the A-to-D reading will be in tenths of a degree
thermocouple.SetLinearScale(-500, 500);
int reading = 0;
double tempC = 0.0D;
double tempF = 0.0D;
// Set the real time clock
if (RealTimeClock.IsTimeValid == false)
{
Debug.Print("Setting real time clock ...");
RealTimeClock.SetTime(new DateTime(2010, 12, 7, 12, 26, 30));
}
Utility.SetLocalTime(RealTimeClock.GetTime());
while (true)
{
// Read the thermocouple
reading = thermocouple.Read();
// Convert to a floating point value in degrees C
tempC = ((double)reading) / 10.0D;
// Calculate temperature in degrees F
tempF = ((tempC / 100.0D) * 180.0D) + 32.0D;
data = Encoding.UTF8.GetBytes(DateTime.Now.ToString() + " " + tempC.ToString("F1") + " C, " + tempF.ToString("F1") + " F\r\n");
try
{
FileHandle.Write(data, 0, data.Length);
}
catch { }
FileHandle.Flush();
Debug.Print(DateTime.Now.ToString() + " " + tempC.ToString("F1") + " C, " + tempF.ToString("F1") + " F");
Thread.Sleep(1000);
}
}
}
}
What is happening is that after running for a while (about 35 minutes at one sample every 5 seconds, about 5 minutes if I try to log a sample every second) the code croaks with the following exception …
12/07/2010 14:18:44 0.2 C, 32.4 F
#### Exception System.IO.IOException - CLR_E_FILE_IO (1) ####
#### Message:
#### Microsoft.SPOT.IO.NativeFileStream::Write [IP: 0000] ####
#### System.IO.FileStream::Write [IP: 002a] ####
#### FEZ_Domino_Application1.Program::Main [IP: 0116] ####
A first chance exception of type ‘System.IO.IOException’ occurred in Microsoft.SPOT.IO.dll
12/07/2010 14:18:46 0.0 C, 32.0 F
The date, time and temperature info is the output of my code … the thermocouple was in an ice/water bath.
Any help or pointers would be greatly appreciated.
I removed all of the code except the SD-related stuff -
using System;
using System.Threading;
using System.Text;
using System.IO;
using Microsoft.SPOT;
using Microsoft.SPOT.IO;
using GHIElectronics.NETMF.IO;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
namespace FEZ_Domino_Application1
{
public class Program
{
public static void Main()
{
// Assume that the SD card is inserted and create a new storage device
PersistentStorage sdPS = new PersistentStorage("SD");
// Mount the file system
sdPS.MountFileSystem();
// Read the root directory from the card and get the file handle
string rootDirectory = VolumeInfo.GetVolumes()[0].RootDirectory;
FileStream FileHandle = new FileStream(rootDirectory + "\\data.txt", FileMode.Append);
byte[] data;
while (true)
{
data = Encoding.UTF8.GetBytes("12/7/10 15:16:00 0.0 C, 32.0 F\r\n");
try
{
FileHandle.Write(data, 0, data.Length);
}
catch { }
FileHandle.Flush();
Debug.Print("OK");
Thread.Sleep(1000);
}
}
}
It runs for several minutes before producing the same sort of exception -
“Since the SD file was opened in append mode, should it have been positioned to the end of file before starting to write to it?”
I don’t think so. I wondered about that too, so I tested it. I started out with a blank card and ran the code for about about 30 seconds. It created the file and wrote a bunch of readings to it. I stopped the code and looked at the file on a PC, then I put the card back in the Domino and let write some more data to the file. Everything looked OK. The only time I have the problem is if I let the code run for more than a few minutes.
Before testing, please format your SD card on the PC.
Use FAT32 and some known number for allocation unit size (cluster size) not the default.
We will try to do the same test here.
Please tell me the allocation unit size and if you have the same problem.
Are you sure you are not stopping your program unsafely? I mean you are in a while(true), if you remove the SD card while it is writing, then the next time you plug it in, you will have exceptions at some point because the file system is corrupted.
Format the SD card and run the program, do you have problems the very first time?
“Format the SD card and run the program, do you have problems the very first time?”
Mike,
Yes, the problem occurs the first time I use the card right after re-formatting it.
This morning I stopped and got a new 2 GB micro SD card. I switched brands and bought a PNY this time instead of SanDisk. It looks like that solved the problem … the code has been running for over 50 minutes without a problem. I’ll modify my code so that I can close the file properly before removing the card.