Hi,
here is a first video of my Arduino Time Lapse Intervallometer:
It is Full-HD if your computer can handle it (make it fullscreen).
Shots are taken during aprox one hour with this hardware:
Carsten
Hi,
here is a first video of my Arduino Time Lapse Intervallometer:
It is Full-HD if your computer can handle it (make it fullscreen).
Shots are taken during aprox one hour with this hardware:
Carsten
NICE! I love time lapse photography.
I've got an FZ50 and bought an Arduino to build just this thing! Do you happen to have the schematics or code posted anywhere? Great job!
The schematics are base on http://www.mindspring.com/~tom2000/Projects/AI-1_Remote/AI-1_Remote.html
The display is basically just a HD44780-compatible LCD in 4-bit mode go to
http://www.arduino.cc/playground/Code/LCD
to get an idea.
/*
X Assist Time Lapse Device
Author: Carsten Wartmann
Copyright (c) 2009 Carsten Wartmann. All right reserved.
This is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser Public License for more details.
You should have received a copy of the GNU General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
Conrad:
1x SOLID-STATE-RELAY LH1540-AT
4x FOTOTRANSISTOR/OPTOKOPPLER 4N25-000E
4x 1,8k
4x 27k
4x 33k
*/
/* Todo
- keep params in EEPROM
- besseres Focusmangement (bei Autofocus Focustime abziehen von Interval)
- F/f Auto/Manual Focuswahl
*/
// Pins
#define CLOCK 2 // grau : on the 74HC164
#define DATA 3 // rot/ws : on the 74HC164 means A1/A2 interconnected
#define EEEE 4 // violett : on the display
#define RS 5 // rosa : on the display
#define BUTA 6 // braun
#define BUTB 7 // grün
#define PADL 8 // schwarz
#define PADU 9 // rot
#define PADR 10 // orange
#define PADD 11 // gelb
#define FOCUS 13
#define EXPOSE 12
// Buffer for text
byte line[80];
// cursor position
byte cx = 0;
byte cy = 0;
unsigned long time;
unsigned long interval=5000;
boolean exlock;
unsigned int taken;
unsigned long wait;
unsigned long next;
boolean automode = false; // Exposure running
boolean apress;
int animnr=0;
char autoanim[5] = " .*A";
void setup()
{
pinMode(CLOCK, OUTPUT);
pinMode(DATA, OUTPUT);
pinMode(FOCUS, OUTPUT);
pinMode(EXPOSE, OUTPUT);
pinMode(EEEE, OUTPUT);
pinMode(RS, OUTPUT);
pinMode(BUTA, INPUT);
pinMode(BUTB, INPUT);
pinMode(PADR, INPUT);
pinMode(PADL, INPUT);
pinMode(PADU, INPUT);
pinMode(PADD, INPUT);
initLCD();
Serial.begin(38400); //Only for debugging atm, can be removed
wait=millis(); // Init the refresh delay
}
// Send a byte
void sendByte(byte pattern)
{
shiftOut(DATA, CLOCK, MSBFIRST, pattern);
digitalWrite(EEEE, LOW);
delayMicroseconds(700); //600 min?
digitalWrite(EEEE, HIGH);
}
// Send a byte COMMAND
void sendCMD(byte pattern)
{
digitalWrite(RS, LOW);
shiftOut(DATA, CLOCK, MSBFIRST, pattern);
digitalWrite(EEEE, LOW);
delayMicroseconds(700); //600 min?
digitalWrite(EEEE, HIGH);
digitalWrite(RS, HIGH);
}
void initLCD()
{
delay(105);
digitalWrite(RS, LOW);
delay(5);
sendByte(B00110000);
delay(60);
sendByte(B00110000);
delay(60);
sendByte(B00110000);
delay(60);
sendByte(B00110000);
delay(60);
sendByte(B00111000); //2 Lines 5x7pixel
sendByte(B00001000);
sendByte(B00000001);
sendByte(B00000110); //Decrement Display Shift
sendByte(B00001110); // Cursor D C B
delay(60);
delay(5);
sendByte(B0000001);
delay(60);
digitalWrite(RS, HIGH);
sendCMD(0x03); // HOME
// Init the line buffer
for (int i=0;i < 80;i++){
line[i] = 48+16;
}
}
void printIn(char msg[]) {
unsigned int i;
for (i=0;i < strlen(msg);i++){
sendByte(msg[i]);
}
}
// not used here
int smod(int z1, int z2) {
int ze;
ze=z1 % z2;
if (ze>=0) {
return(ze);
}
else{
return(z2+ze);
}
}
void printTime( int px, int py, char label[], unsigned long milli){
unsigned long h,m,s;
char timestr[3] = " ";
s = milli/1000;
m = s/60;
h = m/60;
sendCMD(0x0C);
sendCMD(0x80+px+(0x40*py)); // Cursor
printIn(label);
itoa(h,timestr,10);
if (strlen(timestr)<2){
sendByte(48);
}
printIn(timestr);
printIn(":");
itoa(m%60,timestr,10);
if (strlen(timestr)<2){
sendByte(48);
}
printIn(timestr);
printIn(":");
itoa(s%60,timestr,10);
if (strlen(timestr)<2){
sendByte(48);
}
printIn(timestr);
// printIn("s");
sendCMD(0x80+cx+(0x40*cy)); // Cursor
sendCMD(0x0E);
}
void expose()
{
taken++;
digitalWrite(EXPOSE,HIGH);
delay(200);
digitalWrite(EXPOSE,LOW);
}
void focus()
{
digitalWrite(FOCUS,HIGH);
delay(2500);
digitalWrite(FOCUS,LOW);
}
void setCursor(int px, int py)
{
// sendCMD(0x0C); // Cursor invisible
sendCMD(0x80+px+(0x40*py)); // position Cursor
// sendCMD(0x0E); // Line Cursor on
}
void gui()
{
char timestr[3] = "";
sendCMD(0x0C); // Cursor invisible
setCursor(0,0);
printIn("E:000");
itoa(taken,timestr,10);
for(int i=0; i<strlen(timestr);i++)
{
sendCMD(0x10); // Cursor invisible
}
printIn(timestr);
setCursor(0,1);
if (automode)
{
printIn("F L ");
sendByte(autoanim[animnr]);
animnr = (animnr + 1) % 4;
}
else
{
printIn("F L a");
}
setCursor(cx,cy); // position Cursor
sendCMD(0x0E); // Line Cursor on
}
void loop()
{
// Switch on Auto-Mode when on "a" and A-Button
if (cx==4 && cy==1)
{
if (digitalRead(BUTA) == LOW && !apress)
{
apress = true;
}
if (digitalRead(BUTA) == HIGH && apress)
{
automode = automode^1;
apress=false;
gui();
if (automode){ //take first picture immediately
expose();
}
}
}
// Manually take a picture when on "E" and A-Button
if (cx==0 && cy==0)
{
if (digitalRead(BUTA) == LOW && !apress)
{
apress = true;
}
if (digitalRead(BUTA) == HIGH && apress)
{
apress=false;
gui();
expose();
}
}
// Manually Focus On "F" and A Button
if (cx==0 && cy==1)
{
if (digitalRead(BUTA) == LOW && !apress)
{
apress = true;
}
if (digitalRead(BUTA) == HIGH && apress)
{
apress=false;
gui();
focus();
}
}
if (automode)
{
if (long(next-millis())<=0)
{
expose();
next=millis()+interval-200;
}
}
else
{
next=millis()+interval-200;
}
// Refresh cycle
if (millis()-wait>=300) //Wait a second
{
wait=millis();
printTime(6,0,"I=",interval);
printTime(6,1,"N=",next-millis()+1000);
gui();
}
// Cursor right
if (digitalRead(PADR) == LOW) {
cx = (cx + 1) & 15 ;// & 1 means x modulo 16
sendCMD(0x80+cx+(0x40*cy)); // Cursor
delay(200);
}
// Cursor left
if (digitalRead(PADL) == LOW) {
cx = (cx - 1) & 15; // & 1 means x modulo 16
sendCMD(0x80+cx+(0x40*cy)); // Cursor
delay(200);
}
// Pad Up
if (digitalRead(PADU) == LOW) {
if (cy==0)
{
switch (cx) {
case 8:
interval=interval+36000000;
break;
case 9:
interval=interval+3600000;
break;
case 11:
interval=interval+600000;
break;
case 12:
interval=interval+60000;
break;
case 14:
interval=interval+10000;
break;
case 15:
interval=interval+1000;
break;
}
next=millis()+interval;
printTime(6,0,"I=",interval);
//Serial.println(interval);
}
if (cx<8){
cy = 0;
sendCMD(0x80+cx+(0x40*cy)); // Cursor
}
delay(150);
}
// Pad Down
if (digitalRead(PADD) == LOW) {
if (cy==0)
{
switch (cx) {
case 8:
interval=interval-36000000;
break;
case 9:
interval=interval-3600000;
break;
case 11:
interval=interval-600000;
break;
case 12:
interval=interval-60000;
break;
case 14:
interval=interval-10000;
break;
case 15:
interval=interval-1000;
break;
}
next=millis()+interval;
printTime(6,0,"I=",interval);
//Serial.println(interval);
}
if (cx<8){
cy = 1;
sendCMD(0x80+cx+(0x40*cy)); // Cursor
}
delay(150);
}
}
You will have to change it anyhow to fit your hardware, so use with care.
Carsten
Thanks! I can't wait to try this out.
This looks very professional. I am searching for a case like yours for weeks by now. Where did you get such a nice box for your project?
Udo:
I grabbed it out of the trash... Have a look here:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1236549392/0#0
In my last post there is a hint what kind of device it it. MAYBE you can get one at ebay.
Carsten
Great. So I will try my luck at *bay. The only other case I found so far is not close as cool.