PWM generation in atmega168 using data received from USART

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

Hi Friends

I am trying to generate PWM in atmega168 to control servos when data is received on the USART. but I can set the timers to Fast-PWM but don't know how to generate PWM on OCxx pin. If anyone knows plz help

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

Take a look at the various options for the WGM bits AND table 15-2 (if using Timer1).

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

You need to set the COMxx bits to the mode that you want.

Regards,
Steve A.

The Board helps those that help themselves.

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

This is a good place to start.

http://mil.ufl.edu/~achamber/servoPWMfaq.html

Also read the datasheet for Timer0 and Timer1. The easiest option in my opinion is to use the 'phase and frequency correct' mode on with the 16-bit Timer1. You set the ICR1 to a value that that the counter will count up to and then back to zero.

The time it takes the timer to count from 0 to ICR1 and back to 0 again will be your period. Most servos I've worked with require a 20ms period which is the same as 50Hz.

To calculate your ICR1 value (which is a 16 bit register) use this formula given in the datasheet.
ICR1 = FOSC / (PWM_FREQ * 2 * PRESCALER)
where FOSC is your system clock, PWM_FREQ would be 50, and the prescaler is up to you. The only time you would really need to use a prescaler is if your ICR1 is greater than 2^16. Then you can use a prescaler of 4 or 8 to make it smaller.

Once you have the period down, you need to figure out the pulse width. Again, most servos I've worked with will change direction ranging from 5 to 10 percent duty cycle with 7.5 percent being in the middle. Make sure you check your datasheet on this.

Do do this, you will change the OCR1 register. When the timer hits the OCR1 value as it is counting up to ICR1, the output OC1A will go high, and as the timer counts back down and hits the OCR1 value, it will make the output go low again. This means that as you raise or lower the value of OCR1, your duty cycle will change.

If you set your OCR1A to 7.5 percent of ICR1, the servo should be still. If you set it to 5 percent of ICR1, the servo should move full speed in one direction. If you set it to 10 percent of ICR1, the servo should move full speed in the opposite direction.

Hope that helps.

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

Koshchi wrote:
You need to set the COMxx bits to the mode that you want.
Quote:
Take a look at the various options for the WGM bits AND table 15-2 (if using Timer1).

thanks for ur response
I know how to set these bits to get the required mode. the problem is hoe to use the data from the usart to generate pwm, where to place these data, for example if i use timer0(8-bit) and for the servo time is 20ms, from this data TOP becomes 76 with a prescaler of 256.
the question is where i place TOP? should i place it in TCNT0 and the data from the usart in OCR0A/OCR0B.

Thanks

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

What functions as TOP depends on the WGM bits you choose. You have to look at the WGM table very carefully. It tells you what register is used to control TOP. The data to control the pulse width goes into OCR0A or OCR0B; one of these goes to one IO pin and the other output goes to a different IO pin.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

Quote:

the question is where i place TOP?

That depends on the speed of your AVR. There's a tool you can download from this site called avrcalc (search for it!). Just set the "Crystal Freq." to the value your AVR is clocking at. Then blob the "ms" button under "Units" at the bottom right and in the "Needed timer" type in 20.

If the initial selections lead to the bottom left saying "Out of 16 bit timer range" then drop the "Pre scale TCCRx" droplist and change it from "none" to one of the other values until the text in the bottom left is as close to 20ms as you can get.

In this picture I picked an F_CPU of 3.6864MHz. With prescale set to "none" it said "out of range" to achieve 20ms. When I set it to "8" (that is divide by 8) it led to the values shown here.

For this the OCR1AL/OCR1AH values are shown as 0x00 and 0x24. So the total OCR value used to set TOP (if using a mode where OCR sets TOP) is 0x2400. In fact I'd use mode 14 in the WGM bits so that ICR1 is used to set TOP and the OCR1A and OCR1B registers can be used for two channels of servo control.

Attachment(s):