Arduino Datalogger

I have recently being playing with using an arduino as a cheap datalogger for simple timing experiments using a light gate. I thought I’d share the schematics and code so that others can build and improve upon my design.

The unit connects to a light gate (or a phototransistor and LED is you want to DIY) and is triggered when the beam is broken. The logger will then display the time for which the beam was broken. It also allows the user to input the length of the card that has passed through the light gate in order to determine its velocity or acceleration. I have recently included an auto power off function so that it conserves the battery (this is not shown in the schematics below – I will update them soon). I will also include some photos of the finished unit – the total cost is about £10 per unit + about 2 hours or so of construction.

Schematics

Here’s a layout of the circuit on stripboard

light gate mk2_bb

and the circuit diagram:

light gate mk2_schem

The LCD display is a standard 16×2 which is compatible with the Hitachi HD44780 driver.  The transistor is a BC547 NPN type and everything else is on the diagram.

Arduino Code

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// setup global variables
int photodiodePin = 2, ledPin = 13, sensorPin = A0, poweroffPin = 10;
volatile int mode = 0, count = 0;
int lastState = LOW;
int sensorVal, oldSensorVal = -1;
//int inputPins[] = {0,1,3,11,12,A1,A2,A3,A4,A5};
unsigned long onTime, poweroffTime = 180000;                  // power off after 3 mins
unsigned long startTime, deltaTime, deltaTimes[2];
float output, cardLength;

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Set Card Length:");

  //for (int i = 0; i < sizeof(inputPins) - 1; i++){
  //  pinMode(i, INPUT_PULLUP);
    //    digitalWrite(i, HIGH);
  //}
  pinMode(photodiodePin, INPUT);                     // sets the digital pin as input to read photodiode
  pinMode(ledPin, OUTPUT);                           // sets an output to display when gate is high
  digitalWrite(ledPin, LOW);                         // sets led pin as LOW
  pinMode(poweroffPin, OUTPUT);                      // sets the digital pin as output to autopoweroff
  digitalWrite(poweroffPin, HIGH);                   // sets poweroff pin as HIGH
  attachInterrupt(1, changeMode, FALLING);

  onTime = millis();
}

void loop() {
  if(millis() - onTime > poweroffTime){
    digitalWrite(poweroffPin, LOW);                   // sets poweroff pin as LOW and power down
  }

  if(mode > 0){
    byte currentState = digitalRead(photodiodePin);  // read current state of input
    if(currentState == HIGH && lastState == LOW){    // rising edge detected
      if(count == 1){                                // 2nd pulse
        deltaTime = micros() - startTime;            // calc time delay
      }
      startTime = micros();
      //      digitalWrite(ledPin, HIGH);                    // set output LED ON
      onTime = millis();                             // reset onTime due to activity
    }
    if(currentState == LOW && lastState == HIGH){    // falling edge detected
      deltaTimes[count] = micros() - startTime;
      switch(count){                                 // determine if 1st or 2nd pulse
      case 0:                                      // 1st pulse
        switch(mode){
        case 1:
          output = (float)deltaTimes[0] / 1000000;
          lcd.setCursor(0,1);
          lcd.print("                ");
          lcd.setCursor(0,1);
          lcd.print(output, 4);
          lcd.print(" s");
          break;
        case 2:
          output = 10000 * (cardLength / (float)deltaTimes[0]);
          lcd.setCursor(0,1);
          lcd.print("                ");
          lcd.setCursor(0,1);
          lcd.print(output, 4);
          lcd.print(" m/s");
          break;
        case 3:
          count = 1;                             // increment counter at the end of the pulse
          break;
        }
        break;
      case 1:                                      // 2nd pulse
        count = 0;
        // Calculate acceleration
        output = 10000000000 * ((cardLength / (float)deltaTimes[1]) - (cardLength / (float)deltaTimes[0])) / (float)deltaTime;
          lcd.setCursor(0,1);
          lcd.print("                ");
          lcd.setCursor(0,1);
          lcd.print(output, 4);
          lcd.print(" m/s2");
        break;
      }
      //      digitalWrite(ledPin, LOW);                     // set output LED OFF
    }
    lastState = currentState;
  }
  else {
    sensorVal = analogRead(sensorPin) / 4;
    if (sensorVal != oldSensorVal) {
      cardLength = 1.0 + float(sensorVal) / 10.0;
      lcd.setCursor(0,1);
      lcd.print("                ");
      lcd.setCursor(0,1);
      lcd.print(cardLength, 1);
      lcd.print(" cm");
      oldSensorVal = sensorVal;
      delay(50);
    }
  }
}

void changeMode() {
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200) {
    count = 0;
    if(mode == 0){
      ADCSRA = 0;
      PRR = B11011111;
    }
    if(mode < 3){
      mode++;
    }
    else{
      mode = 1;
    }
    lcd.clear();
    switch(mode){
    case 1:
      lcd.print("Timing:");
      break;
    case 2:
      lcd.print("Velocity:");
      break;
    case 3:
      lcd.print("Acceleration:");
      break;
    }
  }
  last_interrupt_time = interrupt_time;
}

Housing

I will upload the CAD files for the housing soon.

2 thoughts on “Arduino Datalogger

  1. Hi – I’m looking to build a similar timer but with two light gates (one for ‘start’ one for ‘stop’) to conduct velocity and acceleration experiments at my school. Have you extended yours to do this?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s