For many of my applications I’m using a PWM (Pulse Width Modulated) signal. One example is the motor driver used in this project where I use one PWM signal for each motor. Another usage of PWM is to control the brightness of an LED. Processor Expert makes usage of the PWM hardware easier. Still, for some settings it is good to have the resulting signals in mind. So in this post I’m showing how the settings impact the PWM signal generated.
I’m using Processor Expert with CodeWarrior for MCU10.3 and the FRDM-KL25Z board for this article. As the Processor Expert PWM component is pretty much the same for all architectures and IDE’s supported, things should applicable for any other microcontroller. With MCU10.3 there is now a PWM component which makes things easy for Kinetis too:
💡 the only difference is that for Kinetis (ARM Cortex) and ColdFire+ there is a LDD (Logical Device Driver) component involved. While it is still possible to use the LDD driver, it is not easy to use. I use the PWM instead of the TimerUnit_LDD.
The most important settings are:
- Period: this is defines the period or frequency of the signal.
- Starting pulse width: this defines the first duty.
- Initial polarity: this determines if the duty is low or high active (see below).
Below is where the settings in the component properties I use in this example:
To show things on a pin it I’m using the following code snippet:
Bit1_SetVal(); WAIT1_Waitms(1); /* 1 ms pulse on pin */ Bit1_ClrVal(); PWM1_Enable(); WAIT1_Waitms(20); PWM1_Disable(); Bit1_SetVal(); WAIT1_Waitms(1); /* 1 ms pulse on pin */ Bit1_ClrVal();
This generates a 1 ms pulse on pin, then enables the PWM for 20 ms. I generate that 1 ms pulse so I can easily set a trigger on it with a logic analyzer.
Let’s check what the component documentation says:
So I expect a PWM with 5 ms period: 1 ms low, then 4 ms high, and so on. Checking this with the logic analyzer confirms this:
The first thing to note is that the PWM remains high at the second Bit1 pulse. This because I have disabled the PWM, and it will stay in whatever state it was (high in my case).
💡 If the hardware supports it, then I can use the PWM SetValue() and ClearValue() methods to directly affect the PWM signal. This is useful if I want to disable the PWM, and have the output signal in a defined state. An even better way is to change the duty cycle in an interrupt generated by the PWM (see below).
The important thing to remember is that the initial polarity determines if the signal is ‘high’ or ‘low’ active in respect to the duty cycle.
💡 Unfortunately for the Kinetis it is not possible to change the initial polarity to ‘high’. This is possible for other microcontrollers like the S08 or ColdFire. To me, having a ‘low’ active PWM is somewhat counter-intuitive. Usually I think of “80% duty” in “the signal is 80% of the time active” while with ‘low’ polarity it is 80% low and 20% high.
To change the duty cycle, several methods available:
For example if I change it with
then I get a 10% low duty ratio for the above PWM:
Changing the duty ‘on the fly’ might have undesired effects. I recommend carefully to check what happens if the duty cycle is change inside the PWM period: depending how things are implemented in hardware and software, the new duty cycle might be effective immediately, or at the start of the next period. If the duty cycle changes within the PWM period, this might be a problem for the consumer of the signal.
PWM interrupts are very useful (if supported by the hardware), so I can change the duty at the right time, or do something else. In my example I want to toggle my pin. For this I enable interrupts for my PWM:
This enables the PWM OnEnd() event method:
In that event handler, I toggle my pin:
Now my pin toggles at the end of the PWM period every 5 ms:
It is important to know that the initial polarity setting determines if the ‘active’ duty cycle is high or low. Unfortunately at least for the Kinetis KL25Z only an initial low polarity is possible. If PWM interrupts are implemented by the hardware, then this is a good place to change the duty witout impacting the PWM frequency. In any case, a logic analyzer to verify the output signal is a must in my view for every firmware and embedded developer. 🙂
Happy PWMing 🙂