Difference between revisions of "PWM"

From ArmadeusWiki
Jump to: navigation, search
m (Configuration)
(Usage)
 
(46 intermediate revisions by 5 users not shown)
Line 1: Line 1:
On this page, you will find usefull informations to configure and use the Pulse Width Modulation (PWM) capabilities of your APF9328 board.
+
On this page, you will find usefull informations to configure and use the Pulse Width Modulation (PWM) capabilities of your APF boards.
  
Your board is capable of driving 2 PWM signals:
+
The i.MX processors are able to drive 2 types of PWM signals:
* one is linked to the LCD controller and allow to control the [[BackLight | LCD backlight]]
+
* one that is linked to the LCD controller and allows controlling the [[BackLight | LCD backlight]] (fixed frequency)
 
* the other can be used to generate a PWM signal in several mode:
 
* the other can be used to generate a PWM signal in several mode:
 
** audio playback
 
** audio playback
 
** real PWM
 
** real PWM
 +
 +
==Hardware==
 +
PWM pin detail for each APF boards can be found [[Hardware|here]] (under 'BaseBoards' section).
 +
On [[APF28Dev]] for example, PWM4 is on connector J10 at pin 26.
  
 
== Linux driver installation ==
 
== Linux driver installation ==
i.MXL PWM driver is now installed by default in standard Armadeus rootfs. Following instructions are only given as reference (to uninstall it at rootfs generation for example):
+
i.MX PWM driver is installed by default in standard Armadeus rootfs.
*Launch Linux configuration:
+
{{Note|On [[APF51Dev]], as PWM outputs/pins are multiplexed and used as user LED and button by default, you may have to define APF51DEV_USE_LED_AS_PWM or APF51DEV_USE_SWITCH_AS_PWM in Linux sources (''arch/arm/mach-mx5/apf51dev-baseboard.c''), rebuild and reflash the Linux kernel.}}
$ make linux26-menuconfig
+
And in '''Device Drivers  ---> Armadeus specific drivers'''  choose:<br>
+
[[Image:linux_config_pwm.png]]<br>
+
*Then rebuild your system:
+
$ make
+
  
== Installation ==
+
{{Note|On [[APF6Dev]], as PWM outputs is by default used for LCD's backlight control, you may have to modify APF6Dev device tree in Linux sources (''arch/arm/boot/dts/imx6qdl-apf6dev.dtsi''), rebuild and reflash the imx6q-apf6dev.dtb file.}}
Either copy generated module ''target/linux/modules/pwm/pwm.ko'' to your system with TFTP or NFS or reflash the generated rootfs. [[Linux_drivers_generalities|For more informations.]]
+
  
 
== Usage ==
 
== Usage ==
* Load the module:
+
* Load the driver ([[APF9328]], [[APF27]], [[APF51]]):
# insmod /lib/modules/2.6.23.1/extra/pwm/pwm.ko
+
<pre class="apf">
or (if you have reflashed your rootfs):
+
# modprobe imx-pwm
# modprobe pwm
+
i.MX PWM driver v0.81
* Create device file if not existing (Major is dynamically allocated)
+
imx-pwm imx-pwm.0: initialized
# DEV=`cat /proc/devices | grep imx-pwm | cut -d " " -f 1`; mknod /dev/pwm c $DEV 0
+
</pre>
 +
* On [[APF28]] with 2.6.35 kernel and on [[APF6]] & [[OPOS6UL]], the PWM driver is builtin so no need to load it before use.
 +
* For the one who plan to use sound, ''/dev/pwm0'' device file should be automatically created.
  
 
=== PWM Mode ===
 
=== PWM Mode ===
  
<strong>Remark:</strong>
+
{{Note|The PWM has a resolution of 1uS}}
* The pwm has a resolution of 1uS
+
  
 +
After driver loading, you have access to ''/sys/class/pwm/...'' functionalities:
  
Now you have access to /sys/class/pwm/ functionnalities:
+
{| border="1" cellpadding="10" cellspacing="0" summary="PWM usage depending on kernel version" class="wikitable"
 +
|- style="background:#efefef;" align="center"
 +
! 2.6 kernels || 3.x+ kernels
 +
|-----
 +
 
 +
|<pre class="apf">
 +
export PWM=pwm0    (on APF9328/APF27/APF51)
 +
export PWM=pwm4    (on APF28Dev)
 +
</pre>
 
* to change frequency (for example 500 Hz):
 
* to change frequency (for example 500 Hz):
  # echo 500 > /sys/class/pwm/pwm0/frequency
+
<pre class="apf">
* to change period (for example 100us):
+
  # echo 500 > /sys/class/pwm/$PWM/frequency
  # echo 100 > /sys/class/pwm/pwm0/period
+
</pre>
 +
* if you prefer working with periods (for example 100us):
 +
<pre class="apf">
 +
  # echo 100 > /sys/class/pwm/$PWM/period
 +
</pre>
 
* to change duty cycle (for example 50.0%)
 
* to change duty cycle (for example 50.0%)
  # echo 500 > /sys/class/pwm/pwm0/duty
+
<pre class="apf">
 +
  # echo 500 > /sys/class/pwm/$PWM/duty
 +
</pre>
 
* to activate PWM:
 
* to activate PWM:
  # echo 1 > /sys/class/pwm/pwm0/active
+
<pre class="apf">
 +
  # echo 1 > /sys/class/pwm/$PWM/active
 +
</pre>
 
* to de-activate PWM:
 
* to de-activate PWM:
  # echo 0 > /sys/class/pwm/pwm0/active
+
<pre class="apf">
 +
  # echo 0 > /sys/class/pwm/$PWM/active
 +
</pre>
 +
 
 +
||<pre class="apf">
 +
export PWM_CHIP=pwmchip2    (on APF6Dev)
 +
export PWM_CHIP=pwmchip0    (on APF9328Dev/APF27Dev/APF51Dev/APF28Dev/OPOS6UL)
 +
 
 +
export PWM=0    (on APF9328Dev/APF27Dev/APF51Dev/APF6Dev/OPOS6UL)
 +
export PWM=4    (on APF28Dev)
 +
</pre>
 +
* declare the PWM we will use:
 +
<pre class="apf">
 +
# echo ${PWM} > /sys/class/pwm/${PWM_CHIP}/export
 +
</pre>
 +
* to have a 100uS period:
 +
<pre class="apf">
 +
# echo 100000 > /sys/class/pwm/${PWM_CHIP}/pwm${PWM}/period
 +
</pre>
 +
* to change duty cycle (for example 50% = 50us of 100us period)
 +
<pre class="apf">
 +
# echo 50000 > /sys/class/pwm/${PWM_CHIP}/pwm${PWM}/duty_cycle
 +
</pre>
 +
* to activate PWM:
 +
<pre class="apf">
 +
# echo 1 > /sys/class/pwm/${PWM_CHIP}/pwm${PWM}/enable
 +
</pre>
 +
* to de-activate PWM:
 +
<pre class="apf">
 +
# echo 0 > /sys/class/pwm/${PWM_CHIP}/pwm${PWM}/enable
 +
</pre>
 +
 
 +
|}
 +
 
 +
==== Bash test script (2.6 kernels) ====
 +
* A Bash test script is available given below. Just enter the desired frequency and duty cycle.
 +
<source lang="Bash">
 +
#!/bin/sh
 +
#
 +
# script to command imx pwm
 +
# usage : pwm_imx frequency duty
 +
#
 +
 
 +
if [ $# -lt 2 ]
 +
then
 +
echo "Provide two arguments to this script !"
 +
echo "pwm_imx frequency dutycycle"
 +
exit 1
 +
fi
 +
 
 +
SYS_DIR="/sys/class/pwm/pwm0/"
 +
FREQUENCY=$1
 +
DUTY=$2
 +
 
 +
DUTY=`(echo $DUTY | awk '{ print $1*10}')`
 +
 
 +
if [ ! -d "$SYS_DIR" ]; then
 +
echo "Can't find /sys/ interface for PWM"
 +
exit 1
 +
fi
 +
 
 +
echo "Starting PWM"
 +
echo 1 > $SYS_DIR/active
 +
 
 +
#SET FREQUENCY
 +
echo $FREQUENCY > $SYS_DIR/frequency
 +
echo "Setting PWM to $FREQUENCY Hz"
 +
 
 +
#SET DUTY CYCLE
 +
echo $DUTY > $SYS_DIR/duty
 +
echo "Setting DUTY to $2 %"
 +
 
 +
exit 0
 +
 
 +
</source>
 +
 
 +
* Other test script may be found in ''target/test/test_pwm.sh'' of your armadeus BSP
  
 
=== Audio Mode ===
 
=== Audio Mode ===
Audio playback mode is working since v0.5 of PWM driver (thanks to [[User:SebastienR]]).
+
Audio playback mode is working since v0.5 of PWM driver (thanks to [[User:SebastienR|SebastienR]]).
You can play 8, 16 & 32 KHz 8bit linear RAW sound. It's recommended to play 8kHz one, as they use less CPU ressources.
+
You can play 8, 16 & 32 KHz 8bit linear RAW sound. It's recommended to play 8kHz one, as they are using less CPU resources.
 
To convert a sound to the right format we recommend to use SoX (on Linux).
 
To convert a sound to the right format we recommend to use SoX (on Linux).
For exemple:
+
For example:
 
  [host]$ sox /usr/share/sounds/KDE_Chimes_1.ogg -r 8192 -b -u -c 1 Chimes.raw
 
  [host]$ sox /usr/share/sounds/KDE_Chimes_1.ogg -r 8192 -b -u -c 1 Chimes.raw
 
  -r -> sampling rate
 
  -r -> sampling rate
Line 56: Line 148:
 
  -c 1 -> Mono / 1 channel
 
  -c 1 -> Mono / 1 channel
  
Then you can test it using target/linux/modules/pwm/test/testplaymode:
+
Then you can test it using ''target/linux/modules/pwm/test/testplaymode'', which can be compiled that way:
[host:/.../armadeus]$ make -C target/linux/modules/pwm/test/
+
<pre class="host">
  [host:/.../armadeus]$ cp target/linux/modules/pwm/test/testplaymode $NFS_DIR
+
$ make shell_env
[host:/.../armadeus]$ cp target/linux/modules/pwm/test/KDE_Startup_2.raw $NFS_DIR
+
$ . armadeus_env.sh
 +
$ export PATH=$PATH:$ARMADEUS_TOOLCHAIN_PATH
 +
$ make -C target/linux/modules/pwm/test/
 +
  $ cp target/linux/modules/pwm/test/testplaymode /tftpboot/
 +
$ cp target/linux/modules/pwm/test/KDE_Startup_2.raw /tftpboot/
 +
</pre>
 
on target do:
 
on target do:
 +
<pre class="apf">
 
  # testplaymode
 
  # testplaymode
 +
</pre>
 
or
 
or
 +
<pre class="apf">
 
  # testplaymode KDE_Startup_2.raw
 
  # testplaymode KDE_Startup_2.raw
 +
</pre>
 +
 +
==Going further==
 +
If you need more than one PWM at a time, you can use the APF's FPGA with [[MotionSystem|the following project]].
  
 
== Links ==
 
== Links ==

Latest revision as of 13:30, 10 February 2022

On this page, you will find usefull informations to configure and use the Pulse Width Modulation (PWM) capabilities of your APF boards.

The i.MX processors are able to drive 2 types of PWM signals:

  • one that is linked to the LCD controller and allows controlling the LCD backlight (fixed frequency)
  • the other can be used to generate a PWM signal in several mode:
    • audio playback
    • real PWM

Hardware

PWM pin detail for each APF boards can be found here (under 'BaseBoards' section). On APF28Dev for example, PWM4 is on connector J10 at pin 26.

Linux driver installation

i.MX PWM driver is installed by default in standard Armadeus rootfs.

Note Note: On APF51Dev, as PWM outputs/pins are multiplexed and used as user LED and button by default, you may have to define APF51DEV_USE_LED_AS_PWM or APF51DEV_USE_SWITCH_AS_PWM in Linux sources (arch/arm/mach-mx5/apf51dev-baseboard.c), rebuild and reflash the Linux kernel.


Note Note: On APF6Dev, as PWM outputs is by default used for LCD's backlight control, you may have to modify APF6Dev device tree in Linux sources (arch/arm/boot/dts/imx6qdl-apf6dev.dtsi), rebuild and reflash the imx6q-apf6dev.dtb file.


Usage

# modprobe imx-pwm
i.MX PWM driver v0.81
imx-pwm imx-pwm.0: initialized
  • On APF28 with 2.6.35 kernel and on APF6 & OPOS6UL, the PWM driver is builtin so no need to load it before use.
  • For the one who plan to use sound, /dev/pwm0 device file should be automatically created.

PWM Mode

Note Note: The PWM has a resolution of 1uS


After driver loading, you have access to /sys/class/pwm/... functionalities:

2.6 kernels 3.x+ kernels
export PWM=pwm0    (on APF9328/APF27/APF51)
export PWM=pwm4    (on APF28Dev)
  • to change frequency (for example 500 Hz):
 # echo 500 > /sys/class/pwm/$PWM/frequency
  • if you prefer working with periods (for example 100us):
 # echo 100 > /sys/class/pwm/$PWM/period
  • to change duty cycle (for example 50.0%)
 # echo 500 > /sys/class/pwm/$PWM/duty
  • to activate PWM:
 # echo 1 > /sys/class/pwm/$PWM/active
  • to de-activate PWM:
 # echo 0 > /sys/class/pwm/$PWM/active
export PWM_CHIP=pwmchip2    (on APF6Dev)
export PWM_CHIP=pwmchip0    (on APF9328Dev/APF27Dev/APF51Dev/APF28Dev/OPOS6UL)

export PWM=0    (on APF9328Dev/APF27Dev/APF51Dev/APF6Dev/OPOS6UL)
export PWM=4    (on APF28Dev)
  • declare the PWM we will use:
 # echo ${PWM} > /sys/class/pwm/${PWM_CHIP}/export
  • to have a 100uS period:
 # echo 100000 > /sys/class/pwm/${PWM_CHIP}/pwm${PWM}/period
  • to change duty cycle (for example 50% = 50us of 100us period)
 # echo 50000 > /sys/class/pwm/${PWM_CHIP}/pwm${PWM}/duty_cycle
  • to activate PWM:
 # echo 1 > /sys/class/pwm/${PWM_CHIP}/pwm${PWM}/enable
  • to de-activate PWM:
 # echo 0 > /sys/class/pwm/${PWM_CHIP}/pwm${PWM}/enable

Bash test script (2.6 kernels)

  • A Bash test script is available given below. Just enter the desired frequency and duty cycle.
#!/bin/sh
#
# script to command imx pwm 
# usage : pwm_imx frequency duty 
#

if [ $# -lt 2 ] 
then
echo "Provide two arguments to this script !"
echo "pwm_imx frequency dutycycle"
exit 1
fi

SYS_DIR="/sys/class/pwm/pwm0/"
FREQUENCY=$1
DUTY=$2

DUTY=`(echo $DUTY | awk '{ print $1*10}')`

if [ ! -d "$SYS_DIR" ]; then
echo "Can't find /sys/ interface for PWM"
exit 1
fi

echo "Starting PWM"
echo 1 > $SYS_DIR/active

#SET FREQUENCY
echo $FREQUENCY > $SYS_DIR/frequency
echo "Setting PWM to $FREQUENCY Hz"

#SET DUTY CYCLE
echo $DUTY > $SYS_DIR/duty
echo "Setting DUTY to $2 %"

exit 0
  • Other test script may be found in target/test/test_pwm.sh of your armadeus BSP

Audio Mode

Audio playback mode is working since v0.5 of PWM driver (thanks to SebastienR). You can play 8, 16 & 32 KHz 8bit linear RAW sound. It's recommended to play 8kHz one, as they are using less CPU resources. To convert a sound to the right format we recommend to use SoX (on Linux). For example:

[host]$ sox /usr/share/sounds/KDE_Chimes_1.ogg -r 8192 -b -u -c 1 Chimes.raw
-r -> sampling rate
-b -> byte/8bit signal
-u -> linear /not compressed
-c 1 -> Mono / 1 channel

Then you can test it using target/linux/modules/pwm/test/testplaymode, which can be compiled that way:

 $ make shell_env
 $ . armadeus_env.sh
 $ export PATH=$PATH:$ARMADEUS_TOOLCHAIN_PATH
 $ make -C target/linux/modules/pwm/test/
 $ cp target/linux/modules/pwm/test/testplaymode /tftpboot/
 $ cp target/linux/modules/pwm/test/KDE_Startup_2.raw /tftpboot/

on target do:

 # testplaymode

or

 # testplaymode KDE_Startup_2.raw

Going further

If you need more than one PWM at a time, you can use the APF's FPGA with the following project.

Links