Python 版の WiringPi をインストールしたときに使った WiringPi-Python ディレクトリにサンプルプログラムがあるので、それを実行してみる。
次のディレクトリに移動し、make してから実行する。
これは、Python 版ではなく C のプログラムなので、その実行には root 権限が必要となる。
$ cd WiringPi-Python/WiringPi/examples
$ make pwm
$ sudo ./pwm
ソースを見ればわかるが、enter キーを押すことで、ひとつずつ LED を点灯し、次に enter キーを押すと今度は消していって、最後はすべての LED の明るさを変える。
12個の LED を software pwm により輝度制御を行うサンプルプログラミになっている。
Raspberry Pi はソフトウェアによる PWM 生成の他にハードウェアでも、1ch だけであるが PWM を生成できるようになっている。
ハードウェアによる PWM 生成の例は test2.c だが、「
PWM on Raspberry Pi」にもある。
ここに記載されている C のソースコードは、このままでは動かないので、修正したものを次に示す。
修正箇所は、ハードウェアによる生成は「pwmWrite(HARD_PWM_PIN, down);」で、ソフトウェアによる場合は「softPwmWrite(SOFT_PWM_PIN, down);」を使っている。
どちらも pwm のパルス幅を down という変数にしているが、この初期値が設定されていなかった。
変数 down の宣言部分で、このように「int down = kMaxVal;」初期値を設定している。
念のために、この down が0以下なら0、kMaxVal を超えていたら kMaxVal にする if 分も追加している。
//////---------------------------------------------------------------------------
////// Name: pwm_hard.c
////// Compiled with: gcc pwm_hard.c -I/usr/local/include -L/usr/local/lib -lwiringPi -lpthread -o pwm_hard
////// Schematic: .------.
////// | o o |
////// RPi | o o |12
////// | o o-|-----(->|)-----\/\/\/\--o GND
////// | o o |11 LED1 220
////// | o o-|-----(->|)-----\/\/\/\--o GND
////// | o o | LED2 220
////// | o o-|
//////
////// Notes:
//////---------------------------------------------------------------------------
#include
#include
#include
#include
#include
#define kMaxVal 99
void control_event(int sig);
int HARD_PWM_PIN = 1; //Hardware PWM Pin(GPIO18-12)
int SOFT_PWM_PIN = 0; //Software PWM Pin(GPIO0-11)
int DELAY_MS = 10;
int main(void)
{
(void)signal(SIGINT, control_event);
(void)signal (SIGQUIT, control_event);
printf("Hardware and software based PWM test on LED\n");
if (getuid() != 0) {
// wiringPi requires root privileges
printf("Error:wiringPi must be run as root.\n");
return 1;
}
if (wiringPiSetup() == -1) {
printf("Error:wiringPi setup failed.\n");
return 1;
}
pinMode(HARD_PWM_PIN, PWM_OUTPUT); // setup hardware pwm
softPwmCreate(SOFT_PWM_PIN, 0, 100); // setup software pwm pin
int up;
int down = kMaxVal;
while (1) {
for (up = 1; up = 5; down--) {
if (down < 0) {
down = kMaxVal;
}
if (down > kMaxVal) {
down = kMaxVal;
}
pwmWrite(HARD_PWM_PIN, down);
softPwmWrite(SOFT_PWM_PIN, down);
delay(DELAY_MS * 2);
}
delay(DELAY_MS * 5);
}
}
void control_event(int sig)
{
printf("\b\bExiting...\n");
pwmWrite(HARD_PWM_PIN, 0);
softPwmWrite(SOFT_PWM_PIN, 0);
delay(100); // wait a little for the pwm to finish write
exit(0);
}
これを実行するとわかるが、ハードウェアによる PWM 出力の LED がソフトウェアのそれと比べて暗い。
調べると、ハードウェアは0〜1023の値をとることができるが、ソフトウェアは0〜99となっている。
このプログラムでは、ソフトもハードも99までとしているので、ソフトは最大値までいっているが、ハードによる PWM は 1/10 程度の値にしかなっていない。
そのため、ハードウェアによる PWM 生成の LED は暗く見えている。
ソフトウェアによる PWM は「softPwmCreate(SOFT_PWM_PIN, 0, 100);」により初期化している。この中で初期値(最小値?)を0、レンジを100にしている。
レンジが100ということで、とりうる値は0〜99でしょう。100はとりえない。
なので、「softPwmCreate(SOFT_PWM_PIN, 0, 1024);」と、100を1024にしてしまうだけでいけちゃう? 周期が長くなってしまう?
Better PWM on the Raspberry Pi では、DMA を使った PWM 生成を考えている。
ここでは、DMA を使って、8ch で 2000 ステップの PWM 出力を CPU パワーをほとんど使わずに生成していると記述されている。サンプルコードは無いけれど。
ほかには・・・
RPIO.PWM: Precise PWM via DMA for servos and more (1µs res) ここも Python ラッパあり。
PWM via DMA for the Raspberry Pi Python で DMA PWM。
というわけで、RPIO のインストール。「python-setuptools」をインストール済みであれば1行目は不要。
$ sudo apt-get install python-setuptools
$ sudo easy_install -U RPIO
でも、これって python 動かすのに root 権限が必要?
easy_install ではなく、ソースからインストールする場合はこれ。
$ git clone https://github.com/metachris/RPIO.git
$ cd RPIO
$ sudo python setup.py install
そのあと、python インタプリタを立ち上げて・・・
$ sudo python
>>> from RPIO import PWM
>>> servo = PWM.Servo()
>>> servo.set_servo(18, 1200)
などと、する。ここで、18とあるのは GPIO の番号で、1200 とあるのはパルス幅uSec。
パルス幅は0から19990までの値をとることができる。10uSec 単位でパルス幅を決めることができる。
止めるときはこれ。
>>> servo.stop_servo(18)
ピン番号との対応表。右端の GPIO の番号で PWM のビットというかチャネルを決める。
set_servo(18, 10000) ならGPIO18で、bit 1、P1のピン12から出力されている。
bit
|
P1 pin
|
name
|
0
|
11
|
GPIO17
|
1
|
12
|
GPIO18
|
2
|
13
|
GPIO27
|
3
|
15
|
GPIO22
|
4
|
16
|
GPIO23
|
5
|
18
|
GPIO24
|
6
|
22
|
GPIO25
|
7
|
7
|
GPIO04
|
8
|
3
|
GPIO02
|
9
|
5
|
GPIO03
|
10
|
24
|
GPIO08
|
11
|
26
|
GPIO07
|
12
|
19
|
GPIO10
|
13
|
21
|
GPIO09
|
14
|
23
|
GPIO11
|
15
|
8
|
GPIO14
|
16
|
10
|
GPIO15
|
|
|
|
|
P5 pin
|
|
17
|
3
|
GPIO28
|
18
|
4
|
GPIO29
|
19
|
5
|
GPIO30
|
20
|
6
|
GPIO31
|