I also have connected to an accelerometer and had to read/write data to an SD card. I posted my code below - please let me know if this helps or if you have questions:
#include <SdFat/SdFat.h> // Particle IDE is strange. To include this particular library,
// you have to both declare it here, as well as manually add the library to the app
// over in the libraries link on the left sidebar.
#include <math.h> // to do thermistor math later
//// //// //// //// ////
//// microSD config ////
// Pick an SPI configuration.
// See SPI configuration section below (comments are for photon).
#define SPI_CONFIGURATION 1
//// //// //// //// ////
// Setup SPI configuration.
#if SPI_CONFIGURATION == 0
// Primary SPI with DMA
// SCK => A3, MISO => A4, MOSI => A5, SS => A2 (default)
SdFat sd;
const uint8_t chipSelect = SS;
#elif SPI_CONFIGURATION == 1
// Secondary SPI with DMA
// SCK => D4, MISO => D3, MOSI => D2, SS => D1
SdFat sd(1);
const uint8_t chipSelect = D1;
#elif SPI_CONFIGURATION == 2
// Primary SPI with Arduino SPI library style byte I/O.
// SCK => A3, MISO => A4, MOSI => A5, SS => A2 (default)
SdFatLibSpi sd;
const uint8_t chipSelect = SS;
#elif SPI_CONFIGURATION == 3
// Software SPI. Use any digital pins.
// MISO => D5, MOSI => D6, SCK => D7, SS => D0
SdFatSoftSpi<D5, D6, D7> sd;
const uint8_t chipSelect = D0;
#endif // SPI_CONFIGURATION
//// //// //// //// ////
//// //// //// //// ////
SYSTEM_MODE(SEMI_AUTOMATIC); // allows Photon code to execute without being connected
// to a WiFi network. You must manually call Particle.connect() to connect to a network.
// On the other hand, in AUTOMATIC mode, Particle.connect() is automatically called before
// any code is executed, and the device waits to be connected to WiFi before executing any
// of your code.
// variable initalizations
FatFile globalAccelFile;
String globalAccelFileName;
String accelData;
bool flag; // flag checks whether certain events were successful or not
double accelMagnitude;
int fileTracker = 1;
int globalAccelFileTracker = 1;
// checks the accelerometer x y and z analog values, which are connected to A0, A1, and A2, respectively.
void checkAccel() {
globalAccelFileName = "globalAccel" + String(globalAccelFileTracker) + ".txt";
globalAccelFile.open(globalAccelFileName, O_RDWR | O_CREAT | O_AT_END);
accelMagnitude = floor(sqrt(pow(analogRead(A0),2) + pow(analogRead(A1),2) + pow(analogRead(A2),2)) + 0.5);
accelData += String(accelMagnitude).remove(4);
// maximum String length is 622 bytes. Let's just be safe and say 616 so we don't overrun.
if (accelData.length() > 616) {
accelData += " " + Time.timeStr();
globalAccelFile.write(accelData);
accelData = "";
}
if (accelData.length() <= 616) {
accelData += "\n"; // each data point is on its own line
}
if (globalAccelFile.fileSize() > 1000000) // if the accel file exceeds 1MB, on to the next one
{
globalAccelFileTracker++;
}
globalAccelFile.close(); // don't forget to close the file, otherwise you run the risk of corrupting the file and card.
}
// Find out if the SD card is cooperating. Good idea to call this before attempting to do anything major
// with the SD Card. This function is a little leaky - some SD errors can get by without this function picking them up.
void checkSdError() {
Serial.print("sd.cardErrorCode(): ");
flag = sd.cardErrorCode(); // directly related to sd success/failure
Serial.println(flag);
Serial.print("sd.cardErrorData(): "); // for additional debugging
Serial.println(sd.cardErrorData());
// If there's an error, write high to D7. You can plug in an LED at D7 to check the SD status whenever you want.
if (!flag) {
digitalWrite(D7, LOW);
}
else {
digitalWrite(D7, HIGH);
}
}
// software Timers are preferable to delays, so the code can run concurrently, not sequentially. Along these lines, it's probably
// a good idea to enable system threading using SYSTEM_THREAD(ENABLED);
Timer CheckAccelTimer(50, checkAccel); // sample accelerometer at 20 Hz
Timer CheckSdErrorTimer(1000, checkSdError); // checks for SD card errors every 1 second
void setup() {
// Particle.connect(); // must manually call Particle.connect() if system_mode is semi_automatic
// Time.zone(-7); // changes time zone. Does not adjust for DST, must manually change.
Serial.begin(115200); // debugging purposes
sd.begin(chipSelect, SPI_FULL_SPEED); // init at full speed for best performance
pinMode(D7, OUTPUT); // initalize D7 as an output for use by checkSdError
Time.setTime(1473379200); // set time to start on September 9 2016 00:00:00 GMT (UNIX time = 1473379200, or seconds since
// the UNIX epoch, 1 January 1970)
// Start the timers
CheckAccelTimer.start();
CheckSdErrorTimer.start();
}
// keep the loop empty - it's better to use software timers (as I did above) so that you can nest events,
// instead of running your code line by line (which is what happens in setup and loop).
void loop() {
}