Wednesday, May 22, 2013

Logging to an SD Card with Arduino - the Software

The sketch that I used for logging to an SD Card is available here for download.  It is pretty much based on the examples from the Arduino download but with a couple of interesting notes:

Nothing special here except that at one point I had put the initialization of the card where it could get executed twice.   Fail!   It is much happier in the setup section with one time things.
    // Make sure that the default SD chip select pin is set to output, even if
    // you don't use it (interferes with lcd???):
    pinMode(SS, OUTPUT);

    // See if the card is present and can be initialized:
    if (!SD.begin(chipSelect)) {
        utilLcd.lcdDisplay("SD Card is not ", "present/working", -1);
        while (1);
    }

Prior to starting to make observations we open an output file.
    // Open up the file we're going to log to and create a new file
    char filename[] = "READINGS.DAT";
    SD.remove(filename);
    dataFile = SD.open(filename, FILE_WRITE);
    // Did the file open work?
    if (! dataFile) {
        utilLcd.lcdDisplay("Could not create", "readings file", -1);
        while (1) ;
    }

Almost certainly overkill, but, I wanted to have the most dense data logging possible so am logging two longs in eight bytes.   Pretty much their native size if not format.  I have not done a timing between doing this and saving as ascii but I would hope for this to be more efficient!?!?
    // Convert the above from an unsigned long ints to a 8-byte array...
    buffer[0] = (int)((timestamp >> 24) & 0xFF);
    buffer[1] = (int)((timestamp >> 16) & 0xFF);
    buffer[2] = (int)((timestamp >> 8) & 0XFF);
    buffer[3] = (int)((timestamp & 0XFF));
    buffer[4] = (int)((voltage >> 24) & 0xFF);
    buffer[5] = (int)((voltage >> 16) & 0xFF);
    buffer[6] = (int)((voltage >> 8) & 0XFF);
    buffer[7] = (int)((voltage & 0XFF));
    // ... and save them in our data file
    dataFile.write(buffer, 8);

If we are logging to an SD card we may well NOT be doing anything further with it on the Arduino but I wanted to do so anyway.   Obviously we had closed and reopened the logging file and then I use this function to reach into that file and get the eight bytes that were logged.
/* ************************************************************************
Read a specific observations entry from our file into our global record buffer
************************************************************************ */
int observation(long entry) {
    if (dataFile.seek(entry * 8)) {
        for (int i = 0; i<8; i++) {
            buffer[i] = dataFile.read();
        }
        return(TRUE);
    }
    else {
        return(FALSE);
    }
}

Finally, an example of getting back the long value that had been saved.   In this case the voltage reading.
/* ************************************************************************
Return the voltage portion of our file buffer
************************************************************************ */
unsigned long voltageEntry() {
    unsigned long temp = ( ((unsigned long)buffer[4] << 24)
                   + ((unsigned long)buffer[5] << 16)
                   + ((unsigned long)buffer[6] << 8)
                   + ((unsigned long)buffer[7] ) );
    return(temp);
}

This code captured and logged at the rate of about 860 observations per second.

No comments:

Post a Comment