How-To PWM
Description
The Pi-Tron CM4 has a PCA9685 PWM chip on board, its purpose however is only to control Kontron touch displays connected to the so called Family HDMI or Family DSI ports. It cannot be used to generate PWM signals on the DIOs of the Pi-Tron CM4.
The PWM chip allows the user to turn displays on and off, but also to control the backlight of the displays to adjust the brightness. The PWM chip is essentially used in two ways, one is to generate a PWM signal for the displays backlight, but also as a digital output to turn functions on or off, like a normal GPIO output would do.
Note on compatibility
The *Family HDMI* and *Family DSI (DSI1)* ports are only compatible with Kontron touch displays. Raspberry Pi displays can only be connected to the *DSI0* port.

Requirements
- 24 volts power supply with 2 pin power plug for the Pi-Tron CM4.
- Development computer with network access to the Pi-Tron CM4 or alternatively connect an HDMI monitor, mouse and keyboard.
- To login into the Pi-Tron CM4 via network, it is requires that the SSH server is running.
- The login details are by default: username: pi and password: raspberry
- Note: The latest version of the Raspberry Pi OS requires the user creating the initial SD card or writing the system to eMMC memory to choose a username and password or the information has to be entered during first boot of the system. The above mentioned defaults may not apply to your situation.
- An active Internet connection to install additional software.
- The PCA9685 PWM chip is connected to I2C bus 1 and has the address 0x40.
- A connected Kontron Family HDMI touchscreen display.
How-To
Preparation
Activate I2C
First make sure the I2C bus 1 is activated. Use the raspi-config program to enable the I2C interface, if this is not already the case. Afterwards reboot the Pi-Tron CM4.




Install the i2c-tools
Installing the i2c-tools allows the user to perform an I2C bus scan to see which addresses (devices) are available on the bus.
sudo apt update
sudo apt install i2c-tools
Reboot
Reboot the Pi to activate all the changes.
sudo reboot
Accessing the PCA9685 directly
The PCA9685 can be accessed in different ways, this section will use directly the I2C interface available in the Raspberry Pi OS to modify and activate up to 4 PWM channels of the PCA9685 chip. This will turn on a connected Family HDMI display as well as activate the backlight with 80% brightness. To talk to the PWM chip via I2C directly, the i2cset program from the i2c-tools package is used. The i2cset program allows to modify registers in the chip in a more straight forward manner, compared to the SysFS approach shown in the next section, but it requires a deeper knowledge about the registers and which data to write where and the exact sequence.
Checking I2C bus 1
- Log in into the Pi-Tron CM4 and run the i2cdetect program to see if the PCA9685 is present at address 0x40.
sudo i2cdetect -y 1
- The result should look something like the following table:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- 52 -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
- Once the presents of the PCA9685 is confirmed, the i2cset program can be used to configure the outputs and turn on the display.
Turning on the display
The following is an example sequence on how to turn on the display and set it's background light to 80% brightness.
# Mode 1 - ALLCALL (default) and activate SLEEP
/usr/sbin/i2cset -y 1 0x40 0 0x11
# Prescaler - 5 --> 1000Hz
/usr/sbin/i2cset -y 1 0x40 254 5
# LED0 - HDMI_TFT_EN
/usr/sbin/i2cset -y 1 0x40 6 0
/usr/sbin/i2cset -y 1 0x40 7 16
/usr/sbin/i2cset -y 1 0x40 8 0
/usr/sbin/i2cset -y 1 0x40 9 0
# LED1 - HDMI_TFT_RST
/usr/sbin/i2cset -y 1 0x40 10 0
/usr/sbin/i2cset -y 1 0x40 11 16
/usr/sbin/i2cset -y 1 0x40 12 0
/usr/sbin/i2cset -y 1 0x40 13 0
# LED2 - HDMI_TFT_PWM Backlight brightness to 80 Percent
/usr/sbin/i2cset -y 1 0x40 14 0
/usr/sbin/i2cset -y 1 0x40 15 0
/usr/sbin/i2cset -y 1 0x40 16 0x80
/usr/sbin/i2cset -y 1 0x40 17 0xc
# LED3 - HDMI_TOUCH_RST
/usr/sbin/i2cset -y 1 0x40 18 0
/usr/sbin/i2cset -y 1 0x40 19 16
/usr/sbin/i2cset -y 1 0x40 20 0
/usr/sbin/i2cset -y 1 0x40 21 0
# Mode 1 - deactivate SLEEP
/usr/sbin/i2cset -y 1 0x40 0 0x01
Of course there are other methods to do this, for example using Python or a C program. The commands from the listing above however can be simply run by hand or copied to a Linux shell program and run automatically every time the system boots.
Currently this method is the more preferred way of activating a connected display and turning on the background light. The SysFS approach in the next section is left in this documentation for now, but was found to have varying problems at different points in time.
Accessing the PCA9685 via SysFS
The PCA9685 can be accessed in different ways, this section will use the SysFS interface available in the Raspberry Pi OS to modify and activate up to 4 PWM channels of the PCA9685 chip. This will turn on a connected Family HDMI display as well as activate the backlight with 80% brightness.
The PWM controller is connected to I2C bus 1 on the Pi-Tron CM4 and has the address 0x40. Before trying to access the PWM channels, it's a good idea to first check that the PCA9685 PWM controller is really there.
Add the PCA9685 overlay to the config.txt file
To activate the PCA9685 driver within the Raspberry Pi OS, the corresponding overlay needs to be added to the config.txt file. For Raspberry Pi OS Buster and Bullseye use the following.
sudo nano /boot/config.txt
Starting with Raspberry Pi OS Bookworm, the config.txt file has moved:
sudo nano /boot/firmware/config.txt
At the end of the file add the following line.
dtoverlay=i2c-pwm-pca9685a
Save the changes and leave the editor with Ctrl + O → Enter → Ctrl + X.
Reboot
Reboot the Pi to activate the changes.
sudo reboot
Checking I2C bus 1
- Log in into the Pi-Tron CM4 and run the i2cdetect program to see if the PCA9685 is present at address 0x40. Note: Instead of seeing the number 40, there should be 2 U's, which means this address is in use by a driver, this is correct.
sudo i2cdetect -y 1
- The result should look something like the following table:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- 52 -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
- Once the presents of the PCA9685 is confirmed, the next step is to find out how it is named, meaning which device name and number it has received from the system. Usually the device name is something like pwmchipXY, e.g. pwmchip0.
Determine device name
- Use the command ls -la in the folder "/sys/class/pwm/" to list all PWM devices currently available.
pi@raspberrypi:~ $ ls -la /sys/class/pwm/
drwxr-xr-x 2 root root 0 May 09 14:18 .
drwxr-xr-x 69 root root 0 Mar 27 07:42 ..
lrwxrwxrwx 1 root root 0 May 09 14:43 pwmchip0 -> ../../devices/platform/soc/fe804000.i2c/i2c-1/1-0040/pwm/pwmchip0
- The PCA9685 was assigned the device name pwmchip0, as shown by the full system path of the device. This includes the parts i2c-1 which says this device is connected to I2C bus 1 and the part 1-0040, which means the devices address is 0x40 which is the PCA9685 PWM controller.
PCA9685 hardware overview
Several pins of the PCA9685 are in use. Below is a schematic drawing of the chip's connections and to which point they connect to and also a table showing signal names and their meaning on the Pi-Tron CM4.

| Signal | Pin | SysFS name | Signal description | Function |
|---|---|---|---|---|
| LED0 | 3 | pwm0 | HDMI_TFT_EN | |
| LED1 | 4 | pwm1 | HDMI_TFT_RST | |
| LED2 | 5 | pwm2 | HDMI_TFT_PWM | HDMI backlight |
| LED3 | 6 | pwm3 | HDMI_TOUCH_RST | |
| LED4 | 7 | pwm4 | DSI_TFT_EN | |
| LED5 | 8 | pwm5 | DSI_TFT_RST | |
| LED6 | 9 | pwm6 | DSI_TFT_PWM | DSI backlight |
| LED7 | 10 | pwm7 | DSI_TOUCH_RST | |
| LED8 | 12 | pwm8 | DSI_GPIO2 | |
| LED9 | 13 | pwm9 | DSI_GPIO3 | |
| LED10 | 14 | pwm10 | ||
| LED11 | 15 | pwm11 | ||
| LED12 | 16 | pwm12 | ||
| LED13 | 17 | pwm13 | ||
| LED14 | 18 | pwm14 | ||
| LED15 | 19 | pwm15 |
Controlling a family HDMI touch display
As stated in the introduction the PCA9685 PWM controller can be used to control connected Kontron family HDMI touch displays. The following steps show how to activate such a displays and turn on the backlight.
- Enable the HDMI TFT with PWM 0
echo 0 > /sys/class/pwm/pwmchip0/export
echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period
echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
- Release the HDMI TFT Reset with PWM 1
echo 1 > /sys/class/pwm/pwmchip0/export
echo 1000000 > /sys/class/pwm/pwmchip0/pwm1/period
echo 1000000 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
- Activate the backlight with PWM 2
echo 2 > /sys/class/pwm/pwmchip0/export
echo 1000000 > /sys/class/pwm/pwmchip0/pwm2/period
echo 800000 > /sys/class/pwm/pwmchip0/pwm2/duty_cycle
* Note: Changing the duty cycle raises or lowers the brightness of the backlight. Higher values mean brighter light and lower values mean less light.
- Release the HDMI TFT Touch Reset with PWM 3
echo 3 > /sys/class/pwm/pwmchip0/export
echo 1000000 > /sys/class/pwm/pwmchip0/pwm3/period
echo 1000000 > /sys/class/pwm/pwmchip0/pwm3/duty_cycle
The connected family HDMI display should now be active with the backlight turned on, any text or graphics should be visible on the screen. This concludes the How-To for the PCA9685 PWM controller.
Restrictions
- No known Restrictions
Related documentation
- PCA9685 16-channel I2C bus controller: https://www.nxp.com/docs/en/data-sheet/PCA9685.pdf
- Covering all aspects of the Raspberry Pi, the official documentation: https://www.raspberrypi.com/documentation
- Documentation for the raspi-config tool: https://www.raspberrypi.com/documentation/computers/configuration.html
- Linux I2C-Tools package: https://i2c.wiki.kernel.org/index.php/I2C_Tools
- Manpages i2c-tools: https://manpages.debian.org/bullseye/i2c-tools/index.html
- Linux PWM interface: https://www.kernel.org/doc/html/latest/driver-api/pwm.html
- Raspberry Pi OS now requires users to create their own login credentials on first boot: https://www.raspberrypi.com/news/raspberry-pi-bullseye-update-april-2022