Arduino Datalogger for TractorPulling

Hi.
I have build a datalogger based on an arduino uno, and the sd shield from sparkfun.
It is logging 2 pressures from 2 different pressure transducers.

The problem is that, in the last 2 pulls it crashed after approxemately 10 minutters. Before that i did'nt have any problems.
Is the problem due to programming isues, or du you think it is because of vibrations from the 1000 HP turbo charged diesel engine.??

this is my code

#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

// A simple data logger for the Arduino analog pins

// how many milliseconds between grabbing data and logging it. 1000 ms is once a second
#define LOG_INTERVAL  1000 // mills between entries (reduce to take more/faster data)

// how many milliseconds before writing the logged data permanently to disk
// set it to the LOG_INTERVAL to write each time (safest)
// set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to 
// the last 10 reads if power is lost but it uses less power and is much faster!
#define SYNC_INTERVAL 1000 // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0; // time of last sync()

#define ECHO_TO_SERIAL   1 // echo data to serial port
#define WAIT_TO_START    0 // Wait for serial input in setup()

// the digital pins that connect to the LEDs
#define redLEDpin 2
#define greenLEDpin 3

// The analog pins that connect to the sensors
//#define pressurePin0 0           // analog 0
//#define pressurePin1 1                // analog 1
#define BANDGAPREF 14            // special indicator that we want to measure the bandgap

//#define aref_voltage 5.0         // we tie 3.3V to ARef and measure it with a multimeter!
#define bandgap_voltage 1.1      // this is not super guaranteed but its not -too- off

RTC_DS1307 RTC; // define the Real Time Clock object


// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;
int pressurePin0 = 0;
int pressurePin1 = 1;

// the logging file
File logfile;

void error(char *str)
{
  Serial.print("error: ");
  Serial.println(str);
  
  // red LED indicates error
  digitalWrite(redLEDpin, HIGH);

  while(1);
}

void setup(void)
{
 
  Serial.begin(9600);
  Serial.println();

  // use debugging LEDs
  pinMode(redLEDpin, OUTPUT);
  pinMode(greenLEDpin, OUTPUT);
  
#if WAIT_TO_START
  Serial.println("Type any character to start");
  while (!Serial.available());
#endif //WAIT_TO_START

  // initialize the SD card
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    error("Card failed, or not present");
  }
  Serial.println("card initialized.");
  
  // create a new file
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // leave the loop!
    }
  }
  
  if (! logfile) {
    error("couldnt create file");
  }
  
  Serial.print("Logging to: ");
  Serial.println(filename);

  // connect to RTC
  Wire.begin();  
  if (!RTC.begin()) {
    logfile.println("RTC failed");
#if ECHO_TO_SERIAL
    Serial.println("RTC failed");
    RTC.adjust(DateTime(2014, 8, 8, 23, 1, 0));
#endif  //ECHO_TO_SERIAL
  }
  

  logfile.println("millis,datetime,pressureTurbo,pressure2,vcc");    
#if ECHO_TO_SERIAL
  Serial.println("millis,datetime,pressureTurbo,pressure2,vcc");
#endif //ECHO_TO_SERIAL
 
  // If you want to set the aref to something other than 5v
 // analogReference(EXTERNAL);
}

void loop(void)
{
  
  

  // delay for the amount of time we want between readings
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
  
  digitalWrite(greenLEDpin, HIGH);
  
  // log milliseconds since starting
  uint32_t m = millis();
  logfile.print(m);           // milliseconds since start
  logfile.print(", ");    
#if ECHO_TO_SERIAL
  Serial.print(m);         // milliseconds since start
  Serial.print(", ");  
#endif

  // fetch the time
  //now = RTC.now();
  // log time
  //logfile.print(now.unixtime()); // seconds since 1/1/1970
  //logfile.print(", ");
  //logfile.print('"');
  DateTime now = RTC.now();
  
  logfile.print(now.year(), DEC);
  logfile.print("/");
  logfile.print(now.month(), DEC);
  logfile.print("/");
  logfile.print(now.day(), DEC);
  logfile.print(" ");
  logfile.print(now.hour(), DEC);
  logfile.print(":");
  logfile.print(now.minute(), DEC);
  logfile.print(":");
  logfile.print(now.second(), DEC);
  logfile.print('"');
#if ECHO_TO_SERIAL
  Serial.print(now.unixtime()); // seconds since 1/1/1970
  Serial.print(", ");
  Serial.print('"');
  Serial.print(now.year(), DEC);
  Serial.print("/");
  Serial.print(now.month(), DEC);
  Serial.print("/");
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print(":");
  Serial.print(now.second(), DEC);
  Serial.print('"');
#endif //ECHO_TO_SERIAL

  //analogRead(pressurePin0);
  //delay(10); 
  int pressure0Reading = analogRead(pressurePin0);  
  
  //analogRead(pressurePin1); 
  //delay(10);
  int pressure1Reading = analogRead(pressurePin1);    
  
  // converting that reading to voltage, for 3.3v arduino use 3.3, for 5.0, use 5.0
  float voltage0 = pressure0Reading * 5.0 / 1023;
  float voltage1 = pressure1Reading * 5. / 1023;  
  float pressure0ReadingActual = voltage0 * 4 ;
  float pressure1ReadingActual = voltage1 * 4;
  
  logfile.print(", ");    
  logfile.print(pressure0ReadingActual);
  logfile.print(", ");    
  logfile.print(pressure1ReadingActual);
#if ECHO_TO_SERIAL
  Serial.print(", ");   
  Serial.print(pressure0ReadingActual);
  Serial.print(", ");    
  Serial.print(pressure1ReadingActual);
#endif //ECHO_TO_SERIAL

  // Log the estimated 'VCC' voltage by measuring the internal 1.1v ref
  analogRead(BANDGAPREF); 
  delay(10);
  int refReading = analogRead(BANDGAPREF); 
  float supplyvoltage = (bandgap_voltage * 1024) / refReading; 
  
  logfile.print(", ");
  logfile.print(supplyvoltage);
#if ECHO_TO_SERIAL
  Serial.print(", ");   
  Serial.print(supplyvoltage);
#endif // ECHO_TO_SERIAL

  logfile.println();
#if ECHO_TO_SERIAL
  Serial.println();
#endif // ECHO_TO_SERIAL

  digitalWrite(greenLEDpin, LOW);

  // Now we write data to disk! Don't sync too often - requires 2048 bytes of I/O to SD card
  // which uses a bunch of power and takes time
  if ((millis() - syncTime) < SYNC_INTERVAL) return;
  syncTime = millis();
  
  // blink LED to show we are syncing data to the card & updating FAT!
  digitalWrite(redLEDpin, HIGH);
  logfile.flush();
  digitalWrite(redLEDpin, LOW);
  
}

best regards
Bastian

Hi, welcome to the forum.

This SD shield ? SparkFun microSD Shield - DEV-12761 - SparkFun Electronics
It contains a level shifter, so it is okay for the Arduino Uno.
When you have soldered the standard square pin rows, they make good contact with the Uno board.

If your Uno board is a fake/clone from Ebay, the crystal might get broken faster with vibrations.
The shaking might be a problem for the SD card, but you can detect that with the SD library. I think you have to check the returning value from the SD library. Perhaps you can use the EEPROM inside the Uno board to store errors.

How is the power connected ? Just a jack plug into the barrel jack connector ? That would be my first concern for bad contacts.

You use the Arduino default SD library ? That is okay.
Do you use the newest Arduino IDE ? Version 1.0.5 or 1.5.7 BETA. The SD library with it is good, but a little slow. The newest SdFat is faster : greiman (Bill Greiman) · GitHub It is not more reliable, only faster.

To keep something running with strong vibrations, use a small board with a resonator, like the Pro Mini. And a EEPROM to store data. The disadvantage is that you can't take out a SD card to read it on a computer.

This is not nice programming: delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
When you want a certain curve for the delay, at least explain what you are doing.
That delay could be zero, and buffers to the SD card could be filled, and the sketch could be slowed down a lot.

I don't see other problems with the sketch. But I don't know what the effect of the flush is.

You need something to test it and to store an error.
Can you attach it to something ? a blender or so ? to simulate the vibrations ?
The only safe location to store something (for example SD card contacts problem) is the EEPROM. So you need to be able to store something and show it when it is connected to the serial monitor. I can be just a byte with an error number.

Did you wrap the Arduino into some gel/foam/rubber ? Even a thin shock-absorbant can reduce the g-forces a lot.