LEDの明るさを変化させてみる(PWMを使う)(Arduino)
前回まで、
digitalWrite(13, HIGH);
digitalWrite(13, LOW)
で、13番ピンに、5Vを出力、出力を停止を指示していました。
この場合、停止指示をするまでは、5Vを継続的に出力しています。
これに対し、PWDでは、1秒間を何周期(490Hz,980Hz)かに分け、
その1周期毎に、HIGHの時間とLOWの時間を作り
その割合を利用して、平均的な電圧を作り出すというものです。
※ PWMの周波数は基本490Hzですが、UNOの5番,6番ピンは980Hzです。
今回のPWDが利用出来るデジタルピンは、
UNOの場合、0番から13番のうち、
3番,5番,6番,9番,10番,11番ピンがパルス波形を出力可能です。
Arduino本体のピン番号のところに、
“~”のようなマークが付けられていると思います。
このPWDの出力関数は、
analogWrite( )関数です。
書式は、
analogWrite( ピン番号、 デューティ比)
です。
デューティ比とは、1周期内でのONとOFFのを、
0~255の数値で表したものです。
0:周期のすべてで出力しない(平均電圧は0V)
127:周期の半分の間、出力する(平均電圧は2.5V)
255:周期の全てで出力する(平均電圧か5.0V)
という具合です。
では、デジタルピン6番を使って、
LEDの明るさを変化させるプログラムをしてみます。
ブレッドボードとArduinoの配線を行います。
※ArduinoのUSBケーブルは抜いておきましょう。
回路図のように配線します。
この回路図の作図には fritzing を利用させて頂いております。
https://fritzing.org/home/
ArduinoIDEでスケッチしてみます。
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
// 変数宣言
int i = 0;
// 徐々に点灯
for ( i = 0; i <= 255; i+=2 ) {
analogWrite( 6, i );
delay(50);
}
// 徐々に消灯
for ( i = 255; i >= 0; i-=2 ) {
analogWrite( 6, i );
delay(50);
}
delay(1000);
}
このとき、 setup( )関数に、
デジタルピン6番の出力設定などの記述は必要ありません。
配線の確認を済ませたら、
USBケーブルを接続し、Arduinoに書き込みます。
徐々に明るさが変化しましたか。
このプログラムでは、
analogWrite( 6, i );
の整数型変数iの値を0~255の間で変化させることで、
電圧を変化させ、LEDの明るさを変えています。
また、変数iの値を2ずつ変化させていますが、
特に意味はありません。
もちろん、1ずつで構いません。
続いて、
アナログピンを使って、電圧を測定してみます。
アナログピンは、入力されてくる電圧を、
0~1023の数値に変換して表されます。
0:0V
511:2.5V
1023:5V
といった具合です。
アナログピンを使用する場合、
void setup()関数で、ピンのモード設定が必要です。
今回は、アナログ0番ピンを使用しますので、
pinMode( A0, INPUT ); // アナログ0番ピンを入力用に割り当て
と設定します。
アナログピンに入力されてくる値を読み込むには、
analogRead( ) 関数を使用します。
書式は、
analogRead( ピン番号 )
となり、読み込まれた数値は、
この関数自身が保持していますので、
int val = analogRead( A0 );
などと使用し、変数に代入して利用します。
この例の場合、analogRead( A0 )が持っている数値を、
代入演算子(=)を使って、整数型変数valに代入しています。
では、2カ所電圧を測定します。
図のように、配線します。
これは、以前にLED点灯時に使用した回路と同じです。
これに、ブレッドボードの抵抗+位置と、
アナログA0番ピンに配線(黄色)をします。
※配線を変更する時は、ArduinoのUSBケーブルは抜いておきます。
では、ArduinoIDEでスケッチします。
// 大域変数宣言
int vali = 0; // 読み込み数値保持用変数
void setup() {
// put your setup code here, to run once:
pinMode( A0, INPUT ); // アナログ0番ピンを入力用に割り当て
Serial.begin( 9600 ); // シリアルポートを初期化(9600 bpsで通信)
}
void loop() {
// put your main code here, to run repeatedly:
vali = analogRead( A0 ); // アナログ0番ピンより数値読み込み
Serial.println( vali ); // 読み込んだ数値をシリアルモニタに表示
delay(2000); // 2秒停止
}
このプログラムで、
// 大域(グルーバル)変数宣言
int vali = 0; // 読み込み数値保持用変数
が定義されています。
これは、このシート(スケッチ)のどこからでも参照可能
というものです。
各、関数内で定義された変数は、その関数内のみで有効となり、
他の関数からは見えない(使えない)状態となります。
これを、局所(ローカル)変数宣言といいます。
この、どの範囲で利用出来るかを変数の有効(スコープ)範囲
といいます。
※今回の例では、大域変数宣言を使ってみただけで、
局所変数として宣言しても問題ありません。
スケッチの確認を済ませたら、
USBケーブルを接続し、Arduinoに書き込み実行してみます。
シリアルモニタで確認してみると、
1023と表示されています。
回路上の測定位置は、ブレッドボードの抵抗+位置なので、
5VがArduinoより供給されているはずです。
ですが、0~1023の数値表現なので分かりづらいですね。
では、V表示に変更してみましょう。
といっても、勝手にはしてくれませんから計算で求めます。
計算式は、
V = ( 5.0 ÷ 1023 ) × 測定数値
となりますね。
この式をスケッチに組み込んでみます。
// グローバル変数宣言
int vali = 0; // 読み込み数値保持用変数
float valf = 0; // V計算結果保持用変数
void setup() {
// put your setup code here, to run once:
pinMode( A0, INPUT); // アナログ0番ピンを入力用に割り当て
Serial.begin(9600); // シリアルポートを初期化(9600 bpsで通信)
}
void loop() {
// put your main code here, to run repeatedly:
vali = analogRead( A0 ); // アナログ0番ピンより数値読み込み
valf = ( 5.0 / 1023.0 ) * vali; // 数値をVに変換計算
Serial.print( valf ); // V変換値をシリアルモニタに表示
Serial.println( " V" );
delay(2000); // 2秒停止
}
Arduinoに書き込み実行してみます。
こんどは、電圧らしき表示になりました。
測定位置を変更します。
今度は、LEDにかかる電圧を測定して見ます。
図のように、アナログA0ピンとの配線(黄色)を、
LEDアノード(+)側へ移動します。
※配線を変更する時は、ArduinoのUSBケーブルは抜いておきます。
配線が変更できたら、ArduinoのUSBケーブルを接続し、
電源を供給します。
このとき、プログラムは同じなので、書き込み処理は不要です。
電源供給(USBケーブルを接続)のみでOKです。
私の場合ですと、1.9Vくらいの電圧がかかっています。
このとき、シリアルモニタの表示が正しくない
(訳の分からない文字や数値が途中表示のような)場合、
コンソールモニタ右下の出力クリアを押して下さい。
それでも直らない場合は、
マイコンボードへの書き込みを再度行うか、
Arduino本体のリセットボタンを押します。
値自身が正しくない場合には、
回路、プログラムをもう一度確認します。
analogWrite( )関数を使って出力している平均電圧を、
参考までに測定してみました。
今回の、測定に使ったデューティ比は、
デューティ比を5等分した辺りの値かな?ということで設定してみました。
( デューティ比:0 → 63 → 127 → 191 → 255 で測定)
0、63、127 は 2.5V レンジ、191、255は 10 Vレンジで測定しています。
※私のマルチテスター(アナログ)では、やや低めの測定値になっています。