Monday, November 10, 2008

Timecode Based Stopwatch

A stopwatch that is timecode based. This will be the foundation for all of my motion control R and D. Eventually I hope to drive all of the mechanics by a sync pulse from a video camera. Until then this setup will have to suffice.



Here's a copy of the code used in this project.


/* Frame Rate Stopwatch By Daniel Thompson http://danthompsonsblog.blogspot.com
*
* This sketch is based on Paul Badger's StopWatch sketch which can be found here:
*
http://arduino.cc/en/Tutorial/Stopwatch
*
* The Frame Rate Stopwatch sketch runs at 25fps (PAL Video) by default and has an adjustable frame rate.
* Just change the framerate variable to suit your needs.
* Demonstrates using millis(), pullup resistors,
* making two things happen at once, printing fractions
*
* Physical setup: momentary switch connected to pin 2, other side connected to ground
* LED with series resistor between pin 13 and ground
* LCD Display setup as described in this tutorial:
*
http://www.ladyada.net/learn/arduino/lcd.html
* Easydriver v3.1 board. by Brian Schmalz
http://schmalzhaus.com/EasyDriver/
* Sparkfun Stepper Motor Connected to the Easydriver as described in this tutorial:
*
http://danthompsonsblog.blogspot.com/2008/09/easydriver-v31-tutorial.html
* 12v 0.4a regulated DC power supply.
*
* ///////////////////////////////////////////////////////////////////////////////////////
* Hardware hookup guide for Jaycar's 2x16 character backlit LCD Display MODEL No.QP5518
* ///////////////////////////////////////////////////////////////////////////////////////
*
* Note: Includes hookup info for use with a 10k Pot for contrast control.
*
* connect LCD PIN DB11 ------> Output PIN 7
* connect LCD PIN DB12 ------> Output PIN 8
* connect LCD PIN DB13 ------> Output PIN 9
* connect LCD PIN DB14 ------> Output PIN 10
* connect LCD PIN R/W -------> Ground
* connect LCD PIN 5v ------------> 10k Pot (left pin)and 5v supply
* connect LCD PIN Contrast ------> 10k Pot (middle pin)
* connect Ground -------> 10k POT (right pin)
* connect LCD PIN Gnd 0v ------> Ground
* connect LCD PIN REGISTOR SELECT ------> Output PIN 11
* connect LCD PIN ENABLE SIGNAL ------> Output PIN 12
* connect LCD PIN Gnd 0v ------> Ground
*/




#include
<LCD4Bit.h>
//create object to control an LCD.
//number of lines in display=1
LCD4Bit lcd = LCD4Bit(1);

#define ledPin 13 // LED connected to digital pin 13
#define buttonPin 2 // button on pin 2
#define steppin 5 // Easydriver step pin on pin 5
#define dirpin 3 // Easydriver step pin on pin 3

int value = LOW; // previous value of the LED
int buttonState; // variable to store button state
int lastButtonState; // variable to store last button state
int blinking; // condition for blinking - timer is timing
int frameRate = 25; // the frame rate (frames per second) at which the stopwatch runs - Change to suit
long interval = (1000/frameRate); // blink interval
long previousMillis = 0; // variable to store last time LED was updated
long startTime ; // start time for stop watch
long elapsedTime ; // elapsed time for stop watch
int fractional; // variable used to store fractional part of Frames
int fractionalSecs; // variable used to store fractional part of Seconds
int fractionalMins; // variable used to store fractional part of Minutes
int elapsedFrames; // elapsed frames for stop watch
int elapsedSeconds; // elapsed seconds for stop watch
int elapsedMinutes; // elapsed Minutes for stop watch
char buf[10]; // string buffer for itoa function

void setup()
{
Serial.begin(
9600);
pinMode(ledPin, OUTPUT);
// sets the digital pin as output
lcd.init(); // intialise the LCD.
pinMode(buttonPin, INPUT); // not really necessary, pins default to INPUT anyway
digitalWrite(buttonPin, HIGH); // turn on pullup resistors. Wire button so that press shorts pin to ground.
pinMode(dirpin, OUTPUT);
pinMode(steppin, OUTPUT);
}

void loop(){

///////////////////////////////////////
// Initiate LED and Step Pin States
///////////////////////////////////////

digitalWrite(steppin, LOW);
// Initiate the Easy Driver step pin ready for a rising edge
digitalWrite(ledPin, LOW); // set the Led to Low

//////////////////////////////
// Check for button press
//////////////////////////////
buttonState = digitalRead(buttonPin); // read the button state and store

// check for a high to low transition if true then found a new button press while clock is not running - start the clock
if (buttonState == LOW && lastButtonState == HIGH && blinking == false){
startTime
= millis(); // store the start time
blinking = true; // turn on blinking while timing
delay(5); // short delay to debounce switch
lastButtonState = buttonState; // store buttonState in lastButtonState, to compare next time
}

// check for a high to low transition if true then found a new button press while clock is running - stop the clock and report
else if (buttonState == LOW && lastButtonState == HIGH && blinking == true){
blinking
= false; // turn off blinking, all done timing
lastButtonState = buttonState; // store buttonState in lastButtonState, to compare next time

/////////////////////////////////////////////
// Routine to report elapsed time
/////////////////////////////////////////////
elapsedTime = millis() - startTime; // store elapsed time
elapsedMinutes = (elapsedTime / 60000L);
elapsedSeconds
= (elapsedTime / 1000L); // divide by 1000 to convert to seconds - then cast to an int to print
elapsedFrames = (elapsedTime / interval); // divide by 40 to convert to 1/25 of a second - then cast to an int to print
fractional = (int)(elapsedFrames % frameRate); // use modulo operator to get fractional part of 25 Frames
fractionalSecs = (int)(elapsedSeconds % 60L); // use modulo operator to get fractional part of 60 Seconds
fractionalMins = (int)(elapsedMinutes % 60L); // use modulo operator to get fractional part of 60 Minutes
lcd.clear(); // clear the LDC

if (fractionalMins < 10){ // pad in leading zeros
lcd.printIn("0"); // add a zero
}

lcd.printIn(itoa(fractionalMins, buf,
10)); // convert the int to a string and print a fractional part of 60 Minutes to the LCD
lcd.printIn(":"); //print a colan.

if (fractionalSecs < 10){ // pad in leading zeros
lcd.printIn("0"); // add a zero
}

lcd.printIn(itoa(fractionalSecs, buf,
10)); // convert the int to a string and print a fractional part of 60 Seconds to the LCD
lcd.printIn(":"); //print a colan.



if (fractional < 10){ // pad in leading zeros
lcd.printIn("0"); // add a zero
}

lcd.printIn(itoa(fractional, buf,
10)); // convert the int to a string and print a fractional part of 25 Frames to the LCD
}

else{
lastButtonState
= buttonState; // store buttonState in lastButtonState, to compare next time
}

////////////////////////////////////////////////////
// run commands at the specified time interval
////////////////////////////////////////////////////

// blink routine - blink the LED while timing
// check to see if it's time to blink the LED; that is, the difference
// between the current time and last time we blinked the LED is larger than
// the interval at which we want to blink the LED.

if ( (millis() - previousMillis > interval) ) {

if (blinking == true){
previousMillis
= millis(); // remember the last time we blinked the LED

digitalWrite(ledPin, HIGH);
// Pulse the LED for Visual Feedback
digitalWrite(steppin, HIGH); // create a rising edge for the Easydriver to step the motor once


elapsedTime
= millis() - startTime; // store elapsed time
elapsedMinutes = (elapsedTime / 60000L); // divide by 60000 to convert to minutes - then cast to an int to print
elapsedSeconds = (elapsedTime / 1000L); // divide by 1000 to convert to seconds - then cast to an int to print
elapsedFrames = (elapsedTime / interval); // divide by 40 to convert to 1/25 of a second - then cast to an int to print
fractional = (int)(elapsedFrames % frameRate);// use modulo operator to get fractional part of 25 Frames
fractionalSecs = (int)(elapsedSeconds % 60L); // use modulo operator to get fractional part of 60 Seconds
fractionalMins = (int)(elapsedMinutes % 60L); // use modulo operator to get fractional part of 60 Minutes
lcd.clear(); // clear the LDC

if (fractionalMins < 10){ // pad in leading zeros
lcd.printIn("0"); // add a zero
}

lcd.printIn(itoa(fractionalMins, buf,
10)); // convert the int to a string and print a fractional part of 60 Minutes to the LCD
lcd.printIn(":"); //print a colan.

if (fractionalSecs < 10){ // pad in leading zeros
lcd.printIn("0"); // add a zero
}

lcd.printIn(itoa(fractionalSecs, buf,
10)); // convert the int to a string and print a fractional part of 60 Seconds to the LCD
lcd.printIn(":"); //print a colan.

if (fractional < 10){ // pad in leading zeros
lcd.printIn("0"); // add a zero
}
lcd.printIn(itoa((fractional), buf,
10)); // convert the int to a string and print a fractional part of 25 Frames to the LCD
}

else{
digitalWrite(ledPin, LOW);
// turn off LED when not blinking
}
}

}