If you're aiming to manage the brightness of an LED or the speed of a motor in your embedded system project, having PWM in your toolkit is invaluable. Pulse Width Modulation, or PWM, is a technique that involves encoding a message into a pulsing signal characterized by a variable duty cycle. In simpler terms, it enables you to regulate the average voltage output of a pin by swiftly toggling it on and off. Don't be intimidated by terms like "pulse width modulation" or "duty cycle" they might sound complex, but by the end of this Protip, you'll be well-versed in harnessing the power of this tool for your maker projects.
PWM vs GPIOIn a previous protip "Using GPIO Ports with Micropython on the PSoC6", we discussed what are GPIO pins and how they can only handle binary signals of HIGH and LOW. However, for more complex signal requirements, a Pulse Width Modulation (PWM) signal can be used to achieve a custom voltage signal. In this technique, the microcontroller generates bursts of square wave signals with different widths, which when averaged per unit time, can generate any voltage between the microcontroller's VDD and ground.
While PWM is a powerful and versatile technique, it requires special hardware and is not usually available on all microcontroller pins. Therefore, it is important to carefully consider your pin connections whenever you intend to use PWM in your project setup.
Note: On the PSoC6, all GPIO pins are PWM-capable. The frequency can range from 1Hz to 100MHz.
One of the most important parameters in PWM is the "duty cycle". The duty cycle indicates the percentage of time that the PWM signal is in the "HIGH" state (the time when the signal is generating a voltage) compared to the total period of the signal. For example, a 50% duty cycle means that the signal is "HIGH" for half the time and "LOW" for the other half.
The duty cycle is directly proportional to the voltage generated by the PWM signal. For example, if we have a PWM signal with a duty cycle of 25%, the voltage generated will be equal to 25% of the maximum voltage possible. Similarly, if we have a duty cycle of 75%, the voltage generated will be equal to 75% of the maximum voltage possible.
It's important to note that the frequency of the PWM signal also plays a role in determining the voltage generated. Generally, a higher frequency will result in a smoother voltage output. However, increasing the frequency will also increase the number of computations required by the microcontroller.
Setting up the PSOC6 board for MicropythonBefore using the GPIO Ports, it is necessary to make sure that Micropython is installed on your PSoC6 board. Follow the instructions provided in the "Micropython on PSoC6" Protip. This comprehensive guide will walk you through installing Micropython on the PSoC6 and demonstrate how to operate its onboard LED.
Code1. Import the machine module:
import machine
The machine module is a core component of MicroPython that provides functionalities to interact directly with the hardware components of a microcontroller. By leveraging the functionalities offered by this module, developers can gain direct control over the I/O pins, pulse width modulation (PWM), I2C, SPI, UART communication peripherals, and more.
Alternatively, you could just import the Pin module, which is the core module for PWM control using:
from machine import PWM
Step 2: Create the PWM Object by using the PWM constructor, which takes the following arguments:
- Pin Number: The pin number on which the PWM signal will be generated.
- Frequency: The frequency of the PWM signal in Hz.
- Duty Cycle: The duty cycle of the PWM signal. The range is from 0 to 65535. In this example, we'll be using a duty cycle of about 12.5% so the duty cycle vale is 8192.
- Invert: A Boolean value that determines whether the PWM signal is inverted. In this example, we'll be setting "invert" to 0.
Here's what the PWM object creation looks like:
pwm = PWM('P9_0', freq=50, duty_u16=8192, invert=0)
After successful creation, PWM will already be up and running. If you want to change the signal you could use the init() method to reinitialize the PWM object with different settings settings.
The init method takes the following arguments:
- Frequency: The frequency of the PWM signal in Hz. In the following example code, we change the previous frequency of 50Hz to 90Hz
- Duty Cycle: The duty cycle of the PWM signal. The range is from 0 to 65535. In this example, we'll be using a duty cycle of about 100%.
- Whether the signal is to be inverted or not
pwm.init(freq=90,duty_us=65535,invert=1) # Modify the settings of PWM object
You could also use the duty_u16() and freq() methods to respectively obtain/edit the duty cycle or frequency.
For example, to obtain the frequency and duty cycle values, you would run:
pwm.freq()
pwm.duty_u16()
A function providing the current system frequency or duty cycle becomes valuable when frequent adjustments to these parameters are necessary. This is particularly beneficial when other processes rely on the system's ongoing frequency or duty cycle, ensuring synchronization and coherence amid dynamic changes.
If you would want to change the frequency and duty cycle you could run:
pwm.freq(120)
pwm.duty_u16(10000)
To stop the pin from generating PWM signals, all you'll have to do is deinitialize your object by:
pwm.deinit()
Thanks for tuning in! If you want to learn more about using the PSoC6 with Micropython or see some cool maker projects, feel free to check out our Hackster channel @ https://www.hackster.io/Infineon_Team.
Comments