Light a eCandle

Against the darkness of all dangers, fears and sadness, keep a eCandle light.

Take a piece a paper, a resistor, a LED, the following lines of code and light a eCandle. This may be a ePrayer for the victims of the vicious terrorist attacks in Paris.

/* Constants */
const int16_t _maxDutyCycle = 256;
/* Custom variables */
volatile uint8_t *_outputPort = &PORTB;
uint8_t _outputPin = PINB5;
int16_t _absMax = (_maxDutyCycle / 1);
int16_t _absMin = (_maxDutyCycle / 4);
uint16_t _interval = 2;
/* Application variables */
volatile uint8_t _pwmOutputPinMask = (1 << _outputPin);
uint8_t _defTCCR2B;
int16_t _min = _absMin;
int16_t _max = _absMax;
	
void setup(void)
{  
	/* Initialize PWM */
	InitializePWM();
	/* Set default values */

}


/* Fliker LED attached to the output pin */
void loop(void) 
{
	_max = random(_min, _absMax);
	for (int16_t i = _min; i <= _max; i++) {
		DutyCycle(i);
		delay(_interval);
	}
	_min = random(_absMin, _max);
	for (int16_t i = _max; i >= _min; i--) {
		DutyCycle(i);
		delay(_interval);
	}
}


/* Set up output pin and timer2, clockRate at 5 */
void InitializePWM(void)
{
	cli();
	/* Set data direction */
	*(_outputPort - 1) |= _pwmOutputPinMask; 
	/* Set timer 2, Mode 3, aka Fast PWM mode */
	TCCR2A = (1 << WGM20) | (1 << WGM21); 		
	/* Set timer 2 prescaler */
	TCCR2B = 0x05;
	/* Record default value */
	_defTCCR2B = TCCR2B;
	/* Output Compare Match A Interrupt Enable and Overflow Interrupt Enable */
	TIMSK2 = (1 << OCIE2A) | (1 << TOIE2);
	sei();
}

void DutyCycle(int16_t dutyCycle)
{
	if (dutyCycle <= 0) {
		dutyCycle = 0;
		/* Stop clock */
		TCCR2B = 0x00; 
		/* Set output pin to low state */
		*(_outputPort) &= ~_pwmOutputPinMask; 
	} else if (dutyCycle >= _maxDutyCycle) {
		dutyCycle = _maxDutyCycle;
		/* Stop clock */
		TCCR2B = 0x00; 
		/* Set output pin to high state */
		*(_outputPort) |= _pwmOutputPinMask; 
	} else {
		/* Set trigger level for next compare cycle */
		OCR2A = dutyCycle; 
		/* resume clock */
		TCCR2B = _defTCCR2B; 
	}
}

/* Invoked after TCNT2 overflows */
ISR(TIMER2_OVF_vect)
{	
	/* Set output pin to high state */
	*(_outputPort) |= _pwmOutputPinMask;  
}


/* Invoked after TCNT2 equals COMPA */
ISR(TIMER2_COMPA_vect)
{
	/* Set output pin to low state */
	*(_outputPort) &= ~_pwmOutputPinMask;  
}

You may customize your own candle using the custom variables: _outputPort for any port,
_outputPin for any pin from this port, _absMax absolute max intensity, _absMin absolute min intensity and flickering intervals in milliseconds.

 

Leave a Reply

You must be logged in to post a comment.