This dissertation is an effort to learn embedded system development and embedded programming using AVR microcontroller.
This dissertation will look at the working of Analog to Digital conversion (ADC) and the usage of Pulse Width Modulation (PWM) for Digital to Analog conversion (DAC). This dissertation will also cover the features of AVR microcontroller and the usage of timers and ADC conversion in AVR microcontroller.
This dissertation will combine the Analog to Digital conversion (ADC) and Pulse Width Modulation (PWM) to create an intelligent lighting, which will be automatically controlled based on the external ambient lighting. So, at dusk, when the external sunlight gradually decreases, the intelligent light will start, and it brightness will start gradually increasing to its maximum. Similarly, at dawn, the first appearance of light in the sky before sunrise, the intelligent light will slowly start dimming and will automatically switch off in the morning.
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
// initialize adc
void adcInit()
{
// AREF = AVcc
ADMUX = (1<<REFS0);
// ADC Enable and prescaler of 128
// 8000000/128 = 62500
ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
// read adc value
uint16_t adcRead(uint8_t ch)
{
// select the corresponding channel 0~7
// ANDing with '7' will always keep the value
// of 'ch' between 0 and 7
ch &= 0b00000111; // AND operation with 7
ADMUX = (ADMUX & 0xF8)|ch; // clears the bottom 3 bits before ORing
// start single conversion
// write '1' to ADSC
ADCSRA |= (1<<ADSC);
// wait for conversion to complete
// till then, run loop continuously
// The loop does nothing while ADIF is set to 0,
// it exits as soon as ADIF is set to one,
// i.e. conversion is complete.
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
ADCSRA|=(1<<ADIF);
return (ADC);
}
void pwmInit()
{
/*
TCCR0 - Timer Counter Control Register (TIMER0)
-----------------------------------------------
BITS DESCRIPTION
NO: NAME DESCRIPTION
--------------------------
BIT 7 : FOC0 Force Output Compare [Not used in this example]
BIT 6 : WGM00 Wave form generation mode [SET to 1]
BIT 5 : COM01 Compare Output Mode [SET to 1]
BIT 4 : COM00 Compare Output Mode [SET to 0]
BIT 3 : WGM01 Wave form generation mode [SET to 1]
BIT 2 : CS02 Clock Select [SET to 0]
BIT 1 : CS01 Clock Select [SET to 0]
BIT 0 : CS00 Clock Select [SET to 1]
The above settings are for
--------------------------
Timer Clock = CPU Clock (No Prescalling)
Mode = Fast PWM
PWM Output = Non Inverted
*/
TCCR0|=(1<<WGM00)|(1<<WGM01)|(1<<COM01)|(1<<CS00);
//Set OC0 PIN as output. It is PB3 on ATmega16 ATmega32
DDRB|=(1<<PB3);
}
/******************************************************************
Sets the duty cycle of output.
Arguments
---------
duty: Between 0 - 255
0 = 0%
255 = 100%
The Function sets the duty cycle of pwm output generated on OC0 PIN
The average voltage on this output pin will be
duty
Vout= ------ x 5v
255
This can be used to control the brightness of LED or Speed of Motor.
*********************************************************************/
void setPWMOutput(uint8_t duty)
{
OCR0=duty;
}
int main()
{
uint16_t adcResult;
uint8_t pwmBrightness;
// initialize adc and pwm
adcInit();
pwmInit();
_delay_ms(50);
while(1)
{
adcResult = adcRead(0); // read adc value at PA0
// Mapping the adc value in the range of 0-1024 (2^10 bits)
// to 0-255, which can be sent to 8 bit OCR0 register.
// So the adcResult is divided by 4, to make it in the
// range of 0-255.
// After that the value is subtracted from 255, so that if
// the adc value is less, we want to send high value to the
// OCR0, for increasing brightness, and if the adc value is
// high, we want to send lower values for the PWM signal
// generation, to reduce the brightness of the LED.
pwmBrightness = (uint8_t)(255 - (adcResult/4));
//Send the pwm value to the OCR0, to control the LED brightness
setPWMOutput(pwmBrightness);
}
}
The presentation and the project report can be downloaded from the previous post: Seminar on Embedded System Development using AVR Microcontroller.