目的:
C言語で PWMを使用した LED調光を行う。
環境/構成:
PWM は 2系統あり、それぞれ割り当てることができる GPIO は
- PWM Channel 0 : GPIO12、GPIO18
- PWM Channel 1 : GPIO13、GPIO19
である。
環境/構成は、C言語で LED ON/OFF と同様であるが、LED 接続回路 は 下図の通り
PWM に設定できる GPIO 4本にLED を接続。
PWM制御:
- wiringPiSetupGpio で wiringpi の初期設定を行う。
(Gpio でなくても良いが、ここでは Gpio番号を使用する前提とする。) - pinMode で PWM_OUTPUT を指定する。
- pwmSetMode で PWM のモード (バランス/マーク・スペース) を指定する。
- pwmSetClock で 1レンジ当たりのクロック数を設定する。
- pwmSetRange で 1周期のレンジ数 (分解能) を設定する。
- pwmWrite で パルス幅('H' のレンジ数) を設定する。
を行う。
pinMode の設定:
でpinMode を設定する。
これを実行すると、PWMが初期状態 (バランスモード) に戻ると思われる。
この為、PWMの設定(モード,クロック,レンジ)は pinMode を設定した後に行う必要がある。
PWM のモード
PWM のモードには バランスモード とマーク・スペースモードがある。
マーク・スペースモード
一定周期で パルスが発生し、パルス幅を変化させる。
pwmSetMode(PWM_MODE_MS)
バランスモード
デューティーが 50% に近づくほど 周期が短くなる。
pwmSetMode(PWM_MODE_BAL)
モードの設定は、channel 0,1 共通。
パルス周期、パルス幅の設定
パルス周期、パルス幅の設定は、pwmSetClock, pwmSetRange, pwmWrite で行う。
パランスモードの場合、デューティー 0 (100%) の場合の周期が設定値になる模様。
ベースのクロックは 19.2MHz。
pwmSetClock(clock)
1レンジ当たりのクロック数を設定する。
1レンジの長さは (1/19.2MHz)*クロック数 となる。
クロック数の設定は、channel 0,1 共通。
pwmSetRange(range)
1周期のレンジ数(PWM周期の分解能) を設定する。
PWMの周期は レンジ数 * クロック数 * (1/19.2MHz) となる。
PWMの周波数は 19.2MHz/(レンジ数 * クロック数) となる。
レンジ数の設定は、channel 0,1 共通。
pwmWrite(GPIO,width)
GPIO番号とパルス幅(レンジ数)を設定する。
パルス幅(時間)は パルス幅(レンジ数) * クロック数 * (1/19.2MHz) となる。
pwmSetClock(40)
pwmSetRange(256)
pwmWrite(12,128)
の場合、
周波数 : 19.2/(40*256) = 0.001875MHz
= 1.875KHz
デューティ 50%
プログラム例:
C言語での PWM を使用した LED の 調光 の例を示す。
引数として、GPIO番号とパルス幅(レンジ数) を指定する。
1レンジ当たりのクロック数は 40, 1周期のレンジ数 は 256 固定。
尚、GPIO番号のチェックは行っていない。
#include <stdio.h> #include <stdlib.h> #include <wiringPi.h> #define LED_PIN 12 int main (int argc, char *argv[]) { int pin_no = 0 ; int num = 0 ; if (argc == 1) { pin_no = LED_PIN ; num = 256 ; } else if (argc == 2) { pin_no = atoi(argv[1]) ; num = 256 ; } else { pin_no = atoi(argv[1]) ; num = atoi(argv[2]) ; } printf("pin_no : %d\n",pin_no) ; printf("num : %d\n",num) ; wiringPiSetupGpio() ; pinMode (pin_no, PWM_OUTPUT) ; pwmSetMode(PWM_MODE_MS) ; pwmSetClock(40) ; pwmSetRange(256) ; pwmWrite(pin_no , num) ; return 0 ; }
コンパイル 及び 実行:
コンパイルは、
gcc -o led_on led_on.c -lwiringPi
実行は、
sudo ./led_on 12 128
の様に行う。(GPIO番号 12 を デューティー 50% (パルス幅 128) で点灯)
実行すると、設定した GPIO番号に接続した LED が 点灯する。
尚、GPIO 12 と 18, 13 と 19 は 同じ PWM Channel の為、片方の LED の 明るさを変えると もう一方の LED の明るさも変わる。
例えば、
GPIO#12 を パルス幅 128 で 点灯した後、GPIO#18 を パルス幅 64 で点灯すると、GPIO#12 の LED も GPIO#18 と 同じ明るさに変わる。
本プログラムでは、実行毎に pinMode の設定から行っているため、既に点灯(調光)したGPIO があると、後から実行した時の pinMode 設定から PWM設定完了までの間、先に点灯した GPIO の設定が変わってしまう。(一瞬の為、見ていてもわからないが、、、)
通常は先に、使用するGPIOの設定を全て行ってから、pwmWrite で パルス幅の設定のみを行うべきかと思う。
sudo を付けない場合、
pinMode PWM: Unable to do this when using /dev/gpiomem. Try sudo?
の様なメッセージが表示され、実行できない。
/dev/gpiomem のパーミッション は、
crw-rw---- 1 root gpio 246, 0 12月 3 04:10 /dev/gpiomem
の様になっているが、gpio に所属しているユーザでも上のメッセージが表示された。
sudo 無しで実行できるようにしたいが、どうすれば良いか 不明。
0 件のコメント:
コメントを投稿