Absolutelyautomation
Published © CC BY

Low Budget Time-Lapse Camera

Reuse damaged cheap key gadget camera as time lapse camera.

IntermediateProtip3 hours1,228

Things used in this project

Story

Read more

Custom parts and enclosures

Detailed steps

Schematics

Schematics

Code

Code

C/C++
// ********************************************
// Absolutelyautomation.com
// ********************************************
//  Includes
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
// ********************************************

uint8_t watchdog_count = 0;

// ********************************************
// ISRs
ISR(WDT_vect){
	++watchdog_count;
}
// ********************************************

// Digispark Internal LED

#define CAMERA_POWER	PB0
#define ONBOARD_LED     	PB1
#define LIGHT_SENSOR		PB2
#define CAMERA_SHUTTER	PB3
#define EXT_FLASH_LIGHT	PB4



#define DELAY_SHUTTER		1000
#define DELAY_CAM_RDY	5000
#define DELAY_CAM_PWR	2500
#define DELAY_CAM_PIC		3000

int main(void) {

	// Init ONBOARD_LED pin as output
	DDRB |= (1 << ONBOARD_LED);
	// Init CAMERA_POWER pin as output
	DDRB |= (1 << CAMERA_POWER);
	// Init CAMERA_SHUTTER pin as output
	DDRB |= (1 << CAMERA_SHUTTER);
	// Init EXT_FLASH_LIGHT pin as output
	DDRB |= (1 << EXT_FLASH_LIGHT);

	// reset sequence!! (to know visually if reset)  	 

	PORTB |= (1 << ONBOARD_LED);
	_delay_ms(100);
	PORTB ^= (1 << ONBOARD_LED);
	_delay_ms(500);
	PORTB |= (1 << ONBOARD_LED);
	_delay_ms(100);
	PORTB ^= (1 << ONBOARD_LED);
	_delay_ms(1000);
	

	for (;;) {
		
		cli(); //Disable interrupts		
		MCUSR &= ~(1<<WDRF); // clear the watchdog reset
		// disable watchdog timer  
		WDTCR |= (1 << WDCE ) ;
		//WDTCR &= ( 0 << WDE );
		WDTCR &= ~( 1 << WDE );

		if(watchdog_count > 2){
			watchdog_count = 0;

			// ***********************************************************************
			//                             put your code here
			// ***********************************************************************
						
			// Light up ONBOARD_LED
			PORTB |= (1 << ONBOARD_LED);
			
			_delay_ms(100);

			// pressing, waiting and releasing turn on camera button
			PORTB |= (1 << CAMERA_POWER);			
			_delay_ms(DELAY_CAM_PWR);
			PORTB &= ~ (1 << CAMERA_POWER);

			// wait for the camera ready
			_delay_ms(DELAY_CAM_RDY);
			
			// Light conditions
			init_ADC();

			// start ADC measurement
			ADCSRA |= (1 << ADSC);         		
			// wait till conversion complete 
    			while (ADCSRA & (1 << ADSC) ); 	

    			if (ADCH > 25)
    				{
      					// turn off external flash light	
					PORTB &= ~(1 << EXT_FLASH_LIGHT );		
    				} else {
      					// turn on external flash light	
					PORTB |= (1 << EXT_FLASH_LIGHT );		
    				}

			// pressing, waiting and releasing shutter camera button
			PORTB |= (1 << CAMERA_SHUTTER);			
			_delay_ms(DELAY_SHUTTER);
			PORTB &= ~ (1 << CAMERA_SHUTTER);

			// wait for the picture taken
			_delay_ms(DELAY_CAM_PIC);

			// turn off external flash light	
			PORTB &= ~(1 << EXT_FLASH_LIGHT );		

			_delay_ms(100);

			// pressing, waiting and releasing turn off camera button
			PORTB |= (1 << CAMERA_POWER);			
			_delay_ms(DELAY_CAM_PWR);
			PORTB &= ~(1 << CAMERA_POWER);

			_delay_ms(1000);

			// turn off ONBOARD_LED
			PORTB &= ~ (1 << ONBOARD_LED);

			_delay_ms(100);

			// ***********************************************************************
		}

		TCCR0B = (1<<CS01); // Set Prescaler to 8
						
		MCUCR = (1<<SM1)|(1<<SE); //Setup Power-down mode and enable sleep

		MCUSR &= ~(1<<WDRF); // clear the watchdog reset
		// set up watchdog timer  
		WDTCR |= (1 << WDCE ) | ( 1 << WDE );
		WDTCR |= (1 << WDIE ); 
		WDTCR |= (1 << WDP3) | (1 << WDP0); // timer goes off every 8 seconds

		sei(); //Enable interrupts

		asm volatile ("sleep");
				
	}

  return 0;
}

void init_ADC()
{


	ADMUX =
				(1 << ADLAR) |   // left shift result
				(0 << REFS2) |     // Sets ref. voltage to 1.1V, bit 2
				(1 << REFS1) |     // Sets ref. voltage to 1.1V, bit 1
				(0 << REFS0) |     // Sets ref. voltage to 1.1V, bit 0

				(0 << MUX3)  |     // use ADC1 for input (PB2), MUX bit 3
				(0 << MUX2)  |     // use ADC1 for input (PB2), MUX bit 2
				(0 << MUX1)  |     // use ADC1 for input (PB2), MUX bit 1
				(1 << MUX0);       // use ADC1 for input (PB2), MUX bit 0

  	ADCSRA = 
				(1 << ADEN)  |     // Enable ADC 
				(1 << ADPS2) |     // set prescaler to 128, bit 2 
				(1 << ADPS1) |     // set prescaler to 128, bit 1 
				(1 << ADPS0);      // set prescaler to 128, bit 0  

}

Credits

Absolutelyautomation

Absolutelyautomation

3 projects • 0 followers
Projects, Articles & tech reviews for Home & Industry

Comments