Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PWM for servo control

Status
Not open for further replies.
i tested with the below code but the servo is not responding. :(
Code:
#include <avr/io.h> 
#include<avr/interrupt.h>
#include<util/delay.h>

 
// Volatile keyword is important
volatile char count=0;
 unsigned int degrees;
// We use this ISR to leave only every sixth pulse and remove the rest.
// This reduces the PWM frequency to ~56Hz.
ISR(TIMER2_COMP_vect) {
	if (count){ // Disconnect the OC2 to reduce pulse rate
		TCCR2 &= ~(1<<COM21);
		count--;
	}
	else { // Connect the OC2 (PD7) for this pulse
		TCCR2 |= (1<<COM21);
		count=6;
	}
}
 
int main(void) { 
	DDRD|=(1<<PD7); // selcet OC0 as output pin
	// Fast PWM, TOP = 255, Prescale = 128, F_CPU = 11.0592Mhz
	TCCR2 |= (0<<FOC2)|(1<<WGM20)|(1<<WGM21)|(0<<COM20)|(1<<COM21)|(1<<CS20)|(0<<CS21)|(1<<CS22);
	// This gives you ~1ms pulse. (86.4 is accurate value).
	OCR2=0;
 
	// Setup interrupt so we can remove pulses from the pulse train
	TIMSK |= OCIE2;
	sei();
 
		while(1) 
		{ 
		    _delay_ms(1000);
			OCR2 = 65 + ((130 * degrees) / 180);
			degrees=degrees+1;
			if(degrees==180)
			degrees =0;
		} 
}
 
Last edited:
You need to define the cpu frequency for the _delay_ms();
I'm not sure if AVR studio does this for you. Try adding this before the library inclusion.

#define F_CPU 11059200UL
#include<util/delay.h>

Also, you need to turn on optimization for the compiler.
 
With one second delay and one degree increment it takes 3 minutes for the servo to turn 180 degrees :). That is difficult to observe.

Try:
degrees=degrees+30;
if(degrees>180)
degrees =0;
 
Its alivee!! :D thanks a lot for this.. :) and one more question, is this same for PWM with timer/counter module 0 too? if you say, its faster than me going through datasheet.. so...!
 
is this same for PWM with timer/counter module 0 too?

Otherwise it would be, but as it turned out there is no prescaler of 128 for timer/counter0, so all the calculations need to be done for different prescaler.. and the resolution will be much worse (half, actually).

Take a look at my post #4. Those settings are for timer/counter0. Only the interrupt is missing from that code.


EDIT: Here is similar code for Timer0

Code:
#include <avr/io.h> 
#include<avr/interrupt.h>

// Volatile keyword is important
volatile char count=0;

// We use this ISR to leave only every third pulse and remove the rest.
// This reduces the PWM frequency to ~56Hz.
ISR(TIMER0_COMP_vect) {
	if (count){ // Disconnect the OC0 to reduce pulse rate
		TCCR0 &= ~(1<<COM01);
		count--;
	}
	else { // Connect the OC0 (PB3) for this pulse
		TCCR0 |= (1<<COM01);
		count=3;
	}
}

int main(void) { 
	DDRB|=(1<<PB3); // selcet OC0 as output pin
	// Fast PWM, TOP = 255, Prescale = 256, F_CPU = 11.0592Mhz
	TCCR0 |= (0<<FOC0)|(1<<WGM00)|(1<<WGM01)|(0<<COM00)|(1<<COM01)|(0<<CS00)|(0<<CS01)|(1<<CS02);
	// This gives you ~1ms pulse. (43.2 is accurate value).
	OCR0=43;
	
	// Setup interrupt so we can remove pulses from the pulse train
	TIMSK |= OCIE0;
	sei();
	
		while(1) { 
		 
		} 
}


The formula would be:

OCR0 = 33 + ((64 * degrees) / 180);
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top