Difference between revisions of "PWM"
(→PWM Mode) |
|||
Line 57: | Line 57: | ||
</pre> | </pre> | ||
+ | ==== Bash test script ==== | ||
* A Bash test script is available given here : | * A Bash test script is available given here : | ||
<source lang="Bash"> | <source lang="Bash"> | ||
Line 96: | Line 97: | ||
exit 0 | exit 0 | ||
+ | </source> | ||
+ | |||
+ | ==== PWM with Java ==== | ||
+ | |||
+ | The code bellow shows how to directly use PWM from Java. | ||
+ | |||
+ | <source lang="Java"> | ||
+ | |||
+ | import java.io.*; | ||
+ | |||
+ | public class Imxpwm { | ||
+ | |||
+ | private FileReader activeReader; | ||
+ | |||
+ | private FileWriter activeWriter; | ||
+ | |||
+ | private FileReader frequencyReader; | ||
+ | |||
+ | private FileWriter frequencyWriter; | ||
+ | |||
+ | private FileReader periodReader; | ||
+ | |||
+ | private FileWriter periodWriter; | ||
+ | |||
+ | private FileReader dutyReader; | ||
+ | |||
+ | private FileWriter dutyWriter; | ||
+ | |||
+ | public boolean isActive() { | ||
+ | try { | ||
+ | int result = this.activeReader.read(); | ||
+ | if (result == 0) { | ||
+ | return true; | ||
+ | } else { | ||
+ | return false; | ||
+ | } | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public void setActive(boolean active) { | ||
+ | try { | ||
+ | if (active) { | ||
+ | this.activeWriter.write("1"); | ||
+ | this.activeWriter.flush(); | ||
+ | } else { | ||
+ | this.activeWriter.write("0"); | ||
+ | this.activeWriter.flush(); | ||
+ | } | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public double getDuty() { | ||
+ | try { | ||
+ | return this.dutyReader.read()/10.0; | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | return -1.0; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public void setDuty(double duty) { | ||
+ | try { | ||
+ | this.dutyWriter.write(Double.toString(duty * 10)); | ||
+ | this.dutyWriter.flush(); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public int getFrequency() { | ||
+ | try { | ||
+ | return this.frequencyReader.read(); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | return -1; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public void setFrequency(int frequency) { | ||
+ | try { | ||
+ | this.frequencyWriter.write(Integer.toString(frequency)); | ||
+ | this.frequencyWriter.flush(); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public int getPeriod() { | ||
+ | try { | ||
+ | return this.periodReader.read(); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | return -1; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | public void setPeriod(int period) { | ||
+ | try { | ||
+ | // en µs | ||
+ | this.periodWriter.write(Integer.toString(period)); | ||
+ | this.periodWriter.flush(); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * @param frequency | ||
+ | * @param duty | ||
+ | * @param period | ||
+ | * @param active | ||
+ | */ | ||
+ | public Imxpwm(int frequency, int duty, boolean active) { | ||
+ | |||
+ | try { | ||
+ | activeReader = new FileReader("/sys/class/pwm/pwm0/active"); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | try { | ||
+ | activeWriter = new FileWriter("/sys/class/pwm/pwm0/active"); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | try { | ||
+ | frequencyReader = new FileReader("/sys/class/pwm/pwm0/frequency"); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | try { | ||
+ | frequencyWriter = new FileWriter("/sys/class/pwm/pwm0/frequency"); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | try { | ||
+ | periodReader = new FileReader("/sys/class/pwm/pwm0/period"); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | try { | ||
+ | periodWriter = new FileWriter("/sys/class/pwm/pwm0/period"); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | try { | ||
+ | dutyReader = new FileReader("/sys/class/pwm/pwm0/duty"); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | try { | ||
+ | dutyWriter = new FileWriter("/sys/class/pwm/pwm0/duty"); | ||
+ | } catch (Exception e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | this.setActive(active); | ||
+ | this.setDuty(duty); | ||
+ | this.setFrequency(frequency); | ||
+ | } | ||
+ | |||
+ | public static void main(String[] args) throws Exception { | ||
+ | Imxpwm maPWM = new Imxpwm(50, 75, true); | ||
+ | double d = 0.0; | ||
+ | for (int j = 0; j < 100; j++) { | ||
+ | for (int i = 5; i <= 999; i++) { | ||
+ | d = i * 1.0 / 10.0; | ||
+ | maPWM.setDuty(d); | ||
+ | } | ||
+ | } | ||
+ | maPWM.setFrequency(500); | ||
+ | maPWM.setPeriod(50000); | ||
+ | } | ||
+ | |||
+ | } | ||
</source> | </source> | ||
Revision as of 19:43, 27 September 2009
On this page, you will find usefull informations to configure and use the Pulse Width Modulation (PWM) capabilities of your APF9328/APF27 boards.
The i.MX processor is capable of driving 2 PWM signals:
- one is linked to the LCD controller and allow to control the LCD backlight
- the other can be used to generate a PWM signal in several mode:
- audio playback
- real PWM
Contents
Hardware
i.MX PWM module is using PWMO (pin 2 of PortA on APF9328 and pin 5 of PortE on the APF27) as ouput.
- On APF9328DevLight this pin is accessible from TIMER zone under the board (See datasheets for more infos)
- On APF9328DevFull development boards this pin is connected to pin 4 (TIM2) of "Timers" connector (X21)
- On APF27Dev development boards this pin is connected to pin 4 of J22
Linux driver installation
i.MX PWM driver is installed by default in standard Armadeus rootfs.
Usage
- Load the module:
# modprobe imx-pwm Initializing PWM class. Initializing PWM#0...PWM major number = 251 PWM driver v0.7 done.
- If you plan to use sound, create /dev/pwm device file if not already existing (Major is dynamically allocated)
# DEV=`cat /proc/devices | grep imx-pwm | cut -d " " -f 1`; mknod /dev/pwm c $DEV 0
PWM Mode
Remark:
- The pwm has a resolution of 1uS
After driver loading, you have access to /sys/class/pwm/... functionnalities:
- to change frequency (for example 500 Hz):
# echo 500 > /sys/class/pwm/pwm0/frequency
- to change period (for example 100us):
# echo 100 > /sys/class/pwm/pwm0/period
- to change duty cycle (for example 50.0%)
# echo 500 > /sys/class/pwm/pwm0/duty
- to activate PWM:
# echo 1 > /sys/class/pwm/pwm0/active
- to de-activate PWM:
# echo 0 > /sys/class/pwm/pwm0/active
Bash test script
- A Bash test script is available given here :
#!/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
PWM with Java
The code bellow shows how to directly use PWM from Java.
import java.io.*;
public class Imxpwm {
private FileReader activeReader;
private FileWriter activeWriter;
private FileReader frequencyReader;
private FileWriter frequencyWriter;
private FileReader periodReader;
private FileWriter periodWriter;
private FileReader dutyReader;
private FileWriter dutyWriter;
public boolean isActive() {
try {
int result = this.activeReader.read();
if (result == 0) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
public void setActive(boolean active) {
try {
if (active) {
this.activeWriter.write("1");
this.activeWriter.flush();
} else {
this.activeWriter.write("0");
this.activeWriter.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public double getDuty() {
try {
return this.dutyReader.read()/10.0;
} catch (Exception e) {
e.printStackTrace();
return -1.0;
}
}
public void setDuty(double duty) {
try {
this.dutyWriter.write(Double.toString(duty * 10));
this.dutyWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public int getFrequency() {
try {
return this.frequencyReader.read();
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
public void setFrequency(int frequency) {
try {
this.frequencyWriter.write(Integer.toString(frequency));
this.frequencyWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
public int getPeriod() {
try {
return this.periodReader.read();
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
public void setPeriod(int period) {
try {
// en µs
this.periodWriter.write(Integer.toString(period));
this.periodWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param frequency
* @param duty
* @param period
* @param active
*/
public Imxpwm(int frequency, int duty, boolean active) {
try {
activeReader = new FileReader("/sys/class/pwm/pwm0/active");
} catch (Exception e) {
e.printStackTrace();
}
try {
activeWriter = new FileWriter("/sys/class/pwm/pwm0/active");
} catch (Exception e) {
e.printStackTrace();
}
try {
frequencyReader = new FileReader("/sys/class/pwm/pwm0/frequency");
} catch (Exception e) {
e.printStackTrace();
}
try {
frequencyWriter = new FileWriter("/sys/class/pwm/pwm0/frequency");
} catch (Exception e) {
e.printStackTrace();
}
try {
periodReader = new FileReader("/sys/class/pwm/pwm0/period");
} catch (Exception e) {
e.printStackTrace();
}
try {
periodWriter = new FileWriter("/sys/class/pwm/pwm0/period");
} catch (Exception e) {
e.printStackTrace();
}
try {
dutyReader = new FileReader("/sys/class/pwm/pwm0/duty");
} catch (Exception e) {
e.printStackTrace();
}
try {
dutyWriter = new FileWriter("/sys/class/pwm/pwm0/duty");
} catch (Exception e) {
e.printStackTrace();
}
this.setActive(active);
this.setDuty(duty);
this.setFrequency(frequency);
}
public static void main(String[] args) throws Exception {
Imxpwm maPWM = new Imxpwm(50, 75, true);
double d = 0.0;
for (int j = 0; j < 100; j++) {
for (int i = 5; i <= 999; i++) {
d = i * 1.0 / 10.0;
maPWM.setDuty(d);
}
}
maPWM.setFrequency(500);
maPWM.setPeriod(50000);
}
}
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 use less CPU ressources. To convert a sound to the right format we recommend to use SoX (on Linux). For exemple:
[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.