Accelerometer and datalogger

Hi to all.

I made a 3 axis accelerometer/datalogger. This is very useful in physics class, - you can do the Gallilean dilution of gravity on a ramp experiment, and compare your raw adc counts to the angle of your slope. You can play with centripetal force and circular motion, and you can show that a falling object experiences no weight force (just like NASAs Vomit Comet). But best of all, duct taped onto a skateboard with an Estes rocket motor ....... XD

The SD card was from RobotBase via ebay (Arduino SD read-write memory module Mass Storage card),
and the accelerometer was also from ebay (MMA7260 Accelerometer Sensor Module 3-Axis Arduino AVR ).

Please enjoy, and I hope this is useful to someone.

The veroboard layout is here:

And the code is here:

/* 
Datalogging accelerometer
Version: 0.2
Status: Incomplete
Last Modified: 19/04/2013
Author: Leon Harris

Description:
This circuit is designed to measure acceleration in the x,y, and z 
 axis, and to store them onto a micro-SD drive.
 The user interface consists of a button to start and stop logging
 data, and two leds to indicate status.
 
 Two modules, both purchased from ebay, were incorporated into this design:
 MMA7260 Accelerometer Sensor Module 3-Axis Arduino AVR	
 Arduino SD read-write memory module Mass Storage card (www.robobase.cn)
 
 User Instructions.
 The red led lights when the unit is in "halt" mode. To make it log
 data, press the button once. The red led will extinguish, and the 
 white led will come on. The arduino will then open a file for 
 logging called "Basename" + N (where N is the number of the file it is up to). 
 Logging will then commence, once every ( int interval) milliseconds until the button is again pressed. 
 The file will be closed, the white led will flash the number of times that the 
 datafile ends in (to let the user know the number of that run), and then the 
 red led will be relit.
 
   Action          Red led      White led      status
   -                lit            -            halted
   press button      -          lit            recording data to file
   press button      lit        flashing       stop recording, flash file number to user
   -                lit          -              halted
   
   
   
   */
   
   
   
   
   /*
   Pin assignments
   
Analog pins
A1: y-axis
A2: x-axis
A0: z-axis
A4: ground   //not used as analogue but rewired as digital gnd with pinMode()
A5: vcc      //not used as analogue but rewired as digital vcc with pinMode()

Digital pins:
D2:   Red led ("paused")
D3:   White LED ("running")
D4:   SS (chip select) for SD
D6:   Button pin

D10: reserved, but not used, needed for SD library (do not use for anything else)

SPI Bus:
D11:  MOSI for SD
D12:  MISO for SD
D13:  sck clock for SD

*/

//Includes

#include <SD.h>  // library for using sd cards on SPI bus
#include <FlexiTimer2.h> // library for interrupts

// Code to define pins

const int groundpin = 18;             // analog input pin 4 -- ground
const int powerpin = 19;              // analog input pin 5 -- voltage
const int xpin = A2;                  // x-axis of the accelerometer
const int ypin = A1;                  // y-axis
const int zpin = A0;                  // z-axis (only on 3-axis models)

const int runningledpin = 3; // White led, used to indicate running 
const int pauseledpin = 2;  // Red led, used to indicate logging

const int buttonpin = 6;  // test for now - will reassign pin

const int chipselect = 4;  // ss pin for SD card

// set up runmode for program control/ led indication
boolean runmode = false;


// accelerometer variables

  int x;
  int y;
  int z;
  
  
// Timer variables
long int logtime=0; // start time is zero
bool logflag=true;
int interval=100; //read sensors 100/1000 times per second

char BASEFILENAME[6] = "accel";  // this is the base filename for logging



  char filename[14]; // this is the actual filename, which we will build later
  
  int fcounter = 0; // this is the used to store the current filenumber
  String dataString = ""; // a string to build output data into
    
void setup()
{
  BASEFILENAME[5] = 0;    // null terminate the name so sprintf can work
    fcounter=1;           // file counter
  // initialize the serial communications:
  Serial.begin(9600);
  // Provide ground and power by using the analog inputs as normal
  // digital pins. Think of it as ghetto current limitting to a 3.3v accelerometer !
  
  pinMode(groundpin, OUTPUT);
  pinMode(powerpin, OUTPUT);
  digitalWrite(groundpin, LOW); 
  digitalWrite(powerpin, HIGH);
  
  

   //set the leds to off
  pinMode(runningledpin, OUTPUT);
  pinMode(pauseledpin, OUTPUT);
  digitalWrite(pauseledpin, HIGH); 
  digitalWrite(runningledpin, LOW);
  

  
  //initialise the button
  pinMode(buttonpin, INPUT);
  digitalWrite(buttonpin, HIGH); // turn on internal pullup resistor
  
  
  // set up the SD card
  Sd2Card card;

SD.begin(chipselect);
  
    pinMode(10, OUTPUT);  // even if not used by the card, sd library breaks if 10 is not output
    
    if (!card.init(SPI_HALF_SPEED, chipselect)) {
 flashError();
   
}
}


//  int readAccel(int* x, int* y, int* z) {
//  *x=analogRead(xpin);
//  *y=analogRead(ypin);
//  *z=analogRead(zpin);
// return(*x,*y,*z);
//}


void pollbutton() {
     if (digitalRead(buttonpin)== LOW) {
    
    runmode = !runmode;
    delay(200);  // debounce the switch for 200 msec
   
}
 return;
}


void flashError(){
// this function flashes to signal a missing, damaged 
// or write protected SD card
  for (int i=0; i < 4; i++) {
   digitalWrite(pauseledpin,LOW);
    digitalWrite(runningledpin,LOW);
    delay(250);
    digitalWrite(pauseledpin,HIGH);
    digitalWrite(runningledpin,HIGH);
    delay (250);
  }
   digitalWrite(pauseledpin,LOW);
 }
  

void flashFilenumber(int suffix) {
 // this function flashes the white led a number of times
 // corresponding to the file number that has just been written
  while (suffix >= 0) {
    digitalWrite(runningledpin, HIGH);
    delay (250);
    digitalWrite(runningledpin, LOW);
    delay(250);
    suffix--;
  }
  return;
}
 
 
void readAccel() {
 // interupt routine
 // Increase logtime by Interval 
 logtime += interval;
 logflag=true;
  //readAccel(&x, &y, &z);
    x=analogRead(xpin);
  y=analogRead(ypin);
  z=analogRead(zpin);

}

  

void loop() 
{


pollbutton();
   
if (runmode){

  sprintf(filename, "%s%02i.txt", BASEFILENAME,  fcounter);
  
  File dataFile = SD.open(filename, FILE_WRITE);
  if (! dataFile){
    Serial.println("Gaaaah, cant open File");
  }

// set up an interval timer to trigger every interval * 1000 mseconds.
// when interupt triggers, fire off readAccel subroutine. 
FlexiTimer2::set(interval, 1.0/1000, readAccel);  
FlexiTimer2::start();
 
 while (runmode) {
 pollbutton();
 digitalWrite(pauseledpin,LOW);
 digitalWrite(runningledpin,HIGH);
// readAccel(&x, &y, &z);
  
 if (logflag) {
  logflag=false;
  dataString = String(logtime); 
  dataString += "\t";
  dataString += String(x);
  dataString += "\t";
  dataString += String(y);
  dataString += "\t";
  dataString += String(z);
  
  Serial.println(dataString);
 
  dataFile.println(dataString);
    if (! dataFile) {
      Serial.println("CANT WRITE TO FILE !!!!!!!");
      
    }
 }
   }
     FlexiTimer2::stop(); // disable interupts until a new run
     logtime=0;     // reset clock for new run
     logflag=true;
     
   dataFile.close(); // close the file 
    flashFilenumber(fcounter); // done at the end of file writing to make timing easier for the user
   fcounter++;
  }
 
  digitalWrite(pauseledpin,HIGH);
  digitalWrite(runningledpin,LOW); 
    

         
    
  }

Thanks for sharing! Looks cool, I will certainly be looking into this when I have finished some other projects :slight_smile: