Theory of operations
A PWM signal is a digital signal with fixed frequency but varying duty cycle.
If the duty cycle of the PWM signal is varied with time, and the PWM signal is filtered, the output of the filter will be an analog signal.
There are mostly 3 ways to generate a PWM signal using a MSP430 :
- loop
- timer
- interrupt
Loop
The easiest way to generate a PWM signal is to create an infinite loop and inside the loop, set a I/O pin ON or OFF, using a counter to determine when to change the ON vs. OFF time, comparing it to a "dutycycle" value. Also in the loop must be present a delay to determine the frequency of the signal.
The pro is obvious, is really easy to generate a PWM signal in this way.
But there are big cons with this method.
Let see some of them:
Two MSP430 subsystems are involved in generating a PWM signal with the timer, the clock subsystem and the timer subsystem.
The output pin of the PWM signal, is directly connected to the timer.
Once programmed the timer, the generation of the PWM signal doesn't require any additional software.
In this way, a timer is still involved, but instead to generate the PWM signal, it generate interrupts.
Any time the interrupt is fired, a piece of software provide to change the state of an I/O pin depending some counter values compared with a threshold, generating in this way the PWM signal.
The frequency of the signal is determined by the timer setting and the precision is depending by the number of "steps" of the counter.
For example, if we want a 100 Hz signal, we need to set up an interrupt timing "at least" set to fire every 1/(100 Hz * 2) i.e. 0.005 seconds.
It means that every 0.005 seconds we have an interrupt and change the state of the output, obtaining a square wave of 100 Hz.
But we want to control the duty cycle, and so we need to have a smaller interrupt time.
Let say we want to divide our 100 Hz in 10 "steps", so we need to set the timer to fire every 1/(100 Hz/10) = 0.001 seconds or 1 ms.
Every ms we have an interrupt and then we decide if having the output ON or OFF.
Our period is so divided in 10 1 ms steps, i.e. 0.001 * 10 = 0.1 sec. that converted is 100 Hz.
But only 10 steps is not good, so better to split the time more, at least 50 or 100.
Of course we have some limits depending the input clock and how long the interrupt function requires to operate.
So we have to play with the clock in order to have the micro go faster and really optimize the interrupt function.
The interrupt function must be executed in a time much shorter than 1 ms, and we need to decide if the output is high or low depending a counter value in that timeframe.
Here a flow chart to better explain the basics.
On the left a flow of the main code.
It simply initialize the system and enter in an infinite loop. Eventually is possible to have code to perform settings/change of the parameters in the loop.
On the right the flow of the timer interrupt.
Every time the interrupt is fired, it uses a counter compared with a threshold to determine if turn the signal ON or OFF and then update the counter restarting the timer.
To measure exactly how long on average the function last, a debug signal is used.
The code turn this debug signal ON just after started the interrupt and OFF just before to exit.
With an oscilloscope is then possible to measure how long the signal remain ON. That more or less would be the time used by the interrupt function.
Here a couple of pictures from my oscilloscope during some tests.
The pro is obvious, is really easy to generate a PWM signal in this way.
But there are big cons with this method.
Let see some of them:
- all the resources of the processor are devoted to generate the signal
- is extremely difficult to calculate a specific timing
- any extra operation added in the loop go to alter the frequency of the generated signal
- if interrupts are used the result signal is extremely instable
So the loop is not really something to consider for real use.
Timer
The second way to generate a PWM signal is to use a timer.
The MSP430 timer is capable to generate a PWM signal, it means that is possible to program a MSP430 timer specifically for the purpose to generate a PWM signal.
Because the signal in the end is generated by a piece of hardware, the result is extremely stable and precise.
Pro:
- very stable PWM signal
- extremely precise timing is possible
Cons:
- the timer is devoted only to the PWM signal generation since the I/O pin is connected to it
- only 1 PWM signal per timer is available
- setting up the timer can be complicated
Interrupt
The third alternative is to soft-generate the PWM, like in the loop solution, but using a timer interrupt instead a deal loop.
A generic timer interrupt is generated and every time the interrupt is fired, a function handle one or more I/O pins to generate the PWM signal.
Pro:
- stable PWM signal
- precise timing (but less than the full timer solution)
- possibility to have more than one PWM signals
- possibility to use the timer resource for other purposes
- easy to calculate the time
Cons:
- limited timing range
PWM generated by a timer
The output pin of the PWM signal, is directly connected to the timer.
Once programmed the timer, the generation of the PWM signal doesn't require any additional software.
Clock
The timer needs to be "fed" with a clock and there are different choices, depending the time required and the precision needed.PWM using a generic time interrupt
In this way, a timer is still involved, but instead to generate the PWM signal, it generate interrupts.
Any time the interrupt is fired, a piece of software provide to change the state of an I/O pin depending some counter values compared with a threshold, generating in this way the PWM signal.
The frequency of the signal is determined by the timer setting and the precision is depending by the number of "steps" of the counter.
For example, if we want a 100 Hz signal, we need to set up an interrupt timing "at least" set to fire every 1/(100 Hz * 2) i.e. 0.005 seconds.
It means that every 0.005 seconds we have an interrupt and change the state of the output, obtaining a square wave of 100 Hz.
But we want to control the duty cycle, and so we need to have a smaller interrupt time.
Let say we want to divide our 100 Hz in 10 "steps", so we need to set the timer to fire every 1/(100 Hz/10) = 0.001 seconds or 1 ms.
Every ms we have an interrupt and then we decide if having the output ON or OFF.
Our period is so divided in 10 1 ms steps, i.e. 0.001 * 10 = 0.1 sec. that converted is 100 Hz.
But only 10 steps is not good, so better to split the time more, at least 50 or 100.
Of course we have some limits depending the input clock and how long the interrupt function requires to operate.
So we have to play with the clock in order to have the micro go faster and really optimize the interrupt function.
Here a flow chart to better explain the basics.
On the left a flow of the main code.
It simply initialize the system and enter in an infinite loop. Eventually is possible to have code to perform settings/change of the parameters in the loop.
On the right the flow of the timer interrupt.
Every time the interrupt is fired, it uses a counter compared with a threshold to determine if turn the signal ON or OFF and then update the counter restarting the timer.
To measure exactly how long on average the function last, a debug signal is used.
The code turn this debug signal ON just after started the interrupt and OFF just before to exit.
With an oscilloscope is then possible to measure how long the signal remain ON. That more or less would be the time used by the interrupt function.
Here a couple of pictures from my oscilloscope during some tests.
Debug signal in the timer interrupt - DCO set for 16 Mhz selection. The irregular wave indicates different execution timing, approx 3.5 us average execution time |
PWM signal generated, 10 steps, approx 10Khz frequency - DCO set for 16 Mhz selection |
I like the idea of using a timer to fire off the interrupt routine, but wonder if this method might compromise performance of the pwm output on the same basis as you mentioned earlier. A pure hardware-driven pwm appears to be available in the MSP430F series. Perhaps in this example you did not have that option?
ReplyDeleteIt really depends about what you have and your needs. Yes, you can generate a PWM using the Timer, but if you have only 1 timer and you need more PWM signals, or you need to use the timer for also something else, then the interrupt drive solution can be handy.
ReplyDeleteAnd yes, the "ideal" PWM generator is hardware, i.e. using the Timer. The interrupt driven solution can have issues if you need to have multiple PWM generators and other timer operations.
Often is matter to compromise in order to better use the resources you have.
In some latest projects I choose to use a PWM generated by the timer, but I'm using chips with more than 1 timer.