Thanks for sharing the code. It worked for me. I’m using the photon to log accelometer and gyrsocope data. I’ve included the SD.fat library in my code. It shows up as #include <SdFat.h> in the code. However, I’m still not able to log any data into my SD card.
What kind of debugging have you tried so far? I remember having some issues getting everything working right.
I'm working on adding the ability to write to an SD card as part of a code used to log Accel/ gyro data. I tried combining your code with mine, and currently trying to get the two codes to work together by eliminating redundancies.
I’m working on adding the ability to write to an SD card as part of a code used to log Accel/ gyro data. I tried combining your code with mine, and currently trying to get the two codes to work together by eliminating redundancies
This line suggests you are targeting an old system version and use the legacy version of SdFat
library.
We'd recommend moving on to the modern structure and more recent system versions.
I am currently using the most recent version of the SDfat library, it is included in my LSM330 code. I checked my SD card using the trymefirst and it is connected properly. However, my code is failing to write my accel data to the SD card. Is there a command I’m missing that allows the photon to write a file to the SD card?
Would someone please provide me with a response.
@nasib94, a bit more debugging information would be useful. What IS your code able to do? If your take the SD code out of the timers and put it into loop() using millis() delays as timers, does it work there? Sprinkling some Serial.print() debug message would also help to figure what the code is doing.
my code is able to output the USB data of the LSM330 sensor in addition to publishing the data to the console. I checked my memory card using the “trymefirst” code and the file was written to my SD card correctly. I guess what I am missing is the correct command to write my data to the SD card. The SDfat lib was included in the project as well.
@nasib94, Software Timers have limited stack space. So, why don't you try what I suggested:
If your take the SD code out of the timers and put it into loop() using millis() delays as timers, does it work there? Sprinkling some Serial.print() debug message would also help to figure what the code is doing.
I’m also sampling at 1000 milli seconds right now with no ouput to the SD card. I included ----Serial.print("sd.cardErrorCode(): "); — in order to check for SD error. Attached is my code for reference:
// This #include statement was automatically added by the Particle IDE.
#include <SdFat.h>
// This #include statement was automatically added by the Particle IDE.
//#include <sd-card-library-photon-compat.h>
// This #include statement was automatically added by the Particle IDE.
#include "LSM330.h"
#include <Wire.h>
LSM330 lsm;
void setup(void)
{
Serial.begin(9600);
// The address can be changed making the option of connecting multiple devices
lsm.getAddrX_LSM330(LSM330_DEFAULT_ADDRESS_ACCEL); // 0x1E
// lsm.getAddrX_LSM330(LSM330_ADDRESS_ACCEL_UPDATED); // 0x1D
lsm.getAddrG_LSM330(LSM330_DEFAULT_ADDRESS_GYRO); // 0x6A
// lsm.getAddrG_LSM330(LSM330_ADDRESS_GYRO_UPDATED); // 0x6B
// The Gyroscope's Output Data Rate and Bandwidth Selection and Full-Scale Selection,
// Acceleration Data Rate Selection and Acceleration Full-Scale Selection,
// can be changed via the following functions
/*
// Also some more parameters can be changed using the following functions
// Gyroscope:
// Power-Down Mode Enable, Gyroscope X, Y, Z Axes Enable,
// Block Data Update, Big/Little Endian Data Selection, Full-Scale Selection,
// SPI Serial Interface Mode Selection
// Accelerometer:
// Block Data Update for Acceleration Data
// Acceleration X, Y, Z Axes Enable
// Acceleration Anti-Alias Filter Bandwidth
// Self-Test Mode Configuration, SPI Serial Interface Mode Selection
// These functions can be modified and added here so that the parameters can be altered as per requirement
*/
lsm.setAccelDataRate(ACCEL_DATARATE_3_125HZ); // AODR (Hz): 3.125
// lsm.setAccelDataRate(ACCEL_DATARATE_POWERDOWN); // Power Down Mode
// lsm.setAccelDataRate(ACCEL_DATARATE_6_25HZ); // AODR (Hz): 6.25
// lsm.setAccelDataRate(ACCEL_DATARATE_12_5HZ); // AODR (Hz): 12.5
// lsm.setAccelDataRate(ACCEL_DATARATE_25HZ); // AODR (Hz): 25
// lsm.setAccelDataRate(ACCEL_DATARATE_50HZ); // AODR (Hz): 50
// lsm.setAccelDataRate(ACCEL_DATARATE_100HZ); // AODR (Hz): 100
// lsm.setAccelDataRate(ACCEL_DATARATE_200HZ); // AODR (Hz): 200
// lsm.setAccelDataRate(ACCEL_DATARATE_400HZ); // AODR (Hz): 400
// lsm.setAccelDataRate(ACCEL_DATARATE_800HZ); // AODR (Hz): 800
// lsm.setAccelDataRate(ACCEL_DATARATE_1600HZ); // AODR (Hz): 1600
lsm.setAccelRange(ACCEL_RANGE_16G); // ±16 g
// lsm.setAccelRange(ACCEL_RANGE_2G); // ±2 g
// lsm.setAccelRange(ACCEL_RANGE_4G); // ±4 g
// lsm.setAccelRange(ACCEL_RANGE_6G); // ±6 g
// lsm.setAccelRange(ACCEL_RANGE_8G); // ±8 g
lsm.setGyroDataRate(GYRO_DATARATE_95_12_5); // ODR (Hz): 95, Cutoff: 12.5
// lsm.setGyroDataRate(GYRO_DATARATE_95_25); // ODR (Hz): 95, Cutoff: 25
// lsm.setGyroDataRate(GYRO_DATARATE_190_12_5); // ODR (Hz): 190, Cutoff: 12.5
// lsm.setGyroDataRate(GYRO_DATARATE_190_25); // ODR (Hz): 190, Cutoff: 25
// lsm.setGyroDataRate(GYRO_DATARATE_190_50); // ODR (Hz): 190, Cutoff: 50
// lsm.setGyroDataRate(GYRO_DATARATE_190_70); // ODR (Hz): 190, Cutoff: 70
// lsm.setGyroDataRate(GYRO_DATARATE_380_20); // ODR (Hz): 380, Cutoff: 20
// lsm.setGyroDataRate(GYRO_DATARATE_380_25); // ODR (Hz): 380, Cutoff: 25
// lsm.setGyroDataRate(GYRO_DATARATE_380_50); // ODR (Hz): 380, Cutoff: 50
// lsm.setGyroDataRate(GYRO_DATARATE_380_100); // ODR (Hz): 380, Cutoff: 100
// lsm.setGyroDataRate(GYRO_DATARATE_760_30); // ODR (Hz): 760, Cutoff: 30
// lsm.setGyroDataRate(GYRO_DATARATE_760_35); // ODR (Hz): 760, Cutoff: 35
// lsm.setGyroDataRate(GYRO_DATARATE_760_50); // ODR (Hz): 760, Cutoff: 50
// lsm.setGyroDataRate(GYRO_DATARATE_760_100); // ODR (Hz): 760, Cutoff: 100
lsm.setGyroScale(GYRO_SCALE_2000DPS); // 2000 dps
// lsm.setGyroScale(GYRO_SCALE_250DPS); // 250 dps
// lsm.setGyroScale(GYRO_SCALE_500DPS); // 500 dps
lsm.begin();
delay(100);
}
void loop(void)
{
byte errorX, errorG;
int8_t addressX, addressG;
// LSM330 Accelerometer Address
addressX = lsm.lsm_i2cAddressX;
// LSM330 Gyroscope Address
addressG = lsm.lsm_i2cAddressG;
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(addressX);
errorX = Wire.endTransmission();
Wire.beginTransmission(addressG);
errorG = Wire.endTransmission();
if ((errorX == 0) && (errorG == 0))
{
Serial.println("Getting Linear Acceleration and Angular Rate Data Readings from LSM330");
Serial.println(" ");
// Set up the sensor for Accelerometer and Gyroscope
lsm.setUpAccelerometer();
lsm.setUpGyroscope();
delay(50);
// Display the results for Acceleration and Angular Rate Values
lsm.Measure_Sensor();
lsm.Measure_Accelerometer();
lsm.Measure_Gyroscope();
// Particle.publish("Impulse", "1 ");
//}
//delay(500);
//Serial.print("Linear Acceleration in Y-Axis: ");
//Serial.println(lsm.lsm_accelData.Y);
//Particle.publish("accelData.Y", String(lsm.lsm_accelData.Y/ 139)); // Divided over 139 to convert into m/s^2
//String(calibY) = ("String(lsm.lsm_accelData.Y" / 139) ; //acceleration in m/s^2
//Particle.publish("realY","String(calibY)" );
//delay(500);
Serial.print("Linear Acceleration in Z-Axis: ");
Serial.println(lsm.lsm_accelData.Z/139);
Particle.publish("accelData.Z", String(lsm.lsm_accelData.Z/139));
delay(50);
if ( 0 < (lsm.lsm_accelData.Z/139) < 25 )
{
Particle.publish("impulse","slow");
}
if ( 25<(lsm.lsm_accelData.Z/139)< 50 )
{
Particle.publish("impulse", "medium");
}
if ((lsm.lsm_accelData.Z/139) > 50 )
{
Particle.publish("impulse", "fast");
}
//Serial.println(" ");
//Serial.println(" *********** ");
//Serial.println(" ");
//delay(500);
//Serial.print("Rotation in X-Axis: ");
//Serial.println(lsm.lsm_gyroData.X);
//Particle.publish("gyroData.X", String(lsm.lsm_gyroData.X));
//delay(500);
//Serial.print("Rotation in Y-Axis: ");
//Serial.println(lsm.lsm_gyroData.Y);
//Particle.publish("gyroData.Y", String(lsm.lsm_gyroData.Y));
//delay(500);
//Serial.print("Rotation in Z-Axis: ");
//Serial.println(lsm.lsm_gyroData.Z);
//delay(500);
//Particle.publish("gyroData.Z", String(lsm.lsm_gyroData.Z));
//Serial.println(" ");
//Serial.println(" *************************** ");
//Serial.println(" ");
//delay(1000);
}
else
{
Serial.println("LSM330 Disconnected!");
Serial.println(" ");
Serial.println(" ************ ");
Serial.println(" ");
}
delay(100);
}
//This is a code to gewrite data to SD card and manage storae//////////////////////////
//// //// //// //// ////
//// 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
//// //// //// //// ////
//// //// //// //// ////
// 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 performanceo
//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() {
//}
If you don’t want people to get lost in that code, you may want to tidy it up a bit before posting.
All these comments and scattered declarations don’t make it easy to follow.
#include <SdFat.h>
//#include <sd-card-library-photon-compat.h>
#include “LSM330.h”
#include <Wire.h>
LSM330 lsm;
void setup(void)
{
Serial.begin(9600);
// The address can be changed making the option of connecting multiple devices
lsm.getAddrX_LSM330(LSM330_DEFAULT_ADDRESS_ACCEL); // 0x1E
// lsm.getAddrX_LSM330(LSM330_ADDRESS_ACCEL_UPDATED); // 0x1D
lsm.getAddrG_LSM330(LSM330_DEFAULT_ADDRESS_GYRO); // 0x6A
// lsm.getAddrG_LSM330(LSM330_ADDRESS_GYRO_UPDATED); // 0x6B
// The Gyroscope's Output Data Rate and Bandwidth Selection and Full-Scale Selection,
// Acceleration Data Rate Selection and Acceleration Full-Scale Selection,
// can be changed via the following functions
lsm.setAccelDataRate(ACCEL_DATARATE_3_125HZ); // AODR (Hz): 3.125
lsm.setAccelRange(ACCEL_RANGE_16G); // ±16 g
lsm.setGyroDataRate(GYRO_DATARATE_95_12_5); // ODR (Hz): 95, Cutoff: 12.5
lsm.setGyroScale(GYRO_SCALE_2000DPS); // 2000 dps
lsm.begin();
delay(100);
}
void loop(void)
{
byte errorX, errorG;
int8_t addressX, addressG;
// LSM330 Accelerometer Address
addressX = lsm.lsm_i2cAddressX;
// LSM330 Gyroscope Address
addressG = lsm.lsm_i2cAddressG;
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(addressX);
errorX = Wire.endTransmission();
Wire.beginTransmission(addressG);
errorG = Wire.endTransmission();
if ((errorX == 0) && (errorG == 0))
{
Serial.println("Getting Linear Acceleration and Angular Rate Data Readings from LSM330");
Serial.println(" ");
// Set up the sensor for Accelerometer and Gyroscope
lsm.setUpAccelerometer();
lsm.setUpGyroscope();
delay(50);
// Display the results for Acceleration and Angular Rate Values
lsm.Measure_Sensor();
lsm.Measure_Accelerometer();
lsm.Measure_Gyroscope();
//delay(500);
Serial.print("Linear Acceleration in Z-Axis: ");
Serial.println(lsm.lsm_accelData.Z/139);
Particle.publish("accelData.Z", String(lsm.lsm_accelData.Z/139));
delay(50);
if ( 0 < (lsm.lsm_accelData.Z/139) < 25 )
{
Particle.publish("impulse","slow");
}
if ( 25<(lsm.lsm_accelData.Z/139)< 50 )
{
Particle.publish("impulse", "medium");
}
if ((lsm.lsm_accelData.Z/139) > 50 )
{
Particle.publish("impulse", "fast");
}
}
else
{
Serial.println("LSM330 Disconnected!");
Serial.println(" ");
Serial.println(" ************ ");
Serial.println(" ");
}
delay(100);
}
//This is a code to gewrite data to SD card and manage storae//////////////////////////
//// //// //// //// ////
//// 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
//// //// //// //// ////
//// //// //// //// ////
// 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 performanceo
//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
I attached a cleaner version of the code and eliminated all the unnecessary comments.
I am about to start a project using the new particle mesh devices along with the Adafruit Adalogger Featgerwing to write and read data from the SD card. If anyone has dabbled around with them yet and have anything to mention as far a some pointers that would be super awesome!!
Hello @ScruffR
I am having some difficulty with the code in the link you posted. I am trying the TryMeFirst program below to test the comms between the photon and the microSD:
#include "SdFat.h"
// Pick an SPI configuration.
// See SPI configuration section below (comments are for photon).
#define SPI_CONFIGURATION 0
//------------------------------------------------------------------------------
// 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
//------------------------------------------------------------------------------
File myFile;
void setup() {
Serial.begin(9600);
// Wait for USB Serial
while (!Serial) {
SysCall::yield();
}
Serial.println("Type any character to start");
while (Serial.read() <= 0) {
SysCall::yield();
}
// Initialize SdFat or print a detailed error message and halt
// Use half speed like the native library.
// Change to SPI_FULL_SPEED for more performance.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
sd.initErrorHalt();
}
// open the file for write at end like the "Native SD library"
if (!myFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END)) {
sd.errorHalt("opening test.txt for write failed");
}
// if the file opened okay, write to it:
Serial.print("Writing to test.txt...");
myFile.println("testing 1, 2, 3.");
myFile.printf("fileSize: %d\n", myFile.fileSize());
// close the file:
myFile.close();
Serial.println("done.");
// re-open the file for reading:
if (!myFile.open("test.txt", O_READ)) {
sd.errorHalt("opening test.txt for read failed");
}
Serial.println("test.txt content:");
// read from the file until there's nothing else in it:
int data;
while ((data = myFile.read()) >= 0) {
Serial.write(data);
}
// close the file:
myFile.close();
}
void loop() {
// nothing happens after setup
}
But it does not compile. It returns the following error:
lib/SdFat/SdCard/SdInfo.h:112:34: 'F_CPU' was not declared in this scope
I have included the SDFat library and it appears this error is in the SDFat library. But others have used this program so how can that be?
If you are using Web IDE posting a SHARE THIS REVISION links is usually the best way to enable others to test your project.
The most recent version of SdFat doesn’t seem to feature a TryMeFirst
example anymore.
With the error message my hunch would be you are not targeting the most recent device OS.
How do i SHARE THIS REVISION?
Is there an update for the device that was released recently? Doesn’t the software update automatically since im using the particle WEB IDE? i have the version 1.0.1, how do i update the photons software OTA using the particle dashboard?
In Web IDE you will find this button
You can have 1.0.1 installed on the device but still build for a previous verison of the device OS. To actually build for 1.0.1 you need to select (or at least check) whether Web IDE is also set to target that version.
oh okay i understand here is the link for the code i am trying to run (the one i included in the previous post)
https://go.particle.io/shared_apps/5c814525e1386c00179adf92.
i have verified that the device os target and the on the device os are both 1.0.1. It still wont compile.
Thanks, ScruffR.