You are on page 1of 4

1 Lab Report - 09

“Microprocessor and interfacing”


EEE-342

“Lab Report-09: Using Timers/counters of AVR


MCU for waveform generation”

NAME: Muhammad Umar


CLASS: BEE-5c
REG No: FA20-BEE-150
INSTRUCTOR: Sir Raheel Ahmed

In Lab Task 1:

A servomotor is connected to Timer OC0 pin, and a potentiometer is connected to ADC


channel 0. Generate a PWM wave at Timer 0. The duty cycle of generated waveform
should vary according to the input voltage at channel 0 of the ADC (The duty cycle should
2 Lab Report - 09

vary as you rotate the Potentiometer). By varying the On-Time of the signal the servo can
be rotated to different positions.

Code:

#include <inttypes.h>
#include <stdlib.h>
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <string.h>
#include <math.h>
//*********************************************************************
#define ADC_CHANNEL0 0
#define ADC_VREF 5 // Ref voltage for ADC is 5 Volts
#define ADC_RES 10 // Resoulution of ADC in bits
#define ADC_QLEVELS 1024 // Quantization levels for the ADC
unsigned char ADC_Initialize(); // Initialize ADC. Mode 1 = Single Conversion, Mode 2 = Free
Running
unsigned int ADC_Read(unsigned char channel); // Reads the result of a single conversion from
the ADC
/******************* Function Prototypes *********************/
void init_timer0(); // Initialize Timer0 for Fast PWM mode
void move_motor(int adc_value); // value = 0 to 1023 for -90 to 90 degrees angle
#define SERVO_OCR OCR0A
#define MIN_ANGLE_OCR 17.0
#define SERVO_OCR_OFFSET 14.0
// ***********************************************************
// Main program
int main(void)
{
init_timer0(); // timer0 configured for Fast PWM mode
ADC_Initialize();
int adc_value;
while(1)
{ // Infinite loop; define here the
adc_value = ADC_Read(ADC_CHANNEL0);
3 Lab Report - 09

_delay_ms(20);
// Set motor Position
move_motor(adc_value);
}}
void init_timer0()
{

DDRD |= (1<<6);
OCR0A = (unsigned char) SERVO_OCR;
TIMSK0 |=0b00000111;//locally enabled interrupts
TCCR0A |=0b10000011;// Configure OC0A for output(PortD.6) and Initialize timer0 for Fast
PWM Mode, Non inverting,
TCCR0B |=0b00000101;// Set Prescaler = 1024
}
/* Function Initializes the ADC for 10-Bit Single Conversion mode*/
unsigned char ADC_Initialize()
{
ADMUX |= (1<<ADLAR);// Left adjust result.
ADMUX |= (1<<REFS0);// Vref = AVCC = 5V
ADCSRA |= 0b11000111;// Enable ADC and select the prescaler for 16 MHz System Clock
return(0);
}
/* Function reads the result of a single conversion from the ADC channel given as an argument*/
unsigned int ADC_Read(unsigned char channel)
{
unsigned char ADC_lo;
unsigned char ADC_hi;
unsigned int result;
ADMUX &= ~(0x07); // clear previous selection of channel
ADMUX |= channel; // Select the new channel
// Delay needed for the stabilization of the ADC input voltage
_delay_us(10);
//wait for ADC to finish any ongoing opeartion
while((ADCSRA & (1<<ADSC)) != 0);
ADCSRA |= (1 << ADSC); //start conversion
while((ADCSRA & (1<<ADIF)) == 0);
ADCSRA |= (1<<ADIF); // clear the flag by writing 1 to it
//result = (ADCH<<8)|(ADCL & 0xC0); // Left adjust result
ADC_lo = ADCL;
4 Lab Report - 09

ADC_hi = ADCH;
result = (ADC_hi<<2)|(ADC_lo >> 6); // Right adjust result
return result;
}
void move_motor(int adc_value) // value = 0 to 1023 for -90 to 90 degrees angle
{
SERVO_OCR=((float)adc_value/1023)*(MIN_ANGLE_OCR)+14;
}

Proteus Simulation:

Critical Analysis / Conclusion:

In this lab I learned about Timers/Counters in ATmega328P, what is their usage and how they
are an important part of our MCU. I learned about the configuration registers of the Timers e.g...
TCNTn, TIMSK etc. I learned about the different modes of operation of Timers. In this lab I
used fast PWM mode to control the direction of the servo motor. In lab task controlled the
direction of the servo motor with the variable input signal at ADC channel 0 and servo connected
at Timer 0 pin, simulated this on proteus and analyzed the results.

You might also like