Problem using timer (PWM) on atmega8 please help

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi :)

I would like to ask question about timers.
I was serching net, datasheets and other books and I can`t figure out what`s going on in this chunk of code(questions below):


// Motor controlling

#include
#include

 int main(void)
 {
 DDRD= 0xFF;
 sei(); 
 TIMSK=(1<<OCIE2);
 TCCR2 = ((0<<WGM21)|(1<<WGM20)|(1<<CS21));
 OCR2=63;// What is the Duty cycle here when I give here this value ?? 
 PORTD=0x00;
 for(;;)
 {
  asm volatile(
	"WDR"::);
 }
 return(0);
 }
 
 //SIGNAL(SIG_OUTPUT_COMPARE2)
ISR(TIMER2_COMP_vect) 
 {                    
if(PORTD &= 0x01) 
{PORTD=0;
}
else 
{
PORTD=1;
}
 } 

I am enclosing this picture which shows my way of thinking:

As far as I am concern when TCNT1 reaches OCR1A an intterupt occurs and program should be executed:

ISR(TIMER2_COMP_vect) 
 {                    
if(PORTD &= 0x01) 
{PORTD=0;
}
else 
{
PORTD=1;
}

From this small chank of code I can state than when I have have small amount of OCR2 my DC motor should drive like mad But it is opposite only when OCR2 has a value of 255 or little less it drives really fast.

How changing OCR2 value changes duty cycle ??
Can anybody explain me this ??
Do you have any suggestions or other ways how I can control my DC motor.

Thanks in advance

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Do you have any suggestions or other ways how I can control my DC motor.

I would use OC2 (PB3) instead of manually toggling a bit. Doing it in the ISR can be dangerous since you don't really know if it was caused by an up counting match or a down counting match. You have to rely on the proper starting conditions. Also if you have other interrupts you run the risk of the timer interrupt being late or missing it all together.

Quote:
From this small chank of code I can state than when I have have small amount of OCR2 my DC motor should drive like mad

But when OCR2 is small (assuming that your ISR start conditions were correct) you would have a small duty cycle, and therefore a slower motor.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You don´t need an ISR.

This all can be done with the PWM hardware of the AVR (with no processing power).
Just initalize your timer/PWM and it runs.

Your Picture looks like a phase correct PWM with TOP= ICRn or OCRnx.

Klaus
********************************
Look at: www.megausb.de (German)
********************************

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Doing it in the ISR can be dangerous since you don't really know if it was caused by an up counting match or a down counting match. You have to rely on the proper starting conditions.

Exactly that`s what I wanted to know. I had a feeling that my match is caused by down counting match.
But as Steve said I am not sure for 100% !!!
I can speculate that from speed of my motor and from the code.

It is tricky because from datasheet we know that counting starts from $0000(0) to $00FF(255) for 8 bit resolution PWM. Then starts counting backward and cycle repeats.

I will try to solve it using OC2 because it is clearer and you know exactly what`s going on.

I am not sure about Klaus solution ??
How would you do that ?
Could you elaborate your idea ??

Thanks for all answers and help !!!
You are great !

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I am not sure about Klaus solution ??
How would you do that ?
Could you elaborate your idea ??

Look into the datasheet "phase correct PWM".
No ISR needed. No software to toggle the pin´s state. It´s all done by hardware.

Just set up the timer for phase correct PWM and set the value for the desired duty cycle into OCRx. After that you can do an infinite loop. Even no ISR is required, but the OCx pin will toggle with the desired duty cycle - all by hardware.

Klaus
********************************
Look at: www.megausb.de (German)
********************************

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I am not sure about Klaus solution ??

Klaus' solution is exactly the same as my solution.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok last request ;)

I did as you suggest:

// Controlling motor DC

#include
#include


 int main(void)
 {
 DDRB= 0x8; //setting PB3 for output
 PORTB=0;   //
 sei(); // I don`t think so nw I need it
 TIMSK=(1<<OCIE2);
 TCCR2 = ((0<<WGM21)|(1<<WGM20)|(1<<CS21)|(0<<COM20)|(1<<COM21));
// setting PWM, Phase Correct   clk/8 prescaller and //according to datasheet "Clear OC2 on Compare Match when up counting. Set OC2 on Compare Match when downcounting "
 OCR2=128; // setting OCR2 value
 TCNT2=0x00; // setting for 0 counter 
 for(;;)
 {
  asm volatile(
	"WDR"::);
 }
 return(0);
 }
 
 

But when I program atmega8 nothing happens ???
Why ??
In my opinion everything should work fine but maybe I forgot about something :)

Please tell me what I did wrong ??
There is no signal on PB3(OC2) !!

Thanks in advance !

Adam

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You appear to be enabling an interrupt (OCIE2) without providing an ISR to handle it. So the chances are the AVR keeps resetting and nothing ever happens. If you are not using interrupts then don't set any IE bits and don't do an sei() instruction.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok exactly When you get rid of sei() everything is fine !!!
I did it before writing previous post even deleted
TIMSK=(1<<OCIE2);
but i forgot to pin out my programmator which gave all the time negation to the reset and atmega8 was not able to start runnig programm.

Once again thank you all for solving my problem :)

Adam