You are on page 1of 11

Embedded System Programing Lab3

In this lab we plan to do following experiments,


1. Generate signal using Pulse Width Modulation(PWM) from
Atmega32
2. How to attach Analog Light Sensor, LDR to Atmega32.
3. Mini project to control motor speed base on light intensity.
At the end of lab you have to submit soft copy of your experiment report. In this report you
will include following points:

Experiment setup:

Brief description of setup including Circuit ( if any )

Which Registers you had used and Value of each register with short
explanation why you had set that value.
(this can be done as
comment in the source code)

Results

Output port results

Reading or Observation of external devices (Sensor, LEDs)

Problems you had faced in experiment and how you solved them.
(mail this report in pdf format to prabhat_ranjan@da-iict.org with subject line :
[ESP]{LABx] Group lm . Here replace x with the lab number nd lm with your group
number. Subject heading for lab 3 for group A would be [ESP]{LAB3] Group A. Keep
cases accurate otherwise my mail handler will not handle it correctly)
Task 1: Generate Pulse from Atmega32 using PWM
Concept:
PWM or Pulse Width Modulation refers to the concept of rapidly pulsing the
digital signal of a wire to simulate a varying voltage on the wire. This method is
commonly used for driving motors, heaters, or lights in varying intensities or speeds.
A few terms are associated with PWM:
Period: how long each complete pulse cycle takes
Frequency:how often the pulses are generated. This value is typically specified in
Hz (cycles per second).
Duty Cycle:refers to the amount of time in the period that the pulse is active or
high. Duty Cycle is typically specified as a percentage of the full period.
ATmega32 has three Timer/Counters- Timer 0, Timer 1, Timer 2. Out of these Timer 0
and Timer 2 are 8-bit timers and Timer 1 is a 16 bit timer. This means that it counts from
$0000 to $FFFF (0 65535). Timer 1 has a PWM mode that allows us to generate free
running Pulse Width Modulated signals on pins PD4 and PD5. Timer 1 can act as either 8bit/9-bit/10-bit Counter. Which one we want to use can be set by setting the lowest two bits
of the register TCCR1A.

PWM11 ( bit 1 )

PWM10 ( bit 0 )

Description

PWM disabled

8-bit PWM

9-bit PWM

1
Table 1: ATmega32 PWM Mode

10-bit PWM

The counter counts up to the maximum value and then starts counting down to 0 (see the
illustration below). When the value of the counter matches that in the compare register, it
affects PD4 and PD5. The behavior of the counter when it matches the value is decided by
setting the 7th (COM1A1) and 6th (COM1A0) bit in case of PD4 and 5th (COMR1B1) and
4th (COM1B0) bit in case of PD5.

COM1X1

COM1X0

Effect on OC1X

None

None

cleared on compare match, upcounting, set on compare


match, down-counting

cleared on compare match,


down-counting, set on compare
1
match, up-counting
Table 2: Behavior of counter on compare match

The bits 0-2 of the Register TCCR1B sets the pre-scaling source of Timer 1 as derived
from the system clock frequency.
Bit2
Bit1
Bit0
Description
0

T/C 1Stopped

CK

CK/8

CK/64

CK/256

CK/1024

Clocked by pin T1, falling edge

1
1
Clocked by pin T1, rising edge
Table 3: Pre scaling source of Timer 1

Duty cycle is defined by the usual definition:

Duty Cycle = (TON*100)/(TON+TOFF)

Fig 1

[1] A working program for PWM is given in the assignment file. You have to connect
circuit given bellow and note down the experiment results.
5V

Input form
Microcontreoller

220

In4148

Fig 2
[2] Change the Duty cycle and see the effect of it on speed of motor.

Task 2: Use Analog Light Sensor with Atmega32


Light Dependant Resistor(LDR)s resistance falls drastically with an increase in the
intensity of the incident light. Being an analog sensor, it was connected to the ADC pin of

the micro-controller. This sensor played a major role in ascending the light gradient.
LDRs or Light Dependent Resistors are very useful especially in light/dark sensor circuits.
Normally the resistance of an LDR is very high, sometimes as high as 1000 000 ohms, but
when they are illuminated with light resistance drops dramatically.

Fig 3
The animation opposite shows that when the torch is turned on, the resistance of the LDR
falls, allowing current to pass through it.
Circuit to connect LDR to Micro-Controller is given below.
Conversion to the byte output of ADC channels can be done by utilizing formula:
Byte = voltage*255/5.0
(where AVCC is assumed to be 5.0 V and ADC output is 8-bit)
[1] program for ADC is given in assignment, your job is to run this program, and display
the ADC value on LEDs

Fig 4
[2] Using UART programming transfer ADC reading of micro-controller to Linux system.
TASK 3: Mini project to control motor speed base on light intensity
In this mini project you will read light intensity using ADC and LDR, base on this light

intensity you will change the speed of motor by changing duty cycle with help of PWM.
ADC will give you reading in Byte ( Max 255), for simplicity divide this ADC data into
three level and for each level select different duty cycle, base on which change the speed
of motor.
For Example :
ADC value =
0 to 75
select duty cycle 50%,
75 to 150 select duty cycle 75%,
150
select duty cycle 100%

ProgramForSerialPortCommunication
#include<avr/io.h>
#include<avr/signal.h>
#include<avr/interrupt.h>
#include<inttypes.h>
#defineXTAL4000000
#defineBAUD9600
intUart_putchar(unsignedcharcharacter)
{
loop_until_bit_is_set(UCSRA,UDRE);
UDR=character;
return0;
}
SIGNAL(SIG_UART_RECV)
{
unsignedcharcharacter;
unsignedchardummy;
character=UDR;
PORTB=~character;
Uart_putchar(character);
while(UCSRA&(1<<RXC))dummy=UDR;
}
voidInit_USART(void)
{
//USARTMode:Asynchronous
UBRRH=0x00;//writehighbytefirst
UBRRL=((XTAL/16)/BAUD)1;//baudrate9600
UCSRA=0x00;
UCSRB|=(1<<3);//TXENON,TXON,xxxx1xxx
UCSRB|=(1<<4);//RXEN,RXON,xxx11xxx

UCSRB|=(1<<7);//RXIE,RXinterruptON,1xx11xxx
UCSRC=0x86;//8Data,1Stop,NoParity1xxxx11x
SREG=(1<<7);//globalinterruptON1xxxxxxx
}
intmain(void)
{
inti,j;
unsignedinta;
DDRB=0xFF;
PORTB=0x00;
Init_USART();
sei();
while(1);
return0;
}
ProgramToControlMotorWithPWM
#include<inttypes.h>
#include<avr/io.h>
#include<avr/interrupt.h>
#include<avr/signal.h>
#definekPinInitCompleteLEDPA0
#definekDelay10000
#definekReverseDelay300000
#definekLowerLimit500
#definekUpperLimit5000
#definelight_low
500
#definelight_mediam1000
#definelight_high3000
intmain()
{
volatilelongd;

shortdir=1;
//SetLEDoutputpins
DDRA=_BV(kPinInitCompleteLED);
DDRB=0;//PortBinputs
//SetupOCRpins(PD4,PD5)asoutputs(00110000)
DDRD=_BV(PD4)|_BV(PD5);
//SetupTimer1.Timer1shouldresetwhen
//itreachesTOP=ICR1(WGM13:0=1110b).On
//comparematchclearoutput,atTOPset(COM1A1:0=10b).
TCCR1A=_BV(COM1A1)|_BV(COM1A0)//BothPWMoutputssetatTOP,
|_BV(COM1B1)|!_BV(COM1B0)//clearoncomparematch
|!_BV(FOC1A)|!_BV(FOC1B)//PWMmode,can'tforceoutput
|_BV(WGM11)|!_BV(WGM10);//FastPWM,TOP=ICR1

TCCR1B=!_BV(ICNC1)|!_BV(ICES1)//Disableinputcapturenoisecanceler,

//edgeselecttonegative.
|_BV(WGM13)|_BV(WGM12)//FastPWM,TOP=ICR1
|!_BV(CS12)|_BV(CS11)|_BV(CS10);//clk(i/o)/1024
//PWMdutycycle
OCR1A=kLowerLimit;
OCR1B=kLowerLimit;
//PWMperiod
ICR1=12500;
//Showinitializationcomplete
PORTA=_BV(kPinInitCompleteLED);

//Loopforeversteeringlefttorighttoleft
OCR1A=kLowerLimit;

while(1)
{
d=kDelay;
while(d);
OCR1A+=dir;
if(OCR1A<kLowerLimit)
{
OCR1A=kLowerLimit;
dir=1;
d=kReverseDelay;
while(d);
}
if(OCR1A>kUpperLimit)
{
OCR1A=kUpperLimit;
dir=1;
d=kReverseDelay;
while(d);
}
}
return0;
}

ProgramFORADC
#include<avr/interrupt.h>
#include<avr/signal.h>
#include<avr/delay.h>

#include<inttypes.h>
#include<avr/io.h>
#include<inttypes.h>//uint8_t==unsignedchar

#defineXTAL4000000
#defineBAUD9600
uint8_tlo_val,hi_val;
uint8_tDEBUG=0;
#defineTHRESHOLD_VALUE240
#defineTOL3
#defineDETECT_STEPS72
#defineCW0
#defineCCW1
#defineCW_OUT0x09
#defineCCW_OUT0x06
#defineCH1
SIGNAL(SIG_ADC)
{
lo_val=inp(ADCL);
hi_val=inp(ADCH);
}
voidInit_USART(void);
intmain(void)
{
DDRB=0xFF;
DDRA=0x00;
outp(0x00,PORTB);
Init_USART();
readadc(CH);
while(1)

{
readadc(CH);
delay(100);
PORTB=hi_val;
outp(0x00,ADCSRA);
}
}
uint8_treadadc(uint8_tch)
{
ADMUX=0x20|0x01;//ch;
outp((1<<ADEN)|(1<<ADSC)|(1<<ADIE)|1,ADCSRA);
sei();
while(bit_is_set(ADCSRA,ADSC));
returnhi_val;
}

You might also like