Bike Light
From OmgaV Wiki
The Bike Light is a simple circuit based on the AVR ATtiny 85, a chocksensor, and a photodiode. The chocksensor triggers if the bike is moving and the photodiode is used to check whether it is light or dark outside. The AVR gathers the data and turns the on LEDs only if the bike is both moving and it is dark.
Developers
Source code for ATtiny 85
/*
Sykellys v.1.0
Av Egil Fykse
13.10.2009
*/
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include <inttypes.h>
#define LED1 PB4 //Define pins
#define LED2 PB0
#define SHOCK PB1
#define PHOTO_OUT PB3
#define PHOTO_IN PB2
#define DARK_DELAY 100
#define LIGHT_LEVEL 400
#define MEASURE_INTERVAL 50
volatile unsigned int darkCount = DARK_DELAY;
volatile unsigned int lightLevel;
volatile unsigned char sleeping = 0;
volatile unsigned int measureCount = 100;
volatile unsigned char blink = 1;
void myInit(){
sei(); //Turn on interrupt
//Timer0 setup:
TCCR0B |= (1<<CS02)|(1<<CS00); //prescaling
TIMSK |= (1<<TOIE0); //Timer/Counter0 Overflow Interrupt Enable
TCCR1 |= (1<<CS13)|(0<<CS12)|(1<<CS11)|(1<<CS10); //prescaling
TIMSK |= (1<<TOIE1); //Timer/Counter1 Overflow Interrupt Enable
DDRB |= (1<<LED1)|(1<<LED2)|(1<<PHOTO_OUT); //Output
GIMSK |= (1<<PCIE);
PCMSK |= (1<<PCINT1);
PORTB |= (1<<SHOCK);
PORTB |= (1<<PHOTO_OUT);
//ADC
ADMUX = 0b1;
ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Prescalar div factor =128
MCUCR |= (1<<SE)|(1<<SM1);
}
uint16_t ReadADC() {
//PRR ^= (1<<PRADC);
//Start Single conversion
ADCSRA = (1<<ADEN)|(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
//Note you may be wondering why we have write one to clear it
//This is standard way of clearing bits in io as said in datasheets.
//The code writes '1' but it result in setting bit to '0' !!!
uint16_t result = ADC;
ADCSRA|=(1<<ADIF);
return(result);
}
int main(void) {
myInit();
while (1){
if (darkCount == 0) {
blink = 0;
PORTB &= ~(1<<PHOTO_OUT);
sleeping = 1;
asm("SLEEP");
}
if (blink){
PORTB |= (1<<LED1)|(1<<LED2);
_delay_ms(500);
PORTB &= ~((1<<LED1)|(1<<LED2));
_delay_ms(500);
}
}
return 0;
}
ISR(TIMER0_OVF_vect) {
if (darkCount > 0) {
darkCount--;
}
}
ISR(TIMER1_OVF_vect) {
if (measureCount < MEASURE_INTERVAL) {
measureCount++;
} else {
lightLevel = ReadADC();
measureCount = 0;
}
}
ISR(PCINT0_vect) {
if (sleeping) {
PORTB |= (1<<PHOTO_OUT);
sleeping = 0;
lightLevel = ReadADC();
}
darkCount = DARK_DELAY;
if (lightLevel < LIGHT_LEVEL) {
blink = 1;
}
}
