ES Sheet - 5
Tuesday, December 3, 2024 10:47 AM
void main() {
unsigned int digital_reading;
unsigned short speed, required_speed = 100;
short delta_speed;
float delta_output, output = 2.5, duty_cycle;
DDRD = 0xFF;
TCCR1A = ;
TCCR1B = ;
ICR1 = 25000;
OCR1A = 12500;
ADMUX = 0x40;
ADCSRA = 0x84;
while(1) {
ADCSRA |= (1<<ADSC);
while(ADCSRA & (1<<ADIF) == 0);
ADCSRA |= (1<<ADIF);
digital_reading = (ADCH<<8) | ADCL;
speed = digital_reading*0.19;
delta_speed = required_speed - speed;
delta_output = delta_speed / 40.0;
output += delta_output;
duty_cycle = output/5.0;
OCR1A = (1 - duty_cycle) * ICR1;
}
}
Lecture Problem: The speed of a DC motor is to be controlled using a
PWM signal. The motor is required to drive a load at a constant speed of
100 RPM. The motor speed will be monitored using an optical shaft
encoder. The motor has sensitivity of 40 RPM/V. The optical shaft encoder
gives one pulse per turn. Write a micro-C program for the ATMega16 MC to
control the speed of the motor using a PWM signal with a frequency of
about 30 Hz. Assume the MC is running at 1MHz.
Solution:
unsigned short run, speed, delta_speed, required_speed, delta_output,
output, sensitivity, duty_cycle;
unsigned int freq, start_count, end_count, delta_count, pulse_count;
unsigned long freq_timer1;
// Interrupt Service Routine for the Input Capture Interrupt Signal
void TIMER1_ICP_ISR () org 0x00A {
// As long as the timer is running increment the pulse_count and get the
start_count and end_count values from the input capture register
if (run == 1) {
if (pulse_count == 0) {
start_count = ICR1;
} else {
end_count = ICR1;
}
pulse_count++;
}
}
// Interrupt Service Routine for the Overflow Interrupt Signal
void TIMER1_OVF_ISR () org 0x010 {
// Indicate that the timer has reached over flow by setting run variable to
0
run = 0;
}
void main () {
// The next two lines of code are used to disable JTAG interface to be
able to use PORT C
MCUCSR |= 0x80;
MCUCSR |= 0x80;
// Configure Port B as O/P
DDRB = 0xFF;
// Configure Port D as I/P to receive the input square wave
DDRD = 0x00;
// Enable the Global Interrupt Flag in Status Register
SREG |= 0x80;
// Choose the Normal mode of operation and the prescaler of 64
// Make sure that the frequency of the timer is greater than 10 times of
the frequency to be measured (100rpm/60)
TCCR1A = 0x00;
TCCR1B = 0x03;
// Enable the Overflow and Input Capture Interrupt Flags
TIMSK = 0x24;
// Set the timer0 mode (PWM Phase Correct mode), its output mode
(set in up count, clear in down count) and the prescaler (64) to
generate a 30 Hz signal
TCCR0 = 0x73;
// Set the OCR0 level to be 0.5 of its maximum value to generate a signal
with 50% Duty Cycle and Average volt 2.5v
OCR0 = 128;
while (1) {
// Reset all the count variables
start_count = end_count = pulse_count = 0;
// Start the calculation process
run = 1;
// Wait until the timer reaches overflow
while (run == 1);
// Calculate the signal frequency
delta_count = end_count – start_count;
freq_timer1 = 1000000;
freq = (freq_timer1 * pulse_count) / delta_count;
// Calculate Speed in minutes
speed = freq * 60;
required_speed = 100;
delta_speed = required_speed – speed;
sensitivity = 40;
delta_output = delta_speed/sensitivity;
output += delta_output;
duty_cycle = output/5;
// Update the OCR0 level to change the duty cycle and control the
motor speed
OCR0 = (1 – duty_cycle) * 255;
}
}