Someone posted a request for this in the comments. After a quick search I couldn't find a simple example on how to do this so here's one I made based on the Debounce example sketch in the Arduino IDE.
/*
Debounce
Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
press), the output pin is toggled from LOW to HIGH or HIGH to LOW. There's
a minimum delay between toggles to debounce the circuit (i.e. to ignore
noise).
The circuit:
* LED attached from pin 13 to ground
* pushbutton attached from pin 2 to +5V
* 10K resistor attached from pin 2 to ground
* Note: On most Arduino boards, there is already an LED on the board
connected to pin 13, so you don't need any extra components for this example.
created 21 November 2006
by David A. Mellis
modified 3 Jul 2009
by Limor Fried
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Debounce
*/// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// Variables will change:
int ledState = HIGH; // the current state of the output pin
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
voidsetup() {
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
voidloop() {
// read the state of the switch into a local variable:
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
// this is all that's new to the code
// toggles the ledState variable each time the button is pressed
if (buttonState == HIGH) {
ledState = !ledState;
Serial.println(ledState);
}
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonState = reading;
}
// set the LED using the state of the button:
digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonState = reading;
}
Finally I had some time to do a tutorial on the Easydriver v4.2 board. The following example code is just for demonstrating the board's new functionality. It is was tested on a sparkfun stepper motor. You will notice in the code that each time the step mode changes, so to does the delay time between steps and the number of steps per revolution. The is not absolutely necessary but it helps you compare the differences between stepping modes.
Make sure you have the serial monitor open in the Arduino IDE when running this code. This will give you some feedback about the various modes of the board as they switch on an off.
Note: For real world use I would recommend hard-wiring the MS1 and MS2 pins to some switches to pull them high or low. This way you can free up some more pins on your Arduino.
For a tutorial on how to use the Easydriver v3.1 check out this post
QUESTIONS ARE WELCOME (but please keep it related to the example in this post )
///////////////////////////////////////////////////////////
// Stepper Motor skecth for use with the EasyDriver v4.2 //
///////////////////////////////////////////////////////////
// Dan Thompson 2010
//
// Use this code at your own risk.
//
// For all the product details visit http://www.schmalzhaus.com/EasyDriver/
// For the full tutorial visit http://danthompsonsblog.blogspot.com/
////// ED_v4 Step Mode Chart //////
// //
// MS1 MS2 Resolution //
// L L Full step (2 phase) //
// H L Half step //
// L H Quarter step //
// H H Eighth step //
// //
////////////////////////////////////
int DIR = 3; // PIN 3 = DIR
int STEP = 2; // PIN 2 = STEP
int MS1 = 13; // PIN 13 = MS
int MS2 = 9; // PIN 9 = MS2
int SLEEP = 12; // PIN 12 = SLP
void setup() {
Serial.begin(9600); // open the serial connection at 9600bps
pinMode(DIR, OUTPUT); // set pin 3 to output
pinMode(STEP, OUTPUT); // set pin 2 to output
pinMode(MS1, OUTPUT); // set pin 13 to output
pinMode(MS2, OUTPUT); // set pin 9 to output
pinMode(SLEEP, OUTPUT); // set pin 12 to output
}
void loop()
{
int modeType = 1; // This number increases by multiple of 2 each through the while loop..
// ..to identify our step mode type.
while (modeType<=8){ // loops the following block of code 4 times before repeating .
digitalWrite(DIR, LOW); // Set the direction change LOW to HIGH to go in opposite direction
digitalWrite(MS1, MS1_MODE(modeType)); // Set state of MS1 based on the returned value from the MS1_MODE() switch statement.
digitalWrite(MS2, MS2_MODE(modeType)); // Set state of MS2 based on the returned value from the MS2_MODE() switch statement.
digitalWrite(SLEEP, HIGH); // Set the Sleep mode to AWAKE.
int i = 0; // Set the counter variable.
while(i<(modeType*200)) // Iterate for 200, then 400, then 800, then 1600 steps.
// Then reset to 200 and start again.
{
digitalWrite(STEP, LOW); // This LOW to HIGH change is what creates the..
digitalWrite(STEP, HIGH); // .."Rising Edge" so the easydriver knows to when to step.
delayMicroseconds(1600/modeType); // This delay time determines the speed of the stepper motor.
// Delay shortens from 1600 to 800 to 400 to 200 then resets
i++;
}
modeType = modeType * 2; // Multiply the current modeType value by 2 and make the result the new value for modeType.
// This will make the modeType variable count 1,2,4,8 each time we pass though the while loop.
delay(500);
}
digitalWrite(SLEEP, LOW); // switch off the power to stepper
Serial.print("SLEEPING..");
delay(1000);
Serial.print("z");
delay(1000);
Serial.print("z");
delay(1000);
Serial.print("z");
delay(1000);
Serial.println("");
digitalWrite(SLEEP, HIGH);
Serial.println("AWAKE!!!"); // Switch on the power to stepper
delay(1000);
}
int MS1_MODE(int MS1_StepMode){ // A function that returns a High or Low state number for MS1 pin
switch(MS1_StepMode){ // Switch statement for changing the MS1 pin state
// Different input states allowed are 1,2,4 or 8
case 1:
MS1_StepMode = 0;
Serial.println("Step Mode is Full...");
break;
case 2:
MS1_StepMode = 1;
Serial.println("Step Mode is Half...");
break;
case 4:
MS1_StepMode = 0;
Serial.println("Step Mode is Quarter...");
break;
case 8:
MS1_StepMode = 1;
Serial.println("Step Mode is Eighth...");
break;
}
return MS1_StepMode;
}
int MS2_MODE(int MS2_StepMode){ // A function that returns a High or Low state number for MS2 pin
switch(MS2_StepMode){ // Switch statement for changing the MS2 pin state
// Different input states allowed are 1,2,4 or 8
case 1:
MS2_StepMode = 0;
break;
case 2:
MS2_StepMode = 0;
break;
case 4:
MS2_StepMode = 1;
break;
case 8:
MS2_StepMode = 1;
break;
}
return MS2_StepMode;
}
Well it took a little longer than a few weeks. But finally I have the first three video tutorials ready for viewing! There is still more to come, but this should be enough to get you started.
PLEASE NOTE: If you have any questions about installation, I've created a thread on the creative crash forums. You can get to it from the Servo Tools For Maya download page . Just click on the forum tab.
Shutterdrone has done it again with another great tutorial. If you are into DIY timelapse photography then you can't go past this one. It's part of a fast growing body of knowledge on the open moco website. What is open moco? It's not to be confused with open moko(open source mobile phone platform). Openmoco.org is a website dedicated to DIY motion control.
This tutorial is not only an introduction to Inervalometers, but also a step by step guide on how to build your own with a few simple components.
I have a friend who is crazy about timelapse photography. Lately he has been experimenting with motion control camera equipment to make his shots more dynamic . Most of his gear is built from combining off the self components in different ways. Nick is wanting more control out of his devices. So I introduced him to the world of electronics and micro controllers.
Now we are endevouring to break some new ground in timelapse (at least for us ;) The first task I have been appointed with is to come up with a way to go from no camera motion to full camera motion in the smoothest possible way.
Below is a snippet of Arduino code utilizing the smoothstep function. I very powerful formula for smoothing the interpolation from one value to another. Also check out this post for a python example video of the same formula
Check out some of Nick's beautiful timelapse work at nickgraalman.com
/////////////////////////////////////// // Smoothstep Interpolation Example // /////////////////////////////////////// // Dan Thompson 2009 // // Inpired by the code and chat on this site. //http://sol.gfxile.net/interpolation/index.html // // Use this code at your own risk. // // This sketch was written with motion controlled timelapse photography // in mind. I have tried to make it generic enough to understand the smoothstep // concept so that one might adapt this powerful formula in other areas as well. // // For the full tutorial visit http://danthompsonsblog.blogspot.com/ // // Usage: // 1. Upload the sketch to the Arduino. // 2. Click on the Serial monitor to see some visual feed back of the SMOOTHSTEP function. // 3. Scroll throught the print out to see the SMOOTHSTEP curve. // 4. Play with the code and addapt it to your needs! ;) #define SMOOTHSTEP(x) ((x) * (x) * (3 - 2 * (x))) //SMOOTHSTEP expression.
int j =0; //Just an Iterator. int i =0; //Just another Iterator. float A =0.0; //Input Min Value float B =100.0; //Input Max Value float X; //final smoothstepped value float v; //smoothstep expression variable float N =100.0; //number of steps void setup() { Serial.begin(9600); //establish serial connection for debugging }
void loop() { if (j < N) // Keep looping until we hit the pre-defined max number of steps { v = j / N; // Iteration divided by the number of steps. v = SMOOTHSTEP(v); // Run the smoothstep expression on v. X = (B * v) + (A * (1- v)); // Run the linear interpolation expression using the current smoothstep result. for ( i=0; i < X ; i++) // This loop could the relevant code for each time your motor steps. { Serial.print("1"); //Prints the number "1" for each step. } Serial.print(""); //Puts a space between each line of steps and their corresponding float value Serial.println(X); // prints the soothstepped value Serial.println("CLICK!!!"); // this could be where you trigger your timelapse shutter j++; // Increments j by 1. } }
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 elseif (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 } }
A quick tutorial on how to get things up and running with the EasyDriver v3.1 Stepper Motor Driver Board. A big thank you to Brian Schmalz, the designer of this board. It's obvious why he has called it the EasyDriver. It was indeed, an "EasyDriver" to set up ;)
PLEASE NOTE: some people have overlooked the extra (ground) pin on the easydriver board. It is not labeled on the board itself, but it is visible as the top right pin in the picture above. Grounding the easydriver board is essential but sometimes overlooked by newbies like myself :)
WARNING Easy Driver v4.2:
Please do not attempt this tutorial with new Easy Driver v4.2 board. Please consult the QA for version 4.2 on the Easy Driver Site for explanations on 4.2's extra functionality. For more information you can always look at the Data Sheet and Schematic as well.
Here is a copy of the code used in this Video:
////////////////////////////////////////////////////////// Stepper Motor skecth for use with the EasyDriver 3.1 ////////////////////////////////////////////////////////// Dan Thompson 2008
//// Inpired by the code and chat on this thread.
//http://forum.sparkfun.com/viewtopic.php?t=10378&highlight=easydriver//// Use this code at your own risk.
// For all the product details visit http://greta.dhs.org/EasyDriver/// For the full tutorial visit http://danthompsonsblog.blogspot.com///int dirpin =3;
int steppin =12;
void setup() {
Serial.begin(9600);
pinMode(dirpin, OUTPUT);
pinMode(steppin, OUTPUT);
}
void loop()
{
int i;
digitalWrite(dirpin, LOW); // Set the direction.
delay(100);
Serial.println(">>"); for (i =0; i<4000; i++) // Iterate for 4000 microsteps. {
digitalWrite(steppin, LOW); // This LOW to HIGH change is what creates the
digitalWrite(steppin, HIGH);// "Rising Edge" so the easydriver knows to when to step.
delayMicroseconds(200); // This delay time is close to top speed for this
} // particular motor. Any faster the motor stalls. digitalWrite(dirpin, HIGH); // Change direction.
delay(100);
Serial.println("<<");
for (i =0; i<4000; i++) // Iterate for 4000 microsteps {
digitalWrite(steppin, LOW); // This LOW to HIGH change is what creates the
digitalWrite(steppin, HIGH); // "Rising Edge" so the easydriver knows to when to step. delayMicroseconds(200); // This delay time is close to top speed for this
} // particular motor. Any faster the motor stalls.}