| Author |
Message |
|
|
Posted: Mar 19, 2009 - 08:24 PM |
|

Joined: Jun 10, 2007
Posts: 53
|
|
Can you tell us a little more about your motors and how they're connected? I assume they're DC motors and connected to an HBridge of some sort, but how is the PWM connected in? A diagram might help?
Your outputs (OC1A,B) will set when compare match on upcounting and clear down counting. So if OCR1A has 200 in it and TOP is 0x3ff, the OC1A will go high when COUNT (the value in TCNT1) reaches 200 on upcounting, and will go low when TCNT reaches 200 downcounting.
The duty cycle is simply the time the output is high divided by the total cycle time. So your total cycle time is 2048 clock ticks and if your OCR1A has 200 in it, then your duty cycle is (2*(1024-200))/2048 = 80%. Putting in 0x1ff in OCR1A will indeed give a 50% duty cycle.
Making your robot turn a given amount depends on your individual robot, motors, gearing, etc. Assuming your motors are running and being controlled as you expect them to be, then this is just a matter of calibration. You have to figure out how long the motor has to be on in order to turn a measured amount.
Changing the prescaler value merely changes the speed the timer/counter runs at. Has no effect on duty cycle, so you're correct that the PWM is not affected.
Hope that helps. |
|
|
| |
|
|
|
|
|
Posted: Mar 19, 2009 - 08:41 PM |
|

Joined: Jun 10, 2007
Posts: 53
|
|
Looks like I misunderstood how this forum thing worked. The preceeding was in response to murder01's question on page 1. Sorry about that, but I hope this is useful anyway. I still don't see any diagram of the circuit being used and how the PWM is applied.
Also, assuming you're using an AVR with "timer/counter 1", you can use ICR1 as TOP, and have both OCR1A and OCR1B available to control OC1A and OC1B respectively. This gives full control of Cycle Length, and Duty Cycle for two outputs.
Another point: Frequency correctness comes about in Phase and Frequency Correct mode because the updates to the OCR registers occur only at BOTTOM and you can avoid having any "odd length cycles" during the changes. This is a minor and obscure point (IMHO); phase correctness is a much bigger deal for stepper motor control anyway.
In case you all may not have noticed, I'm attempting a tutorial on PWM Modes (building on Dean's excellent work), but I'm having problems getting it entered in this forum. Please take a minute to read it over and give me some guidance on whether or not it is worth trying to post it here or not. Thanks! |
|
|
| |
|
|
|
|
|
Posted: Mar 22, 2009 - 01:38 PM |
|

Joined: Nov 30, 2008
Posts: 174
Location: India
|
|
|
youthreewire wrote:
How do I generate PWM from two Pins which go to a H-Bridge to stall a DC motor?What care is to be taken when motor is to be stalled?(I would refer to this as 1-1 state :stalled or brake,where 1-0 corresponds to say clock wise,0-1 to anti and 0-0 to off)
Could some one please guide me? |
|
|
| |
|
|
|
|
|
Posted: Mar 23, 2009 - 12:58 PM |
|

Joined: Feb 09, 2009
Posts: 18
Location: Auckland, New Zealand
|
|
|
youthreewire wrote:
How do I generate PWM from two Pins which go to a H-Bridge to stall a DC motor?What care is to be taken when motor is to be stalled?(I would refer to this as 1-1 state :stalled or brake,where 1-0 corresponds to say clock wise,0-1 to anti and 0-0 to off)
The specifics depend entirely on which particular AVR you are using, but I presume what you want to do is set two channels to be on at the same time while the other two are off. Which two and how you go about it will further depend on your circuit... |
|
|
| |
|
|
|
|
|
Posted: Mar 24, 2009 - 05:30 AM |
|

Joined: Nov 30, 2008
Posts: 174
Location: India
|
|
| I have an atmega8 connected to a H-Bridge for driving a single motor which has two signal pins for the input.Now I want to stall the motor.How shall I do it? |
|
|
| |
|
|
|
|
|
Posted: Mar 24, 2009 - 04:06 PM |
|

Joined: Nov 17, 2004
Posts: 13833
Location: Vancouver, BC
|
|
|
Quote:
How do I generate PWM from two Pins which go to a H-Bridge to stall a DC motor?
This discussion should really be taken to a separate thread in general AVR forum. This thread should be limited to questions or comments regarding the tutorial itself, not questions about the application of the tutorial in any specific circumstance. |
_________________ Regards,
Steve A.
The Board helps those that help themselves.
|
| |
|
|
|
|
|
Posted: Mar 24, 2009 - 05:49 PM |
|

Joined: Nov 30, 2008
Posts: 174
Location: India
|
|
|
|
|
|
|
Posted: Apr 19, 2009 - 03:08 PM |
|

Joined: Mar 15, 2009
Posts: 89
|
|
hey great stuff dude! I went thru all your timer tutorials and it's very well written.
Just curious are you an engineeering student? I am as well and in university - you must be a top gun at uni then if you know how to program the AVR  |
|
|
| |
|
|
|
|
|
Posted: Apr 20, 2009 - 12:15 AM |
|


Joined: Jan 23, 2004
Posts: 9825
Location: Trondheim, Norway
|
|
|
knadoor wrote:
hey great stuff dude! I went thru all your timer tutorials and it's very well written.
Just curious are you an engineeering student? I am as well and in university - you must be a top gun at uni then if you know how to program the AVR
I'm currently in my third year of a double degree in Computer Science/Electronics Engineering at Latrobe University. I've been working with AVRs for longer than that however - since I was in early highschool.
- Dean  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
|
| |
|
|
|
|
|
Posted: Apr 20, 2009 - 11:16 PM |
|

Joined: Feb 02, 2009
Posts: 1004
|
|
|
doctek wrote:
The duty cycle is simply the time the output is high divided by the total cycle time. So your total cycle time is 2048 clock ticks and if your OCR1A has 200 in it, then your duty cycle is (2*(1024-200))/2048 = 80%. Putting in 0x1ff in OCR1A will indeed give a 50% duty cycle.
Sorry for a stupid question but if 1024 is the max value of TOP, then shouldn't it be 1024 clock ticks? Can you please explain how you calculated the duty cycle with a figure? Why did you multiply by 2? If you use just (1024-200)/1024, you still get the same answer. Appreciate your help. |
|
|
| |
|
|
|
|
|
Posted: May 01, 2009 - 02:24 PM |
|

Joined: Apr 30, 2009
Posts: 16
|
|
This and the timer are a excellent tutorial
i am newbie and currently working on this
hope to see the continuous part on this tut! |
|
|
| |
|
|
|
|
|
Posted: May 04, 2009 - 10:16 PM |
|

Joined: Jun 10, 2007
Posts: 53
|
|
| To answer your question, npat_avr, keep in mind that the timer counts up, *and then back down* in PWM modes (except for Fast PWM). So if COUNT is 1024, the total cycle is 2048 counts. In the example you give, you've divided the two into 2048 to get 1024, but the equation is still the same and still correct. |
|
|
| |
|
|
|
|
|
Posted: May 26, 2009 - 06:45 PM |
|

Joined: May 26, 2009
Posts: 1
|
|
| Very nice tutorial, but when you will complete this tutorial? |
|
|
| |
|
|
|
|
|
Posted: Jul 14, 2009 - 02:59 AM |
|

Joined: Jun 18, 2009
Posts: 28
|
|
Hey, I have a question... I NEED 3 PWM for a time based thingy... I want to create a clock with LED's and I want the glow (for minutes/seconds/Hours) to be slowly changing for each LED
12 LED's for seconds, minutes, and hours each (36 total)
SO consider the first 2 second led's on the chain:
12:00:00 Led1: 100% Led2: 0%
12:00:01 Led1: 80% Led2: 20%
12:00:02 Led1: 60% Led2: 40%
etc.
I believe you have the idea.
Then minutes would go by the same idea however hours would go by increments of 16.67% every 10 minutes.
SO I would be multiplexing to just turn the LED's obviously, however I have no idea how to implement the PWM.... Ideas?
Do some of the larger atmega chips have more timers????
Edit - Oh, wait the ATmega328P has 6 PWM channels!!!! Thats exactly how many I needed! HAHAHA.
Ok, I think I can get this to work then. |
Last edited by twist2b on Jul 14, 2009 - 03:06 AM; edited 1 time in total
|
| |
|
|
|
|
|
Posted: Jul 14, 2009 - 03:03 AM |
|


Joined: Jan 23, 2004
Posts: 9825
Location: Trondheim, Norway
|
|
The at90usb1287 has three timers at least, and the PWM megas (can't remember their part numbers) can do something like 6 channels at once.
However, PWM for LEDs isn't that critical to get absolutely perfect. Your best best is software PWM, which uses one fast tick timer and an array keeping track of the individual channel's CURRENT and TOP values. Each time the ISR fires, increment the CURRENT values for each channel, and if it matches the channel's TOP, you reset it back to zero and toggle the channel pin.
Via that method, you just set the channel's TOP array value to the desired frequency, and away you go - you can get many, many channels out of that without too much effort. The slightly wonky PWM frequencies from the conditional logic in the ISR won't be noticeable on a LED.
- Dean  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
|
| |
|
|
|
|
|
Posted: Jul 14, 2009 - 09:25 PM |
|

Joined: Jun 18, 2009
Posts: 28
|
|
| Can you make a MINI tut on THAT? |
|
|
| |
|
|
|
|
|
Posted: Jul 15, 2009 - 05:51 AM |
|


Joined: Jan 23, 2004
Posts: 9825
Location: Trondheim, Norway
|
|
Twist, here's an example of what I'm talking about:
Code:
#define NUM_CHANNELS 2
#define PWM_CHANNEL_PORT PORTD
#define PWM_CHANNEL_DDR DDRD
uint16_t SoftPWM_TOP[NUM_CHANNELS];
uint16_t SoftPWM_COMPARE[NUM_CHANNELS];
uint16_t SoftPWM_CURRENT[NUM_CHANNELS];
uint8_t SoftPWM_PinMasks[NUM_CHANNELS] = {(1 << 0), (1 << 1)};
void SetupPWMTimer(void);
void SetupPWMChannels(void);
void SetupPWMHardware(void);
int main (void)
{
SetupPWMTimer();
SetupPWMChannels();
SetupPWMHardware();
// Enable interrupts
sei();
// Loop forever, PWM taken care of via interrupt
for (;;);
}
void SetupPWMTimer(void)
{
// TODO: Set up timer 1 to fire the compare ISR every .1ms
}
void SetupPWMChannels(void)
{
// Assuming .1ms timer granularity, set first software PWM channel to 100ms period
SoftPWM_TOP[0] = 1000;
// Assuming .1ms timer granularity, set second software PWM channel to 50ms period
SoftPWM_TOP[1] = 500;
// Set first PWM channel to 1/10 duty cycle
SoftPWM_COMPARE[0] = (SoftPWM_TOP[0] / 10);
// Set second PWM channel to 1/3 duty cycle
SoftPWM_COMPARE[1] = (SoftPWM_TOP[1] / 3);
}
void SetupPWMHardware(void)
{
for (uint8_t Channel = 0; Channel < NUM_CHANNELS; Channel++)
{
// Set PWM channel as output
PWM_CHANNEL_DDR |= SoftPWM_PinMasks[Channel];
// Start with channel ON
PWM_CHANNEL_PORT |= SoftPWM_PinMasks[Channel];
}
}
ISR(TIM1_COMPARE_ISR)
{
// Loop through each software PWM channel
for (uint8_t Channel = 0; Channel < NUM_CHANNELS; Channel++)
{
// Increment each channel's CURRENT value
SoftPWM_CURRENT[Channel]++;
// When a channel's CURRENT reaches its COMPARE, clear its output
if (SoftPWM_CURRENT[Channel] == SoftPWM_COMPARE[Channel])
{
PWM_CHANNEL_PORT &= ~SoftPWM_PinMasks[Channel];
}
// When a channel's CURRENT reaches its TOP, reset it and set its output
if (SoftPWM_CURRENT[Channel] == SoftPWM_TOP[Channel])
{
PWM_CHANNEL_PORT |= SoftPWM_PinMasks[Channel];
SoftPWM_CURRENT[Channel] = 0;
}
}
}
Note that you have to set up timer 1 to your desired PWM resolution according to the CTC chapter of my Timers tutorial.
Basically, once you've set up your timer's resolution, you then set each software channel's COMPARE and TOP values to the desired multiple of this resolution -- for example, if your timer interrupts every 1ms, the timer TOP and COMPARE values are in multiples of 1ms.
Each timer the timer interrupts it increments each channel's CURRENT value. If the CURRENT value reaches the channel's COMPARE value, it clears the output. If the CURRENT value reaches TOP, it resets CURRENT and sets the output. This way each channel gets its own frequency (set by TOP) and duty cycle (set by COMPARE).
- Dean  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
Last edited by abcminiuser on Jul 15, 2009 - 05:55 AM; edited 1 time in total
|
| |
|
|
|
|
|
Posted: Jul 15, 2009 - 05:55 AM |
|


Joined: Jan 23, 2004
Posts: 9825
Location: Trondheim, Norway
|
|
Also, to add to what I've written above, note that by increasing the timer resolution (i.e. making it interrupt more times a second) you have finer control over the PWM channels, but at the expense of more CPU usage. The more channels you add will also increase the CPU usage -- although if you want a single frequency for all channels and just want to change each channel's duty cycle, you can use a single TOP value for all channels.
I haven't looked at the assembly output for this, but it might be the case that you can optimise it by making each channel a struct containing its TOP, COMPARE, CURRENT and Pin Mask values so that it can use indirect-lookup-with-offset instructions.
- Dean  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
|
| |
|
|
|
|
|
Posted: Jul 15, 2009 - 06:16 AM |
|

Joined: Jun 30, 2009
Posts: 1
|
|
G'day everyone,
Dean u r a champion. Just a quick question. I'm trying to use fast PWM for switching a MOSFET. I'm using an ATMEGA128 and I want the switching frequency to be 50 KHZ. I'm unsure on how to set this up, any help or pointers in the right direction would be hugely appreciated. |
|
|
| |
|
|
|
|
|
Posted: Jul 15, 2009 - 06:23 AM |
|


Joined: Jan 23, 2004
Posts: 9825
Location: Trondheim, Norway
|
|
alectravelyan,
In fast PWM, your choice of frequency is very limited, as TOP is fixed to be either 8, 9 or 10 bits long (depending on the AVR model and timer used). Each time the timer reaches TOP, it is reset back to zero, thus TOP sets the PWM frequency.
When in Fast PWM mode, you can only change the TOP value by specifying the number of bits you want, and by using the timer's prescaler to prescale the input clock frequency. If you specify your AVR's clock frequency, I can give you the settings which would get you closest to 50KHz.
Fast PWM is not designed to give you perfect frequency you desire, it's really only designed to give you control over the duty cycle only.
The other alternative would be to use the other PWM modes which give control over both TOP and COMPARE -- at 50KHz, I suspect this might give you better results with a fast enough AVR master clock.
- Dean  |
_________________ Atmel Studio 6.1 is now released, grab it here.
Report AS6/ASF bugs here.
|
| |
|
|
|
|
|