Data Logger for the Sparkfun Inventor's Kit

by Mark Feldman (email: mark ==at== ppl-pilot ==dot== com)

About two weeks ago I had my 40th birthday. One of the more exciting presents I got this year turned up in the mail just yesterday but it's been well worth the wait: the SparkFun Inventor's Kit!

The inventors kit consists of an Arduino Uno, a prototype board with jumpers etc and a slew of components (toys) to play with i.e. LEDs, a relay, servo, buttons, motor, potentiometer, buzzer....you get the idea. At roughly US$100 it's not the cheapest kit in the world but you get so many little goddies that it still makes it a good buy, especially if your awesome parents buy it for you as a birthday present! In all modesty the level of skill required is very basic and well within my own abilities (check out my projects on wireless controllers and my 3D printer control board) but I've usually used Microchip's range of PIC microcontrollers for projects I've done in the past. This is my first foray into the world of Arduino and I have to admit the Inventor's Kit has been a great little introduction to the platform.

In this article I'm going to show how to use the kit to write data to an SD card. At first glance it appears that it doesn't provide the components or examples needed to do this but it is in fact possible using only the components provided by the kit (actually I lie, you'll also need a few drops of super-glue, more on that in a moment...)

The project I've decided to use to demo this feature is CIRC-10 i.e. the temperature sensor project which reads the output voltage from the included TMP36, calculates the temperature and sends the result to the connected PC's COM port. With a little bit of extra code and wiring you can also write the temperature to a log file on the SD card. This allows you to run the project off battery or adapter power without actually being connected to a PC and you can import the text file later e.g. into OpenOffice or the spreadsheet of your choice for charting etc.

Here's the basic circuit I used:

The use of the TMP36 IC is exactly the same as in the original project: you connect 5V across the outer pins and tap the voltage off the center pin into A0.

The rest of the circuit consists of interfacing to the SD card, and at this point we immediately run into a small compatibility issue: SD cards run at 3.3 volts. That's fine for the main supply voltage because the Arduino boards provide that as a separate supply alongside the 5V rail. It creates a problem with the data lines though because on Arduino those output 5V for a HIGH signal. There's a thread on the allaboutcircuits forum that shows how to run these through 2 resistors per line (3.6k and 1.8k) to drop the levels to 3.3V but the Inventors Kit doesn't provide resistors with those values. What I did instead was use 3 resistors per line: a 10k resistor for the larger value and 2 10k resistors in parallel (i.e. 5k total) for the lower value; this results in the same voltage drop to 3.3k and the three output signals can then be fed into the SD card. There's a fourth pin used by the SD card to send data back to the host but the Arduino's TTL inputs see 3.3V as a HIGH signal so no conversion is neccessary there.

As far as actually writing data to the SD card goes a library is provided with the Arduino development environment, so you only need to make a few simple calls. The sketch's setup function deletes the log file if it already exists while the loop function opens the file, writes the temperature data and closes the file. Here is the full, modified version of the CIRC-10 source code with SD logging support added:

#include <SD.h>


/*
 *  Logger - A simple program to save the current temperature to 
 *           a log file on an SD card. 
 * 
 *  This program is heavily based on the Arduino Experimentation Kit
 *  Example Code CIRC-10. The example has been modified to save the
 *  temperature readings to SD card.
 *
 *
 *  Please visit http://www.ppl-pilot.com/logger.htm for details.
 */

//TMP36 Pin Variables
int temperaturePin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
                        //the resolution is 10 mV / degree centigrade 
                        //(500 mV offset) to make negative temperatures an option

// filename of the log file on the SD card to write temperature data to
// (this should actually be a const char * but for some strange reason the
// SD exists and remove functions expect a char *)
char * logFileName = "datalog.txt";                        

// Most Arduino boards (including the Uno board used in the Inventors Kit) use hardware
// CS pin 10, I also use it here. If you use this sample on another board that uses pin
// 10 for something else then you can change it to something else but you'll need to leave
// pin 10 as an output or the SD library functions will not work.
const int chipSelect = 10;


/*
 * setup() - this function runs once when you turn your Arduino on
 * We initialize the serial connection with the computer
 */
void setup()
{
  Serial.begin(9600);  //Start the serial connection with the copmuter
                       //to view the result open the serial monitor 
                       //last button beneath the file bar (looks like a box with an antenae)
                       
  Serial.print("Initializing SD card...");
  
  // thisthese two lines are mainly here for when a CS pin other than 10 is used,
  // they're needed in order for the SD functions to work correctly. 
  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  
  // remove the log file if it already exists
  if (SD.exists(logFileName))
    SD.remove(logFileName);
}
 
void loop()                     // run over and over again
{
 float temperature = getVoltage(temperaturePin);  //getting the voltage reading from the temperature sensor
 temperature = (temperature - .5) * 100;          //converting from 10 mv per degree wit 500 mV offset
                                                  //to degrees ((volatge - 500mV) times 100)
 Serial.println(temperature);                     //printing the result
 logTemperature(temperature);                     //save temperature to the log file                     
 delay(1000);                                     //waiting a second
}

/*
 * getVoltage() - returns the voltage on the analog input defined by
 * pin
 */
float getVoltage(int pin){
 return (analogRead(pin) * .004882814); //converting from a 0 to 1024 digital range
                                        // to 0 to 5 volts (each 1 reading equals ~ 5 millivolts
}

void logTemperature(float temperature)
{
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open(logFileName, FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(temperature);
    dataFile.close();
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening log file");
  }
}

The final task is physically connecting the SD card to the prototype board. If you have an SD socket and know how to use a soldering iron then this bit is easy, but many people using the Inventors Kit won't so I've used a well-known hack to make a "socket". First of all cut off two pieces of the supplied pin headers, each of which should be 8 pins long:

Notice how the pins on these headers have two sides, a short side a long side? Take a pair of pliers and gently work each pin so that the amount of metal sticking out each side is roughly equal:

Now take one of your headers and very gently bend the pins into an S shape, then super-glue the two pieces together. It's very important to line the two headers up perfectly and to make sure that you don't get any glue on the parts of the pins that will make contact with the SD card and prototype board connectors:

Allow to dry fully. What you have now is a make-shift SD card holder that you can plug directly into your prototype board. If you have access to a local electronics store then it's easier to use a dual-row header to make this part, that way you won't have to glue anything and it'll be stronger. Either way you should now have two rows of pins that you can slide an SD card into and plug into your Inventor's Kit prototype board:

Note that there shouldn't be any pin touching the left-most pad, and while there is a pin over the raised right-most pad it doesn't actually have to make contact with the metal. I've leave it to you to figure out how to wire this up on your breadboard using the circuit I provided above but here's my own version for reference:

You'll also need the SD card pin layout, image courtesy of Wikipedia:

Note the unusual pin numbering. The first raised pin is 9 and then it starts from pin 1 next to it and rises sequentially. Also don't forget to connect pins 3 and 6 to ground and pin 4 to the 3.3V line on your Arduino Uno board. One last thing you may need to do is use Windows to reformat your SD card with FAT (aka "FAT16") rather than FAT32. In theory the SD library should be able to support FAT32 but I've had problems with it in the past and FAT16 is the recommended file system to use with it.

That's all there is to it! I've used the temperature sensor example as the base for this project but of course you can use the SD library with any of the others. And you're not limited to just writing to the card either, you can just as easily read from it e.g. to play longer music sequences for CIRC-06. Or you can use it to store application data, thus allowing you to significantly boost the size and complexity of programs your Arduino board can run.

Have fun inventing!