[TUT] [C] Newbie's Guide to AVR PWM (Incomplete)

119 posts / 0 new
Last post
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

can't wait until this tutorial is finished, i have look through many tutorials explaining PWM and Timers on the AVRs and they are all incomprehensible. This will make life a bit easier for all new AVR users :)

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

Hi Dean,

It is very long long time since you posted this "incomplete" tutorial on PWM. When can you finish this tutorial, really like your tutorial and the way you present your idea. You are a superb lecturer! Pls finish the tutorial, there are thousands of ppl waiting for your PWM tutorial!

cs

I'm happy ytd, today, and tmr :)

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

Hi,

I do intend on finishing it soon (after exams, in two weeks), but it's been very low on my priority list as I think it would be largely redundant now. There are two other complete PWM tutorials posted here now:

http://aquaticus.info/pwm

And:

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=76406

Which means any effort I make will just add to the noise and cover already covered ground.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

Good tutorial, any ideas?
I have a potentiometer to adjust with the ADC the value of the frequency of the pwm but I want to put another pot to adjust the duty cycle, using the 16 bits with the OCR and ICR.
I'm using the assembly code, any ideas on how to do it?

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

Use one of the WGM modes where ICR1 is "TOP". That is used to vary the PWM frequncy then OCR1 is used to vary the duty cycle.

 

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

I'm using that, but the duty cycle is like a porcentage. I have 10 bits of the ADC for the duty cycle. 1024 would be 100% duty cycle but depending of the frequency of the another pot that are adjusting it that is also 10 bits. I know I have to do some conversions, I can add and multiply, I have the code in Assembly. Any Ideas to adjust the duty cycle. Thank you

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
duty = top * value / 1024;

Regards,
Steve A.

The Board helps those that help themselves.

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

Dean, by chance if you read this. Could you help me out?

I'm trying to get 16 bit PWM modulation to work. Here is my code, it doesn't seem to be working



DDRB   = (1 << 3 ) | ( 1 << 2) | (1 << 1); 

TCCR1A |= (1 << COM1A1) | ( 1 << COM1B1 ) ; //set both to non inverting mode
TCCR1A |= (1 << WGM11);
TCCR1B |= (1 << WGM13) | (1 << WGM12) ;
ICR1 = 65535;

OCR1A = 60000;
OCR1B = 60000;


But it doesn't seem to be working. I also tried


OCR1AH = 60000 >> 8;
OCR1AL = 60000;

I'm just trying to get an output on ports OCR1A and OCR1B. For the 8 bit pwm channel, this always worked fine and was easy. Just had to set OCR2 = X and that would be it. But it doesn't seem to work as easily for 16 PWM.

Any ideas?

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

Please do not cross post. This is already being discussed here.

Regards,
Steve A.

The Board helps those that help themselves.

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

new2atmel wrote:
Hi all,
Firstly I have to say the Dean is a gentleman and a scholar for providing such an educational tutorial.
Secondly, if anyone is interested here is some PWM code I wrote in AVR Studio. It uses UART commands from the PC for triggering the PWM on or off. It uses the Mega32 @10MHz and sets up the PWM for motor control with the frequency set at ~20kHz @ 75% duty cycle using Timer 0

void PWM_Init()
{
	TCCR0 = (0<<WGM01)|(1<<WGM00)|(1<<CS00);//setup PMW, no prescaler
	OCR0 = 0xC0; //set 75% duty cycle
	DDRB |= (1<<DDB3);
}
void main()
{
   unsigned char PWM_on;
   unsigned char PWMON[]="PWM on Pin 4";
   unsigned char PWMOFF[]="PWM off Pin 4";
   PWM_on = 0;
   PWM_Init();
   while (1)
   {
      switch (Received_Command)
      {
        case '3':			
        if (PWM_on == 1)
        {
        TCCR0 ^=(1<<COM01); //disable OC0
        PWM_on = 0;
        UART_putstring(PWMOFF);
        USART_Transmit(LF);
        Received_Command = '0';
        }
        else
        {
        TCCR0 ^=(1<<COM01);
//Clear OC0 on compare match when up-counting. Set OC0 on compare match when downcounting.
        PWM_on = 1;
        UART_putstring(PWMON);
        USART_Transmit(LF);
        Received_Command = '0';
        }
   }//end while(1)
}




I won't bother with the UART code as there is a tute for this.
Enjoy :)

Thank you very much for this help. I am writing a program to control my servo using the PWM on the ATmega1280 (Arduino Mega).
I tried to understand the code and write a similar program but I failed. Here is the code I am using:

void pwm_r()
{
	OCR1A = 2000;
}

void pwm_l()
{
	OCR1A = 1000;
} 
   

void pwm_c()
{
	OCR1A = 1500;    
}  


void init_pwm()
{
	DDRB |= (1<<DDB3);

	//initialization of timer 1 and the frequency (50Hz)

	ICR1 = 20000;

	TCCR1A  = ((1 << COM1A1) | (1 << COM1B1) | (1 << WGM11) | (0 << WGM10)); 

	TCCR1A = ((1 << COM1A1) | (1 << COM1B1)); 
	TCCR1B = ((1 << CS10) | (1 << CS11) | (1 << WGM13));
	ICR1 = 0xFF; 
	TCCR1B = ((1 << CS10) | (1 << CS11) | (1 << WGM13) | (1 << WGM12)); 

}

I then call pwm_l, pwm_c, and pwm_r in main. The purposes of the functions are to turn the servo counter-clockwise, position it to center, and clockwise respectively. When I download the program, it only turns the servo clockwise.

What can I do to actually have the servo turn clockwise, counter-clockwise, and position it in the middle position??
Thanks a lot for the help.

Pages

Topic locked