Vernier Shield Hookup Guide
Storing Data to an SD Card
What you'll need
Recommended Reading / Useful Resources
Adding an SD Card Interface to your Vernier shield is pretty simple. The SD Card shield will have to go below the Vernier Shield using a set of stack-able headers.
Upload this code to your shield. It logs raw voltage values of the sensors to a microSD Card, if you are using the SparkFun microSD Card Shield. If you are using your own SD Card shield implementation, double check the pin assignments for chipselect. On the SparkFun microSD Card Shield, chipselect is on pin 8.
This code example will read raw voltage levels from any analog Vernier Sensor that provides a voltage from 0 to 5V (this accounts for a majority of their sensors). Pressing the button (D12) will start the data collection for a time period defined by the variable duration. Data is logged to a file called "datalog.txt" and displayed to the Serial Monitor.
Upload the VernierSDStore
sketch to your Arduino.
language:c
/*
VernierShieldSDStore (v 2014.02)
Takes data from a Vernier Motion Detector connected to BTA connector.
The data is displayed to the serial monitor and saved to a file called datalog.txt
Data is currently displayed and stored as raw voltage levels from 0 to 5V. Currently working
integrate the AutoIDAnalog.ino code into this code so that data is automatically
calibrated.
Only the 5V analog signal is currently being used, but you can change the code to
See www.vernier.com/arduino for more information.
*/
#include <SD.h> // includes the Arduino SD Library
// pin configurations for SparkFun Vernier Shield
// A1 = Analog 1
// A2 = Analog 2
#define A1_5V 0
#define A1_10V 1
#define A2_5V 2
#define A2_10V 3
char * filename = "datalog.txt"; /* sets the filename for data - change this
if you want to use a different file name
data will be concatenated onto the existing
file if it exists */
float dataRate = 20.0; // # of samples per second.
int duration = 5000; // set the data collection duration in milliseconds
// default value is set to 5 seconds or 5000 milliseconds
unsigned long timeRef; // reference for starting time
unsigned long timeInterval;
unsigned long elapsedTime;
unsigned long ndx = 0;
const int buttonPin = 12; // digital button on Vernier Shield - used to start data collect
const int ledPin = 13; // LED pin on Vernier Shield
/* Global Variable declarations for SD Card Shield */
const int chipSelect = 8;
File dataFile;
// variables used with VernierAnalogAutoID
//
int muxLSB = 10; //low byte of multiplexer
int muxMSB = 11; //high byte of multiplexer
int SensorRaw[2];
float SensorVoltage[2];
float VCC = 5.0;
void setup()
{
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
// set the timeInterval based on dataRate
timeInterval = 1E3 / dataRate;
// initialize the buttonPin as an INPUT with a pull-up resistor
pinMode(buttonPin, INPUT_PULLUP);
pinMode(muxLSB, OUTPUT);
pinMode(muxMSB, OUTPUT);
Serial.println("*************************************************");
Serial.println("Push button (D12) to start data collection.");
Serial.println("Use reset button to reset / stop data collection.");
Serial.println("*************************************************");
while(digitalRead(buttonPin) == HIGH)
{
// holding loop until the button goes low.
}
/***********************
* / Setup SD Card
/***********************/
pinMode(chipSelect, OUTPUT);
Serial.print("Initializing SD card...");
// 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.");
Serial.println();
/***********************
* / Print data header
/***********************/
Serial.println(" ");
Serial.println("Vernier Format 2");
Serial.println("Raw Readings taken using Ardunio");
Serial.println("Data Set");
Serial.print("Time");
Serial.print("\t"); //tab character
Serial.print ("Chan1");
Serial.print("\t"); //tab character
Serial.print("Chan2");
Serial.println("");
Serial.print("seconds");
Serial.print("\t"); //tab character
Serial.print ("V");
Serial.print("\t"); //tab character
Serial.print ("V");
Serial.println();
/*************************
* / Print header to SD Card
/*************************/
dataFile = SD.open(filename, FILE_WRITE);
if (dataFile) // if it opens sucessfully
{
dataFile.println("Vernier Format 2");
dataFile.println("Raw Readings taken using Ardunio");
dataFile.println("Data Set");
dataFile.print("Time");
// query the channel numbers
// print sensor name -- data will be displayed in raw and voltage
dataFile.print("\t"); //tab character
dataFile.print("Chan1");
dataFile.print("\t"); //tab character
dataFile.print("Chan2");
dataFile.println();
// display the units
dataFile.print("seconds");
dataFile.print("\t");
dataFile.print("V");
dataFile.print("\t");
dataFile.print("V");
dataFile.close(); // close the datafile
}
else // if(datafile) -- error opening SD card
{
Serial.println("error opening file.");
Serial.println();
}
digitalWrite(ledPin, HIGH);
timeRef = millis();
ndx = 0; // datapoint index
} // end setup
void loop()
{
unsigned long currTime = millis(); // record current Time
if ((currTime - timeRef) <= (duration)) // controls the duration of the data collection
{
if (currTime >= ndx*timeInterval + timeRef) // controls so only runs once per timeInterval
{
ndx++;
digitalWrite(ledPin, LOW); // blink the LED off to show data being taken.
// Read in sensor values
SensorRaw[0] = analogRead(A1_5V);
SensorRaw[1] = analogRead(A2_5V);
// Convert to voltage values
SensorVoltage[0] = SensorRaw[0]*VCC/1023.0;
SensorVoltage[1] = SensorRaw[1]*VCC/1023.0;
/* // uncomment these lines of code to use the +/- 10V sensors
SensorRaw[0] = analogRead(A1_10V);
SensorRaw[1] = analogRead(A2_10V);
// Convert to voltage values (20V range, -10V offset)
SensorVoltage[0] = SensorRaw[0]*20.0/1023.0 - 10.0;
SensorVoltage[1] = SensorRaw[1]*20.0/1023.0 - 10.0;
*/
dataFile = SD.open(filename, FILE_WRITE);
// if the file is available, write to it:
if (dataFile)
{
dataFile.print((currTime - timeRef)/ 1E3, 3); // 4 decimal places
dataFile.print("\t");
dataFile.println(SensorVoltage[0]);
dataFile.print("\t");
dataFile.println(SensorVoltage[1]);
dataFile.close();
}
// if the file isn't open, pop up an error:
else
{
Serial.println("Error opening file.");
}
// Serial print to the serial monitor
Serial.print((currTime - timeRef) / 1E3, 3);
Serial.print("\t"); // tab character
Serial.print(SensorVoltage[0]);
Serial.print("\t");
Serial.print(SensorVoltage[1]);
Serial.println();
digitalWrite(ledPin, HIGH); // turn the LED back on to show data collection
// duration is still running.
}
}
else // duration is complete -- wait and reset if button is pressed
{
digitalWrite(ledPin, LOW); // turn off LED to show data collection is done.
while(digitalRead(buttonPin) == HIGH)
{
// holding loop until the button goes low.
}
// reset counters and timeRef
digitalWrite(ledPin, HIGH);
ndx = 0;
timeRef = millis();
}
} // end of loop