Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   This topic is locked: you cannot edit posts or make replies.
View previous topic Printable version Log in to check your private messages View next topic
Author Message
abcminiuser
PostPosted: Jul 18, 2008 - 10:07 AM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

This is a continuation of my Timers tutorial and assumes the reader has read and understood that text before beginning this one.

Part Nine - Pulse Width Modulation (PWM)


The previous sections of the timers tutorial have been dealing with a simple task - flashing a LED. We've managed to accomplish that task using a variety of methods which all center around the "Clear On Timer Compare" (or CTC) method of using the timer, in both software and hardware. But what if we want to dim the LED instead? Now we are getting into a new timer concept, that of Pulse Width Modulation, abbreviated to PWM for short.

Pulse Width Modulation allows us to interface our digital components with the analogue world. We can use PWM to adjust a motor's speed, a LED's brightness or a speaker's tone. PWM is a very important concept, which is used all throughout the world of digital electronics. It is a way of approximating an analogue source, which with a little filtering can be used as a real analogue source (albeit with a few limitations).

It's important to note that PWM does not change our AVR's limitations; the signal sent out by the timer is still a true digital signal. However, by altering the on and off time of the signal at a given frequency, we can adjust the average on time to give an approximate analogue signal. This signal is good enough for immediate use in many applications - including motor speed control and LED dimming - without any extra filtering, or with the addition of a capacitor the output can be smoothed to a real analogue wave.

Let's start with a picture representing the different types of signals (modified from Wikipedia):



The top waveform is a traditional analogue signal, varying smoothly from GND to VCC volts. The bottom waveform is a digital representation of the top, using PWM.

PWM allows us to set an overall frequency, and then vary the on and off time (called the duty cycle) of the output within each timer cycle. A longer duty cycle gives a longer on time, resulting in an analogue representation closer to the VCC voltage. A duty cycle of 100% (on for the entire cycle) gives a VCC output, while a duty cycle of 0% (off for the entire cycle) gives a GND output.

When we use the CTC timer mode, what we are actually doing is essentially PWM, but with a fixed duty cycle of 50%, and a variable frequency. For this example, we're using PWM and will conversely be using a fixed frequency and varying the duty cycle to dim our LED.


There are several different PWM modes that the AVR timers can be initialized in, each with slightly different characteristics. These are as follows:

    1) Fast PWM (8, 9 or 10 bit)
    2) Phase Correct PWM
    3) Phase and Frequency Correct PWM



Before we can explore the different modes, we need to understand a little of the timer terminology. Frequency, as we know, is the number of cycles per second that the timer runs at - a higher frequency gives us a faster timer. In the PWM world, having a faster PWM frequency gives us finer control over the output, as we can respond faster to new PWM duty cycles. This is especially important when using PWM to produce audio from digital samples; a faster PWM frequency is required to give the full output frequency range by varying the duty cycle.

Next, we have the BOTTOM value. This is the lowest value that the timer will reach in the current mode. In all timer modes on all AVRs, this will be zero. Accompanying BOTTOM is TOP, which is the maximum value that the timer will reach before either (depending on the mode) resetting back to 0x00 or begin counting in reverse back to BOTTOM. For the normal mode, TOP is equal to the maximum value the timer can reach. For CTC mode, TOP is user settable, which gives us our control over the timer period. We are now using PWM, thus TOP is now set to give the PWM frequency.

Finally, we have our PWM COMPARE value. This sets the duty cycle - when this value is reached the waveform is inverted from its current state. Varying the COMPARE value will give us our varying duty cycle.

Now, let's get down to business and go into the three PWM modes.


Fast PWM

Fast PWM is useful for outputting PWM values quickly, at a loss of phase correctness - changes to the duty cycle will be reflected immediately, with the new signal being phase incorrect. When selected, the timer will count up from BOTTOM to TOP, with TOP being fixed at the bit-width of the fast PWM -- we are given a choice of 8, 9 or 10 bits depending on the timer bit width (8 bit timers will obviously not offer Fast PWM in more than 8-bits). The timer, when started, will count up continuously until TOP is reached, when it wraps back to BOTTOM and starts again. Inside this period when the counter reaches the COMPARE value, the output pin is set when the correct value is reached (and cleared when the timer wraps back from TOP to BOTTOM), so that varying COMPARE we get a PWM of a fixed frequency but a variable duty cycle.



This gives us the ability to change the duty cycle rapidly, in applications where the phase change does not matter. Applications such as motor control are particular about the phase, so we need to use the Phase Correct PWM mode.


Phase Correct PWM

Phase correct PWM gives phase-correct output as the duty cycle changes. The concept of phase is foregn to some, so we'll take a look graphically at how phase-incorrect (Fast PWM) and phase-correct PWM waveforms differ:



Notice the difference? In the case of Fast PWM, the high points are always aligned to the start of each period, with a smaller duty cycle resulting in a shorter ON time. Phase Correct PWM by contrast aligns the high points to the center of each period, so that a smaller duty cycle results in a shorter ON time -- but the ON times of all signals are aligned. As inducated in the Fast PWM explanation, this mode is useful in applications where the phase of the signals should not change, even if the duty cycles do. Phase Correct is slower than Fast PWM (as the name of the latter implies) due to the way Phase Correct PWM works.

When selected, the timer will count up from BOTTOM to TOP, and then start counting downwards back to BOTTOM before repeating. When upcounting, reaching COMPARE will turn on the output pin, while reaching the same value when downcounting will turn the output off. This results in the timer period being twice as long as Fast PWM mode (since the timer also has to count back to BOTTOM rather than just wrapping) but produces a phase-correct signal.



In Phase Correct PWM, the TOP value is variable and so the mode supports a variable PWM frequency. For generating simple audio tones from a speaker it is common to use the variable frequence of this mode to change the note pitch, and use the duty cycle to change the volume; a higher duty cycle results in a longer ON timer for the speaker, and so produces a louder sound.

SECTION INCOMPLETE - More updates soon.

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


Last edited by abcminiuser on Aug 31, 2008 - 12:44 PM; edited 1 time in total
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
new2atmel
PostPosted: Aug 13, 2008 - 04:30 PM
Rookie


Joined: Aug 06, 2007
Posts: 27


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

Code:

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 Smile
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 13, 2008 - 04:35 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

Presumably this is cut from something larger? Otherwise what's the point of a switch() with only one case: ?

(also this is presumably only going to do 20KHz if F_CPU matches yours?)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
new2atmel
PostPosted: Aug 13, 2008 - 04:44 PM
Rookie


Joined: Aug 06, 2007
Posts: 27


Yep it's huge, I just cut and pasted something that would work.
Quote:
(also this is presumably only going to do 20KHz if F_CPU matches yours?)

yes 20KHz will work only at 10MHz F_CPU with this setup - hence all the info.

Cheers
 
 View user's profile Send private message  
Reply with quote Back to top
fizgig
PostPosted: Aug 19, 2008 - 02:30 AM
Hangaround


Joined: May 03, 2005
Posts: 348
Location: Windsor, CA

Man, I can't wait for him to finish this tutorial!!!

Does anyone know of any other PWM lessons that are relevant to AVR users?
 
 View user's profile Send private message  
Reply with quote Back to top
emuler
PostPosted: Aug 30, 2008 - 09:05 AM
Raving lunatic


Joined: Feb 07, 2007
Posts: 2395
Location: New Delhi, India

Simply beautiful, Dean. Very Happy That explanation of Phase Correct PWM is the best I've ever read. Truly, a picture is worth a thousand words. (Not your words, of course. Smile )

Quote:
As this tutorial chain gets a lot of discussion and questions I'd think that moving all the tutorials to a new thread which is then locked would make sense.

I concur with what JohanEkdahl suggests. In addition, some navigation tabs (index page) so the reader can quickly jump to the desired chapter/section.
 
 View user's profile Send private message  
Reply with quote Back to top
jimy.pesin
PostPosted: Sep 29, 2008 - 09:34 PM
Newbie


Joined: Aug 29, 2008
Posts: 3
Location: Long Island, NY

I still don't see the benefit to going to a phase corrected PWM and I don't agree that you get a shorter ON time with the phase corrected PWM. The only thing is that by decreasing your frequency you will have a wider range to work with, but the minimum pulse width will remain the same and the duty cycle percentage will appear smaller because you are comparing the minimum on time to a longer period. So it seems like phase correction is be done with the fast PWM and introducing a delay to achieve the correction. Can anybody give me some insight on this?


Last edited by jimy.pesin on Oct 21, 2008 - 02:49 PM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
jimy.pesin
PostPosted: Sep 29, 2008 - 09:35 PM
Newbie


Joined: Aug 29, 2008
Posts: 3
Location: Long Island, NY

I still don't see the benefit to going to a phase corrected PWM and I don't agree that you get a shorter ON time with the phase corrected PWM. The only thing is that by decreasing your frequency you will have a wider range to work with, but the minimum pulse width will remain the same and the duty cycle percentage will appear smaller because you are comparing the minimum on time to a longer period. So it seems like phase correction can be done with the fast PWM and introducing a delay to achieve the correction. Can anybody give me some insight on this?
 
 View user's profile Send private message  
Reply with quote Back to top
GooDy88
PostPosted: Oct 21, 2008 - 01:41 PM
Newbie


Joined: Oct 21, 2008
Posts: 4


@new2atmel

I tried to understand your code, but what means DDRB |= (1<<DDB3); and ^=

Thx in advance
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Oct 21, 2008 - 01:44 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:
I tried to understand your code, but what means DDRB |= (1<<DDB3); and ^=

You need to read this ("101") tutorial thread first:

http://www.avrfreaks.net/index.php?name ... mp;t=37871

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
GooDy88
PostPosted: Oct 21, 2008 - 01:46 PM
Newbie


Joined: Oct 21, 2008
Posts: 4


Thx that makes sense I think Smile
 
 View user's profile Send private message  
Reply with quote Back to top
alwelch
PostPosted: Nov 09, 2008 - 03:45 PM
Resident


Joined: May 01, 2002
Posts: 846
Location: Texas

I would love to see an organized note on specific AVRs such as the mega128 with all the registers and code organized for timer use for all the modes. It could use a base clock of say 8Mhz and show PWM frequencies possible, etc.

Al Welch Smile
 
 View user's profile Send private message  
Reply with quote Back to top
jwcolby
PostPosted: Nov 10, 2008 - 01:42 PM
Wannabe


Joined: Sep 25, 2006
Posts: 51
Location: 28638

Dean (ABCMini),

Any chance of seeing the rest of this tutorial including some code. I have to say I love your "top down, fill in the pieces" style for tutorial writing.

I am trying to pick up the pieces and write an independent PWM motor control "module" so that I can have one or N motors. I am doing a project to control the motors on my son's ride on toy, where the lack of control causes burned up motors and stripped gears.

Thanks for the tutorial, I read the entire timer tutorial last night and other than the fact that I am still not fluent on the C bit operators it was an easy read which says a lot about your style.

Thanks,

_________________
JWColby
AVRNubee
www.ColbyConsulting.com
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
abcminiuser
PostPosted: Nov 11, 2008 - 09:39 AM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

Quote:

Any chance of seeing the rest of this tutorial including some code. I have to say I love your "top down, fill in the pieces" style for tutorial writing.


Thanks! It's been a while since I wrote any tutorials, so I'll try to pick it up again. My personal projects are starting to slow down, which is unfortunate for me but should be to the benefit to others.

I'm currently in the middle of end-of-year University exams, so I won't be able to work on this just yet. My future depends on me knowing how to do series-series feedback analysis by tomorrow.

Quote:

Thanks for the tutorial, I read the entire timer tutorial last night and other than the fact that I am still not fluent on the C bit operators it was an easy read which says a lot about your style.


Always good to know what I write is readable. I'm not always certain; it's very difficult to think from a complete new user's perspective when writing tutorials, and not sink into the depths of assumed knowledge.


For the C bit operators, read EW's "Programming 101" tutorial in the tutorials forum.

- Dean Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
robodeepak
PostPosted: Nov 13, 2008 - 09:45 AM
Newbie


Joined: Nov 12, 2008
Posts: 3


can i get this code in ATmega8??????????
 
 View user's profile Send private message  
Reply with quote Back to top
jwcolby
PostPosted: Nov 13, 2008 - 02:44 PM
Wannabe


Joined: Sep 25, 2006
Posts: 51
Location: 28638

I am thinking you can. I am hoping to get an Atmega8 running just a single PWM channel, which I will mount on a PC board with the HBridge to control a single motor. Then link it via two wire or RS232 to a central controller that actually runs my app.

Unfortunately I am still struggling to find code that I can get working. The unfortunate part is that according to my dev notes I had PWM code controlling a motor a year and a half ago but I lost the hard drive. Embarassed

_________________
JWColby
AVRNubee
www.ColbyConsulting.com
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
abcminiuser
PostPosted: Nov 13, 2008 - 11:12 PM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

Here is a simple ATMEGA16 (IIRC) example code. It's actually a DAC - digital audio in on Port D and PWM output for a speaker on the Timer 1 compare output.

Code:
#include <avr/io.h>

int main (void)
{
   // Speaker as output
   DDRB   |= (1 << 1);
   
   // DAC inputs as input, pullup
   PORTD  |= 0xFF;
   
   // Set on match, clear on TOP
   TCCR1A  = ((1 << COM1A1) | (1 << COM1A0));

   // Phase + Frequency Correct PWM, Fcpu speed
   TCCR1B  = ((1 << CS10) | (1 << WGM13));

   // TOP is 0xFF for 8-bit audio
   ICR1    = 0xFF;

   for (;;)
     OCR1A = ((int8_t)PIND + 0x7F);
}


Phase and Freq correct mode only, but should get you started.

- Dean Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
anti_dark
PostPosted: Nov 17, 2008 - 05:47 PM
Newbie


Joined: Nov 03, 2008
Posts: 11


thanx a lot for the tutorials on timer. was having great problems in beginning with timers and interrupt. ur tutorial was pretty easy and coool to begin with. thanx again. my best wishes for ur exams
 
 View user's profile Send private message  
Reply with quote Back to top
anti_dark
PostPosted: Nov 17, 2008 - 05:49 PM
Newbie


Joined: Nov 03, 2008
Posts: 11


thanx a lot for the tutorials on timer. was having great problems in beginning with timers and interrupt. ur tutorial was pretty easy and coool to begin with. thanx again. my best wishes for ur exams
 
 View user's profile Send private message  
Reply with quote Back to top
murder01
PostPosted: Nov 20, 2008 - 06:02 PM
Newbie


Joined: Sep 24, 2008
Posts: 12


Hi freaks,
First of all thank you Dean for making life so easy for newbies like me. Your tutorials are so simple and easy to follow. Hats off to you.
Coming to the problem, I am using atmega8 to design a robot. I have to use PWM to control two motors that control the two wheels of the robot. This is what I have done so far:
- Read your timer tutorial and PWM tutorial
- Read the missing part of PWM from Data Sheet
- Wrote a code to initalize PWM and test the motors
The code is as follows:
Code:

#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
#define Delay( x ) _delay_loop_2( x )

#define F_CPU 1000000UL


pwm_init()
{
     TCCR1A |= (1<< COM1A1) | (1<< COM1B1) | (1<< COM1A0) | (1<< COM1B0) | (1<< WGM10)| (1<< WGM11) ;// 10 bit PWM phase correct
     TCCR1B |= (1<< CS10); // no prescaling
     //TCCR1B |= (1<< CS10) | (1<< CS12) ;
     TCNT1 = 0x0000;
}

void pwm_set( int left_speed, int right_speed )
{
     OCR1A = left_speed;
     OCR1B = right_speed;
}
int main ()
{
   unsigned int i;
   DDRD = 0xff;
   PORTD = 0x00;
   DDRB = 0xff;

// PD0 and PD1 - right motor
// PD7 and PD6 - left motor
//  1       0 forward
//  1       1 brake (both outputs low)
//  0       1 reverse
//  0       0 coast (both outputs off =high impedance?)

     PORTB |= (1 << PB1) | (1 << PB2);
     PORTD |= (1 << PD7) | (0 << PD6) | (1 << PD0) | (0 << PD1);

pwm_init();
while(1)
{
for(i=1;i<256;i++)
{
pwm_set(i,i);
Delay(5000); //20000 cycles
}
for(i=255;i>0;i--)
{
pwm_set(i,i);
Delay(5000);
}
}
}


What I don't understand is:
- When does OC1A and OC1B gets set or clear? In this PWM mode the TOP value is 0x03FF. And I am putting values ranfing from 1 to 255 and 255 to 1 in OCR1A and OCR1B. According to me, this code should change the speed of the motors, first increase and then decrease, or vice versa.
- Also how do I set duty cycle? Why would I need it? Suppose I want to use the duty cycle of 50%, that means i put half the value of 0x03FF into OCR1A...is that right?
- I want my robot to turn 90 degrees. I think this should be done by stopping one motor and rotating the other one. But for how long should I rotate the other one so that it turns 90 degrees. As in how do I fix the time for which a particular motor runs?
-How does prescaling affect PWM? I saw that changing prescaler values made the code not run any more.
Please consider my questions. I might look ignorant to some of you. Also if this was the wrong place to post please let me know and I will post in AVR Forums. I just had to thank Dean, so I posted here.

Regards.
Sid
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Nov 20, 2008 - 08:26 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

Quote:
When does OC1A and OC1B gets set or clear?

This depends on what mode you are in and how you have the COMx bits set. In your code (Phase correct and COMx bits set to 0b11) they will be set on compare match when the timer is counting up, and cleared on compare match when the timer is counting down.
Quote:

Also how do I set duty cycle?

By setting OCRxx registers.
Quote:
Suppose I want to use the duty cycle of 50%, that means i put half the value of 0x03FF into OCR1A...is that right?

Yes.
Quote:
Why would I need it?

In the case of your motors, the higher the duty cycle, the faster the motor turns.
Quote:
I want my robot to turn 90 degrees. I think this should be done by stopping one motor and rotating the other one. But for how long should I rotate the other one so that it turns 90 degrees. As in how do I fix the time for which a particular motor runs?

This depends purely on the mechanics of how your robot is set up (how big the wheels are, how far they are apart, speed range of the motors, etc).
Quote:
How does prescaling affect PWM? I saw that changing prescaler values made the code not run any more.

Changing the prescaler will only affect the frequency of the PWM. What frequency you want depends on what it is driving.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
jwcolby
PostPosted: Nov 20, 2008 - 10:02 PM
Wannabe


Joined: Sep 25, 2006
Posts: 51
Location: 28638

Sid,

I am no expert on this but basically what is going on is that the motor acts as inductance (a coil in electronics) and "changes" the waveform that you feed it into a "DC voltage". How effectively it does that for any given frequency is determined by the motor itself, i.e. the size of the wire, the number of turns, and possibly even the standing magnetic fields caused by the motor magnets.

Thus for any given motor, there is an inductance caused by the the specific items mentioned above for that exact motor.

Now, you apply a square wave of some frequency to that motor. If the frequency is too low, the motor just passes the wave form through and does not perform the "AC to DC conversion".

As the frequency goes up, the inductance of the motor is more and more efficient at converting the waveform to a DC voltage, so the wave starts to deform from a square wave to a sawtooth, and eventually (at a high enough frequency) the sawtooth turns into AC ripple on top of a DC voltage.

Because of the DV voltage, a DC current starts to flow in one direction through the motor and the motor tries to turn.

Now... what determines how fast the motor turns is the "on" time vs the "off" time. Obviously if you are feeding a square wave with only a millisecond of on time and 999 milliseconds of off time, the "DC VOLTAGE" applied to the motor is going to be very low. As you increase the ON time of the waveform, the DC voltage gets higher and higher, and so the DC current gets higher and higher.

This is in VERY "layman" terms. But essentially, at least up to a point, the higher the frequency, the more efficiently the motor will turn the signal from a square wave to a DC voltage. The higher the percentage of on time, the higher the DC voltage created, and the faster the motor turns.

There does reach a point of diminishing returns IIRC where higher frequencies actually causes losses in the wire of the motor, and instead of being turned into a DC voltage, the wire just becomes a big radio transmitter radiating significant amounts of power out as a radio signal. At too low a frequency, there is heating in the wire and power is lost to heat.

Thus there is a balancing act where you try to find out what frequency your specific motor most efficiently transforms the frequency you apply to the motor into rotational power (DC voltage).

Someone with more knowledge of motors will no doubt jump in and tell me I am all wet (which to some extent is no doubt true) but at least this should get you started in understanding what the parts the frequency and on / off times do for you.

_________________
JWColby
AVRNubee
www.ColbyConsulting.com
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
murder01
PostPosted: Nov 21, 2008 - 02:29 PM
Newbie


Joined: Sep 24, 2008
Posts: 12


Dear Koshchi,
Thank you for your detailed response. Had a few questions:
Quote:

This depends on what mode you are in and how you have the COMx bits set. In your code (Phase correct and COMx bits set to 0b11) they will be set on compare match when the timer is counting up, and cleared on compare match when the timer is counting down.

-But when you say compare match do you mean a compare match between TCNT1 and OCR1A? For example to get a duty cycle of 50%, I will put 0x01FF in OCR1A. So TCNT1 will count from 0 to 0x03FF while upcounting and as soon at it reaches 0x01FF the OC1A output will be set.I have attached an image to show my understanding of the above.Is this right? If it is then what is the difference between this mode (i.e PWM Phase correct with TOP as 0x03FF) and mode 11 (i.e PWM Phase correct with TOP as OCR1A).
-Also to make a motor run for a certain time, say 10 seconds, and then stop it, how will I implement this in code? Should I put delays up to 10 seconds?

Again thank you so much for your kind help and time. I really appreciate.
Regards.
SID
 
 View user's profile Send private message  
Reply with quote Back to top
murder01
PostPosted: Nov 21, 2008 - 02:34 PM
Newbie


Joined: Sep 24, 2008
Posts: 12


Dear jwcolby,
Thank you so much for your response.
Quote:
This is in VERY "layman" terms. But essentially, at least up to a point, the higher the frequency, the more efficiently the motor will turn the signal from a square wave to a DC voltage. The higher the percentage of on time, the higher the DC voltage created, and the faster the motor turns.

This is exactly what I wanted to clear my basic understanding. Thank you so much once again Smile
Regards.
SID
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Nov 21, 2008 - 03:38 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

Quote:
I have attached an image to show my understanding of the above.Is this right?

Yes.
Quote:
If it is then what is the difference between this mode (i.e PWM Phase correct with TOP as 0x03FF) and mode 11 (i.e PWM Phase correct with TOP as OCR1A).

In this mode OCR1A is TOP, therefore it can not be used to set the duty cycle. You will only be able to get PWM on OC1B (using OCR1B to set the duty cycle). In the modes with a fixed number for TOP, both OC1A and OC1B may be used as PWM outputs (with independent duty cycles, but using the same frequency).

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
ERELCE
PostPosted: Nov 22, 2008 - 10:03 AM
Wannabe


Joined: Oct 23, 2005
Posts: 55
Location: BELGIUM

Sorry, I was in the wrong topic.
I've found my solution in the ADC tutorial
( to the Mod. You may delete this if you want ) Embarassed


Last edited by ERELCE on Nov 26, 2008 - 10:50 PM; edited 1 time in total
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Eloque
PostPosted: Nov 26, 2008 - 04:32 PM
Hangaround


Joined: Sep 09, 2008
Posts: 297


Dean, my man, you are awesome. If I had a sister she would be yours for the taking Smile

Instead of that I shall try to express my appreciation with words. Thank you.

_________________
Code, justify, code - Pitr Dubovich
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Nov 26, 2008 - 09:50 PM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

Quote:
Dean, my man, you are awesome. If I had a sister she would be yours for the taking


How about this - you take mine away, and we call it even? Laughing

Must remember to finish this during my holidays.

- Dean Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Eloque
PostPosted: Dec 01, 2008 - 02:28 PM
Hangaround


Joined: Sep 09, 2008
Posts: 297


I'd feel tempted, but I'd anticipate problems as well.
Other then that, if things keep going the way I want them to go, I might be able to actually finish this lasertag project.

_________________
Code, justify, code - Pitr Dubovich
 
 View user's profile Send private message  
Reply with quote Back to top
motorbyclist
PostPosted: Feb 09, 2009 - 11:44 AM
Newbie


Joined: Feb 09, 2009
Posts: 18
Location: Auckland, New Zealand

Will this ever be completed? This and the preceding tutorial are by far the best I've found and it's a shame it isn't finished.
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Feb 09, 2009 - 11:49 AM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

Quote:

Will this ever be completed? This and the preceding tutorial are by far the best I've found and it's a shame it isn't finished.


One day! I've had a lot more on my plate these holidays than I expected (read: I actually managed to get a job) which hasn't left me the motivation to finish it in the spare time I've had.

Perhaps I'll have a crack at it tomorrow, since I haven't got anything scheduled.

- Dean Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
motorbyclist
PostPosted: Feb 09, 2009 - 08:51 PM
Newbie


Joined: Feb 09, 2009
Posts: 18
Location: Auckland, New Zealand

*holds breath in anticipation*

good on you for finding a job - I left finding my summer job until after exams, which was right when the so-called recession began and now no-one is looking to hire.
 
 View user's profile Send private message  
Reply with quote Back to top
motorbyclist
PostPosted: Feb 16, 2009 - 06:45 AM
Newbie


Joined: Feb 09, 2009
Posts: 18
Location: Auckland, New Zealand

well after a bit of reading the datasheet, PWM is in fact as straightforward as hoped - took as long to find the typo in my code as it did to write it

just one question: frequency and phase correct mode - are not all modes frequency correct? It may take a bit of fiddling to get the desired frequency without too great a compromise in resolution, but I fail to see how we can have a phase (but not frequency) correct PWM signal
 
 View user's profile Send private message  
Reply with quote Back to top
mixi
PostPosted: Mar 09, 2009 - 03:01 AM
Newbie


Joined: Jan 25, 2007
Posts: 1


As of getting the robot to turn you can do as you said, but another way of making a robot turn is, to reverse the direction of one of the motors... The your robot will truely turn in a 90 degree angle Very Happy
 
 View user's profile Send private message  
Reply with quote Back to top
bugmenott
PostPosted: Mar 18, 2009 - 03:37 AM
Hangaround


Joined: Dec 31, 2006
Posts: 168


Pardon my ignorance, but I cannot figure out how to set the PMW to 8-bit rather than 10. Also, the duty cycle can be set as an integer... right?
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Mar 18, 2009 - 05:19 AM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

Quote:
Pardon my ignorance, but I cannot figure out how to set the PMW to 8-bit rather than 10.

This depends somewhat on which AVR and which timer you are using. But it is really just a matter of setting the correct mode.
Quote:
Also, the duty cycle can be set as an integer... right?

Of course, what else would it be?

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
bugmenott
PostPosted: Mar 18, 2009 - 05:04 PM
Hangaround


Joined: Dec 31, 2006
Posts: 168


I just assumed it had be be set as a hex rather than a 'counting number'
 
 View user's profile Send private message  
Reply with quote Back to top
bugmenott
PostPosted: Mar 18, 2009 - 05:05 PM
Hangaround


Joined: Dec 31, 2006
Posts: 168


I just assumed it had be be set as a hex rather than a 'counting number'
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Mar 18, 2009 - 07:53 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

Quote:
I just assumed it had be be set as a hex rather than a 'counting number'

But hex is a counting number, it just goes up to 15 instead of 9 for each digit.

The AVR only knows binary and the compiler will always transform whatever human readable form the number is in to binary.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
youthreewire
PostPosted: Mar 19, 2009 - 09:26 AM
Hangaround


Joined: Nov 30, 2008
Posts: 174
Location: India

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)
 
 View user's profile Send private message  
Reply with quote Back to top
doctek
PostPosted: Mar 19, 2009 - 08:24 PM
Wannabe


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.
 
 View user's profile Send private message  
Reply with quote Back to top
doctek
PostPosted: Mar 19, 2009 - 08:41 PM
Wannabe


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!
 
 View user's profile Send private message  
Reply with quote Back to top
youthreewire
PostPosted: Mar 22, 2009 - 01:38 PM
Hangaround


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?
 
 View user's profile Send private message  
Reply with quote Back to top
motorbyclist
PostPosted: Mar 23, 2009 - 12:58 PM
Newbie


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...
 
 View user's profile Send private message  
Reply with quote Back to top
youthreewire
PostPosted: Mar 24, 2009 - 05:30 AM
Hangaround


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?
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Mar 24, 2009 - 04:06 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
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.
 
 View user's profile Send private message  
Reply with quote Back to top
youthreewire
PostPosted: Mar 24, 2009 - 05:49 PM
Hangaround


Joined: Nov 30, 2008
Posts: 174
Location: India

Ok,sorry t hen topic continued here:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=76183
 
 View user's profile Send private message  
Reply with quote Back to top
knadoor
PostPosted: Apr 19, 2009 - 03:08 PM
Wannabe


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 Smile
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Apr 20, 2009 - 12:15 AM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

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 Smile


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 Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
npat_avr
PostPosted: Apr 20, 2009 - 11:16 PM
Posting Freak


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.
 
 View user's profile Send private message  
Reply with quote Back to top
yiunam
PostPosted: May 01, 2009 - 02:24 PM
Newbie


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!
 
 View user's profile Send private message  
Reply with quote Back to top
doctek
PostPosted: May 04, 2009 - 10:16 PM
Wannabe


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.
 
 View user's profile Send private message  
Reply with quote Back to top
Special
PostPosted: May 26, 2009 - 06:45 PM
Newbie


Joined: May 26, 2009
Posts: 1


Very nice tutorial, but when you will complete this tutorial?
 
 View user's profile Send private message  
Reply with quote Back to top
twist2b
PostPosted: Jul 14, 2009 - 02:59 AM
Rookie


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! Razz 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
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Jul 14, 2009 - 03:03 AM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

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 Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
twist2b
PostPosted: Jul 14, 2009 - 09:25 PM
Rookie


Joined: Jun 18, 2009
Posts: 28


Can you make a MINI tut on THAT?
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Jul 15, 2009 - 05:51 AM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

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 Twisted Evil

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


Last edited by abcminiuser on Jul 15, 2009 - 05:55 AM; edited 1 time in total
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
abcminiuser
PostPosted: Jul 15, 2009 - 05:55 AM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

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 Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
alectravelyan
PostPosted: Jul 15, 2009 - 06:16 AM
Newbie


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.
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Jul 15, 2009 - 06:23 AM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

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 Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
apc3161
PostPosted: Jul 17, 2009 - 01:10 AM
Rookie


Joined: Jun 14, 2009
Posts: 20


Ahh no! The tutorial is not finished! That is such a shame.

The timer tutorial was absloutely incredible and I was hoping I be able to learn PWM in the same manner. sigh...
 
 View user's profile Send private message  
Reply with quote Back to top
Latrocinium
PostPosted: Sep 06, 2009 - 12:23 AM
Newbie


Joined: Feb 23, 2009
Posts: 3


Hey guys,
N00b here. First thanks for the help Dean. Loved the tuts, but ya left me feeling like I was dating in middle school again. jk. (Only on the PWM, though)

However, I did find a good example. That I was able to understand. Needed a lil reformatting for all of us to understand.

So here is the pwm code. I can't take credit for it's generation. Check the Beer-ware license for that info. I did however edit it into one file, and note the freakin hell out of it.

This works perfectly on my tiny2313. If you get the original from the website, and get the iocompat.h it should work for any of the differences for your MCU. I find that making those changes helps me understand it better though.

Code:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

enum { UP, DOWN };


int main (void)
{

    /* Timer 1 is 10-bit PWM (8-bit PWM on some ATtinys).
      Setting WGM10 & WGM11 only will give phase correct PWM
      Setting WGM12 also will give fast PWM, but that's on TCCR1B
      COM1A1 = Clear OC1A on match when upcounting-Set OC1A
               when downcounting on match
   */
    TCCR1A |= ((1<<WGM10)|(1<<WGM11)|(1<<COM1A1));
   /* Clock Selects are for prescallers
      Current CS10 is for clock without prescalling
      Prescaler    8 = (1<<CS11)
      Prescaler   64 = ((1<<CS11)|(1<<CS10))
      Prescaler  256 = (1<<CS12)
      Prescaler 1024 = ((1<<CS12)|(1<<CS10))
   */
    TCCR1B |= ((1<<WGM12)|(1<<CS10));

    // Set Timer1/PWM register value to 0.
    OCR1A = 0;

    /* Enable OC1A or PB3 as output.
      Not sure why but only works with this pin
   */
    DDRB = (1<<3);

    // Enable timer1 overflow interrupt.
    TIMSK = (1<<TOIE1);

    sei ();

    // loop forever, the interrupts are doing the rest
    for (;;)                   
        sleep_mode();

    return (0);
}

ISR (TIMER1_OVF_vect)
{
    static uint16_t pwm;      //pwm counter var
    static uint8_t direction;   //enum var

   /*
   For those who are wondering by ++pwm, it's actually
      incrementing or decrementing everytime through the switch
      However, it does that before comparing to min or max
   */
    switch (direction)         
    {
        case UP:   //increment counter and check against Max-1
            if (++pwm == 1023)
            //start the counting other direction
                direction = DOWN;
            break;

        case DOWN:   //decrement counter and check against min
            if (--pwm == 0)
            //start counting in other direction
                direction = UP;
            break;
    }
   //set the calc'd value to Timer1 output register
    OCR1A = pwm;
}



/*
 * Obtained from http://www.nongnu.org/avr-libc/user-manual/group__demo__project.html
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 43):
 * <joerg@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.        Joerg Wunsch
 * Hey I wanna beer too ;) Actually jack & coke or a smoke, but same deal: Bart Robinson
 * ----------------------------------------------------------------------------
 *
 * Simple AVR demonstration.  Controls a LED that can be directly
 * connected from OC1/OC1A to GND.  The brightness of the LED is
 * controlled with the PWM.  After each period of the PWM, the PWM
 * value is either incremented or decremented, that's all.
 *
 * $Id: group__demo__project.html,v 1.1.1.18 2009/03/05 20:35:12 joerg_wunsch Exp $
 */


Enjoy :-p Twisted Evil
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Sep 06, 2009 - 12:31 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 21986
Location: Lund, Sweden

Quote:

Code:
    /* Enable OC1A or PB3 as output.
      Not sure why but only works with this pin
   */
    DDRB = (1<<3);



There is no provision to select which pins outputs the PWM channels of the timer. It is hard-wired in the chip. Thus Timer/Counter1's channel A always has it's output on PB3.

On some other microcontrollers you can "route" peripheral outputs to different pins, but not so on AVRs.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Latrocinium
PostPosted: Sep 06, 2009 - 01:01 AM
Newbie


Joined: Feb 23, 2009
Posts: 3


Johan,
I really appreciate that answer. I've been banging my head against the monitor for a couple(a lot more, but I'll pretend) hours.
Now to figure out another way to do a multi-channel PWM.
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Sep 06, 2009 - 02:21 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 21986
Location: Lund, Sweden

Quote:

a multi-channel PWM

How many channels?

Most AVRs have several Timer/Counters each being capable of driving two PWM channels. The tiny2313 has the eight bit Timer/Counter0 with two PWM channels, and the sixteen bit Timer/Counter1 also with two PWM channels, making for a total of four PWM channels. While the frequency must be the same for the two channels within each T/C the duty cycle is independently set for each channel.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: Sep 06, 2009 - 10:51 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

I hadn't thought about it before but I keep posting this code segment to other threads and maybe this is the appropriate place for it. What it shows is how to do PWM on an arbitrary pin by doing "soft PWM" but with timer interrupts. It works by starting a timer to have both overflow (PWM frequency) and compare (duty cycle) interrupts. In this case I wanted to vary a pulse width on PC0 using the fastest PWM frequency I could get (so timer 0 counting 256 with no prescaler) and OCR0 can be varied from 0x00 to 0xFF to vary the duty cycle:
Code:
// The following two ISRs are doing "poor man's PWM"
//  but this allows it to be on a pin of my choice
ISR(TIMER0_COMP_vect) {
        // clear the output pin on OCR0 match
   PORTC &= ~(1<<PC0);
}
ISR(TIMER0_OVF_vect) {
        // set the output pin at timer overflow
   PORTC |= (1<<PC0);
}

int main(void) {

   // going to use PORTC.0 to PWM the contrast voltage
   DDRC = (1<<DDC0);
   TIMSK |= ((1<<OCIE0) | (1<<TOIE0)); // use both interrupts
   OCR0 = 10; // 10 out of 256 means very short on period (low voltage)
   TCCR0 = (1<<CS00); // timer on - nice high PWM frequency

   // Might later consider PWMing the backlight voltage too
   // so it would also be adjustable ...
   sei();

this is just a code "snippet" for GCC, not a complete program.

The application was actually to vary the pin 3 (contrast) voltage of an HD44780 LCD module. As the comments say it would be possible to vary the backlight voltage in a similar way.

The way this example works is that it runs an 8bit timer with no prescale so every 256 clock cycles it will overflow and cause an OVF interrupt. At this point the output is turned on. The counter then starts to count up 0, 1, 2, 3,... and I have set the OCR0 register to 10 so when it counts up to 10 and TCNT0==OCR0 it will trigger the COMP(are) interrupt. At this point I switch the output off. So in a complete period of 256 counts the output is on for 10 and off for 246. So the output is only "on" for about 4% of the time. As the output pin is switching between 0V and 5V then it'll be like a voltage that is just 4% of this will be produced by the output pin (after a bit of RC filtering). So it's 4% * 5V = 0.19V

In my example I don't vary OCR so the output voltage is always at this level. But say I now set OCR to 211 (out of 256) then the output signal will be on for 211 clocks and off for 256-211=45 clocks. Because of this the output will appear to be 211/256 * 5V = 4.12V (and so on).


Cliff

_________________


Last edited by clawson on Jun 15, 2011 - 09:30 AM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
Latrocinium
PostPosted: Sep 06, 2009 - 04:11 PM
Newbie


Joined: Feb 23, 2009
Posts: 3


Actually 3 timers proved to be enough, but I wound up doing something close to what clawson just posted.
lol, wish I had seen that lastnight.
 
 View user's profile Send private message  
Reply with quote Back to top
npat_avr
PostPosted: Sep 20, 2009 - 03:54 PM
Posting Freak


Joined: Feb 02, 2009
Posts: 1004


Ok I tried the code from Joerg above and it worked. The LED is dimming perfectly (Thanks, Joerg!!).

Now I am trying to understand what the waveform of the LED current would look like? I understand the average DC value is changing for every cycle but can anyone help me with a waveform picture? I have 8MHz as my clock with no prescalar. The rest of the code is exactly identical to Joerg's code above. Thanks.
 
 View user's profile Send private message  
Reply with quote Back to top
peterminj
PostPosted: Oct 04, 2009 - 07:17 AM
Wannabe


Joined: Sep 05, 2009
Posts: 51


Dean,thanks for the wonderful tutorial.Can you give some example codes for the PWM section like in previous cases and complete this section whenever possible.

Regards,
Peter
 
 View user's profile Send private message  
Reply with quote Back to top
sagunms
PostPosted: Oct 08, 2009 - 06:59 PM
Newbie


Joined: Oct 08, 2009
Posts: 3


Thank you so much Dean for all that effort of explaining the intro of PWM to newbie like me. It was very easy to visualize how PWM works after reading this article. So, when's the remaining tutorial coming?
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Oct 08, 2009 - 10:27 PM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

I've been saying this for a very long time now, but "as soon as I get the chance". I've got a heck of a lot of University on at the moment, but that'll be ending for the year in a little more than a month.

IIRC, another user wrote his own PWM tutorial here, which was complete - that might be helpful in the interim.

- Dean Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
tech20
PostPosted: Oct 19, 2009 - 06:28 AM
Newbie


Joined: Sep 16, 2009
Posts: 4


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 Smile
 
 View user's profile Send private message  
Reply with quote Back to top
chanseng738
PostPosted: Nov 12, 2009 - 02:50 AM
Hangaround


Joined: Feb 24, 2009
Posts: 398


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 Smile
 
 View user's profile Send private message  
Reply with quote Back to top
abcminiuser
PostPosted: Nov 12, 2009 - 02:55 AM
Moderator


Joined: Jan 23, 2004
Posts: 10215
Location: Melbourne, Australia

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 ... mp;t=76406


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

- Dean Twisted Evil

_________________
Make Atmel Studio better with my free extensions. Open source and feedback welcome!
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
hmimo87
PostPosted: Nov 27, 2009 - 03:29 AM
Newbie


Joined: Sep 12, 2009
Posts: 2


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?
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Nov 27, 2009 - 09:32 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

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.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
hmimo87
PostPosted: Nov 27, 2009 - 05:07 PM
Newbie


Joined: Sep 12, 2009
Posts: 2


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
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Nov 27, 2009 - 06:07 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

Code:
duty = top * value / 1024;

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
apc3161
PostPosted: Dec 02, 2009 - 10:22 PM
Rookie


Joined: Jun 14, 2009
Posts: 20


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

Code:



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

Code:


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?
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Dec 03, 2009 - 12:25 AM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

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

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
alex.t
PostPosted: Jan 17, 2010 - 11:47 PM
Newbie


Joined: Jan 14, 2010
Posts: 11


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

Code:

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 Smile


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:

Code:

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.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jan 18, 2010 - 09:36 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

When I download the program, it only turns the servo clockwise.

Why are you seting TCCR1B and ICR1 twice? Only the second setting of each will work yet the OCR1=1000,1500,2000 with ICR1=20000 values sound like they are the ones you probably want to use (assuming F_CPU with the CS?? combination give th right tick rate)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
bgood44
PostPosted: Jan 23, 2010 - 08:37 PM
Wannabe


Joined: Mar 23, 2008
Posts: 85


Any Plans to Finish this tutorial ?
 
 View user's profile Send private message  
Reply with quote Back to top
jenni13
PostPosted: Feb 23, 2010 - 07:04 AM
Newbie


Joined: Feb 23, 2010
Posts: 1


Hi
I am trying to use Atmega16 to turn on/off a MOSFET. I don't really want to generate a PWM. My goal is that when the voltage at a specific point of the circuit is equal or greater than 5V, the MOSFET will turn on, otherwise the MOSFET will turn off.
I appreciate any hints or tutorial from all of you.
Thank you very much.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Feb 23, 2010 - 09:35 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

I appreciate any hints or tutorial from all of you.

You hijacked thew wrong tutorial. You wanted the one about Analog to Digital Conversion. Your program would basically be:
Code:
while(1) {
  take_AC_reading()
  if (reading >= threshold) {
   set IO to turn MOSFET on
  }
  else {
   clear IO to turn MOSFET off
  }
 }
}

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
salecha_rohit
PostPosted: Mar 24, 2010 - 08:25 AM
Newbie


Joined: Mar 12, 2010
Posts: 11


What i ahve understood so far from this tutorial is as follows please let me know if i am correct
TOP=OCRxx BOTTOM=TCNTx
for a PWM wave set the timer in the PWM mode first
then for say 75% duty cycle i.e. we need a count of 192/255 means OCRxx=0xC0 and TCNTx=0xFF.
now since TOP is set at 255 count and if the frequency of the CPU is say 16 Mhz then then total Time period of the wave will be 255/16Mhz=16Microsecs of which 12 microsecs is the ON period.Now this time period can be easily modified by using prescalar values.
Am i correct ?? please let me know.
but i will get the 25% off period only if i use the Toggle mode isnt it ?
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Mar 24, 2010 - 05:09 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

Quote:
i am correct

TOP=OCRxx - this depends on what mode you are in, but in the example you gave, OCRxx is the duty cycle, not TOP

BOTTOM=TCNTx - No, never. TCNTx is the current value of the timer. BOTTOM is always 0.

then for say 75% duty cycle i.e. we need a count of 192/255 means OCRxx=0xC0 and TCNTx=0xFF. - OCRxx is correct, assuming that you have selected a mode where TOP is 255. Again, no need to set TCNTx.

255/16Mhz=16Microsecs of which 12 microsecs is the ON period. - Yes, except that it is really 256/16MHz.

Now this time period can be easily modified by using prescalar values. - Yes, but you can also vary this by changing what TOP is set to.

but i will get the 25% off period only if i use the Toggle mode isnt it ? - Incorrect. You need the "clear on compare, set on TOP" mode.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
salecha_rohit
PostPosted: Mar 24, 2010 - 05:40 PM
Newbie


Joined: Mar 12, 2010
Posts: 11


How to change the TOP value ???
is there a clear on compare and set on top mode..???
 
 View user's profile Send private message  
Reply with quote Back to top
salecha_rohit
PostPosted: Mar 24, 2010 - 05:45 PM
Newbie


Joined: Mar 12, 2010
Posts: 11


ohh yea i got the Clear and Set modes but how to change the TOP value ??
for example if i am using a 16 bit Timer.. i will have to give a huge count for a duty cycle of 75% as my top value will be oxffff
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 24, 2010 - 05:46 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

How to change the TOP value ???

Pick a PWM mode from the WGM table in which the TOP column includes the name of a register rather than a fixed value.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
salecha_rohit
PostPosted: Mar 26, 2010 - 04:20 AM
Newbie


Joined: Mar 12, 2010
Posts: 11


http://www.societyofrobots.com/member_t ... s/node/228
 
 View user's profile Send private message  
Reply with quote Back to top
tabshizzle
PostPosted: Jul 19, 2010 - 01:32 AM
Newbie


Joined: Jul 13, 2010
Posts: 10


Such a shame that this tutorial is incomplete! When I search for tutorials, I specifically look to see if you have written one first.

Still, what you have posted so far is very helpful. Thanks!
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Jul 19, 2010 - 10:28 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

tabshizzle,

Did you also see:

PWM AVR Tutorial
and
PWM for complete idiots

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
tabshizzle
PostPosted: Jul 19, 2010 - 11:25 AM
Newbie


Joined: Jul 13, 2010
Posts: 10


Yes I did, those tutorials were helpful. Thanks clawson.

And while they are good tutorials, for some reason, I just prefer abcminiuser's style.
 
 View user's profile Send private message  
Reply with quote Back to top
qli029
PostPosted: Jul 21, 2010 - 04:28 AM
Newbie


Joined: Jun 30, 2010
Posts: 13


hi Dean, This is very useful material, espcially for beginners. THANKZ,

I hope you can make a PDF for it, I would like to save it for further use.

thankz again,
 
 View user's profile Send private message  
Reply with quote Back to top
dewasurya
PostPosted: Aug 01, 2010 - 05:42 AM
Newbie


Joined: May 25, 2008
Posts: 1


A very useful material indeed.

Thanks for sharing.
 
 View user's profile Send private message  
Reply with quote Back to top
chooglin
PostPosted: Aug 15, 2010 - 10:09 PM
Rookie


Joined: Nov 07, 2008
Posts: 22
Location: E. Europe > Romania > Bucharest

I can't grasp the difference between phase correct PWM and fast PWM.
I see that you consider the time periods to start at different moments, but that is not relevant to the circuit, is it? In both cases it sees some evenly spaced duty cicles.


And second: why 8-9-10 bit PWM and not 16bit PWM? Timer1 is 2 bytes long, it can count on 16 bits, but the PWM will be 10 bits because ......................

?
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Aug 15, 2010 - 10:29 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 21986
Location: Lund, Sweden

Quote:

In both cases it sees some evenly spaced duty cicles.

Depends on what you mean by "evenly". Lets consider a simplified case where the counter counts to 4 (ie 5 steps before it wraps. Lets look at 20% and 60% duty cycle they would be like below for fast PWM

Code:
20%: 10000100001000010000...
60%: 11100111001110011100...

but for phase correct PWM they would be
Code:
20%: 00100001000010000100...
60%: 01110011100111001110...

Now, finally, to hopefully make the difference obvious lets look at two syscles of 20% and two cycles of 60% for both fast PWM and phase correct PWM

Code:
fast PM           10000100001110011100
phase correct PWM 00100001000111001110

Now, lets align the 20% on-parts with each other

Code:
fast PM           ..10000100001110011100
phase correct PWM 00100001000111001110..
                    ^    ^    ^    ^

and notice how the 60% on-parts are not matching.

Phase correct PWM is about centring the on-part around a specific, iterating, point in time (which I have marked above with ^). (Fast PWM starts its on-parts at those points).
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: Aug 16, 2010 - 09:50 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

Here's a tip. If you want to know how something looks different then type "phase correct PWM" into Google's image search. You'll get a number of results including this one:



(rather ironically that URL says that is hosted on fourwalledcubicle.com (Dean's site) and appears on Freaks in a Timer tutorial)

EDIT irony upon irony, that picture is in the first post of this very thread - so exactly what don't you understand about it now? Surely that shows exactly how fast/phase-correct differ - with phase correct having the pulse centred in the time frame.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Aug 16, 2010 - 10:58 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 21986
Location: Lund, Sweden

I guess the question 'chooglin' might ask now is: Why do you need it?
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
chooglin
PostPosted: Aug 18, 2010 - 05:55 PM
Rookie


Joined: Nov 07, 2008
Posts: 22
Location: E. Europe > Romania > Bucharest

I do understand that P.C. PWM means the cycles are centered on specific points in time.
OK, the theory is solid, but the motors see this in both cases:
pulse at t.... pulse at t+T.... pulse at t+2T


Can you explain (without unwitty irony) the physical phenomenon why the centering of impulses at equal time intervals works for motors and the lack of centering doesn't?
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 18, 2010 - 08:31 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

It's more to do with when you are playing back something like audio where the duty cycle varies in each PWM cycle and you don't want artefacts at the switching point. I'm not sure I can see a point of PC for motor control though when you are doing three phase brushless I guess it might come into play - but not for a simple DC motor.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Aug 18, 2010 - 09:53 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 21986
Location: Lund, Sweden

IIRC there is a AVR App Note where phase correct is used to drive a DC motor.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
BenRosmalen
PostPosted: Sep 05, 2010 - 09:09 PM
Newbie


Joined: Aug 11, 2010
Posts: 2
Location: the Neteherlands

Thanks for the tutorial. I am using the atMega324P and without particular reason I like to use the 8-bit timer2 to explorer the in and outs of Phase correct PWM. Both OCRxn (OCR2A & OCR2B) are clear to me and I want to use them both to drive pins OC2A and OC2B. But I did not find a way to set the TOP value.
After reading the datasheet over and over it became clear the TOP value is predefined as 255 for the Phase correct PWM when you want drive both pins using OCR2A and OCR2B, to manipulate the duty cycle. In that case Timer2 has no additional register like ICR1 in timer1 to vary the TOP value in Phase correct PWM.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
narayanatammineni
PostPosted: Jan 06, 2011 - 02:39 PM
Newbie


Joined: Dec 03, 2010
Posts: 1


#include <mega16.h>

// Declare your global variables here

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T State7=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func0=In Func1=In Func2=In Func3=Out Func4=In Func5=In Func6=In Func7=In
// State0=T State1=T State2=T State3=0 State4=T State5=T State6=T State7=T
PORTB=0x00;
DDRB=0x08;

// Port C initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T State7=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func0=In Func1=In Func2=In Func3=In Func4=In Func5=In Func6=In Func7=In
// State0=T State1=T State2=T State3=T State4=T State5=T State6=T State7=T
PORTD=0x00;
DDRD=0x00;
DDRD.5=1;
DDRD.7=1;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 1000.000 kHz
// Mode: CTC top=OCR0
// OC0 output: Toggle on compare match
TCCR0=0x1a;
TCNT0=0x00;
OCR0=0x0;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
TCCR1A=0x43;
TCCR1B=0x91;
TCNT1H=0x00;
TCNT1L=0x00;
OCR1AH=0x00;
OCR1AL=0xFF;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x19;
TCNT2=0x00;
OCR2=0x0F;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
GICR=0x00;
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
// Analog Comparator Output: Off
ACSR=0x80;
SFIOR=0x00;

while (1)
{
// Place your code here

};
}
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Jan 06, 2011 - 04:25 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

@narayanatammineni - And the point of your post?

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
triden
PostPosted: Jan 14, 2011 - 08:43 AM
Hangaround


Joined: Mar 27, 2006
Posts: 248
Location: Vancouver, BC

I am running a mega328p for PWM a fuel injector for a car. I need a PWM frequency of about 15hz, but the FPU is 8Mhz and the max prescaler (1024) won't bring it down enough. Are there any alternatives to getting the PWM frequency down to 15hz without lowering the FCPU?

Christan

_________________
-Christan
Chief Tinkerer
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Jan 14, 2011 - 11:06 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 21986
Location: Lund, Sweden

15 Hz PWM can easily be done by bit-banging it. Make a timer tick with a frequency that is the PWM frequency (15 Hz) times the resolution (in PWM steps). So for a resolution in 100 steps, yout make the timer tick with 1.5 KHz. In the ISR you simply maintain a counter variable that goes from from 0 to 100 and then wrap. Every time you wrap, you raise a pin. Every time you pass the desired duty cycle you lower the pin.

If your PWM frequency is actually 15 KHz then it's getting a wee bit tighter, and the resolution might have to be lowered. (But then again, you'd just go back to using a h/w timer...)

What resolution do you need?
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Koshchi
PostPosted: Jan 14, 2011 - 08:18 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

Is the 16 bit timer available? With that you can go down much farther than 15Hz.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
triden
PostPosted: Jan 15, 2011 - 09:02 AM
Hangaround


Joined: Mar 27, 2006
Posts: 248
Location: Vancouver, BC

I need a pulse width from 4.0 to about 60.0ms. 15hz is about 66ms max so that should work. It would be very beneficial to be able to vary the PW by 0.1 so thats a resolution of about 560 steps I guess. So this means I would make the timer tick at about 8.4khz? Seems like it should work...never tried pwm this slow before.

Koschi: the 16 bit timer is available. I am running an 8mhz cpu. The only thing is in PWM mode, top is not user settable

JohanEkdahl wrote:
15 Hz PWM can easily be done by bit-banging it. Make a timer tick with a frequency that is the PWM frequency (15 Hz) times the resolution (in PWM steps). So for a resolution in 100 steps, yout make the timer tick with 1.5 KHz. In the ISR you simply maintain a counter variable that goes from from 0 to 100 and then wrap. Every time you wrap, you raise a pin. Every time you pass the desired duty cycle you lower the pin.

If your PWM frequency is actually 15 KHz then it's getting a wee bit tighter, and the resolution might have to be lowered. (But then again, you'd just go back to using a h/w timer...)

What resolution do you need?
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Jan 15, 2011 - 05:50 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

Quote:
The only thing is in PWM mode, top is not user settable
Yes it is. Modes 8, 10 and 14 use ICR1 as TOP, Modes 9, 11 and 15 use OCR1A as TOP. And mode 6 has a fixed 511 as top which at 8MHz and a pre-scalar of 1024 gives you 15.2587890625Hz.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
heba_m.sharaf
PostPosted: Apr 27, 2011 - 01:09 AM
Newbie


Joined: Apr 27, 2011
Posts: 1


please, i want to control my brushless motor in airship(blimp)application but i don't know the most suitable type of timer to use either (timer with 8bit )or (timer with 16 bit)?.and if i decide to use timer 1 what is the most suitable mode for using in this application (mode 1 or 2 or 3 or 11 or 12)in case of the phase correct pwm
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Apr 27, 2011 - 09:09 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

Please don't ask general questions on the end of tutorials - take your question to the AVR Forum.

Moderator.

(BTW for BLDC motor control you are going to need three phased PWM signals - may be easiest to bit bang it in fact)

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
deepakgupta2186
PostPosted: Aug 19, 2011 - 01:04 PM
Newbie


Joined: Mar 07, 2011
Posts: 4


sir can u please provide me some information on phase & frequency control PWM of atmega 8535.my id is deepakgupta2186@gmail.com
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Aug 19, 2011 - 04:39 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15000
Location: Vancouver, BC

Exactly what information do you need? Is not the description of that mode in the datasheet clear?

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
angadaria
PostPosted: Sep 14, 2011 - 03:03 PM
Newbie


Joined: Sep 06, 2011
Posts: 1


hi dean...i must say you are the GOD for all of us beginner freaks..you really made the life easier for us...thanks a lot...please write more tutorials once you are done with the exam...wish you good luck...trying PWM on my own..let's see how it goes....thanks again....

thanks and regards
aks Very Happy Very Happy Very Happy
 
 View user's profile Send private message  
Reply with quote Back to top
justinjohney
PostPosted: Aug 09, 2012 - 08:21 AM
Hangaround


Joined: Jun 04, 2012
Posts: 327
Location: Mumbai,India

Code:
#define F_CPU 8192000UL

#include <avr/io.h>
#include <util/delay.h>

void timer1_init(void)
{
   //   Set PB3 (OC1A) as output pin;
   DDRB   |=   (1<<PB3);
   /*   Clear OC1A on Compare Match when upcounting.
      Set OC1A on Compare Match when downcounting.Enable PWM   */
   TCCR1A   |=   (1<<COM1A1);
   //   Select PWM, Phase and Frequency Correct, 10-bit mode, TOP value=ICR1, WGM(13-10)=1000,
   TCCR1B   |=   (1<WGM13);
   //   50% DUTYCYCLE
   OCR1A    =   512;//duty_cycle();DUTY_CYCLE=(TOP*VALUE)/1024
   ICR1    =   320;//for400hz(Fpwm=Ftimer/(2*TOP))here TOP= ICR1A
   /*   STARRT PWM BY :set prescaler 64 for that we need to write (CS12=0, CS11=1, CS10=1),
      fclk(timer)=F_CPU/64  */
   TCCR1B   |=   ((1<CS11)|(1<<CS10));

}

int main(void)
{
   timer1_init();
   while(1)
   {
   }
}

i'm trying to make a 400hz clock(50% dutycycle pwm)for switching H bridge?
i try the code in avr studio4,it compile without errors but while debugging it hangs.
attiny2313
is i need to change the code.
is it gives 400hz?
 
 View user's profile Send private message  
Reply with quote Back to top
sternst
PostPosted: Aug 09, 2012 - 08:59 AM
Raving lunatic


Joined: Jul 23, 2001
Posts: 2728
Location: Osnabrueck, Germany

1) Do not ask questions about your code in the tutorial forum.

2) Do not cross post.

Why haven't you posted your code in your own PWM thread?
Then you would have got already the answer that it is total nonsense to have a compare value that is bigger than TOP.

_________________
Stefan Ernst
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Aug 09, 2012 - 09:10 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71149
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

1) Do not ask questions about your code in the tutorial forum.

Exactly. Threads in tutorial are only for providing feedback for the article in the first post - not for general questions/problems. As such I'll lock this thread. If anyone has things to add about the PWM tutorial then PM one of clawson, plons, js, abcminiuser, EW and ask us to unlock the thread.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   This topic is locked: you cannot edit posts or make replies.
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits