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本体のピン番号のところに、
“~”のようなマークが付けられていると思います。

Arduino本体のPWD表示
Arduino本体のPWD表示

このPWDの出力関数は、
 analogWrite( )関数です。
書式は、
 analogWrite( ピン番号、 デューティ比)
です。
デューティ比とは、1周期内でのONとOFFのを、
0~255の数値で表したものです。
0:周期のすべてで出力しない(平均電圧は0V)
127:周期の半分の間、出力する(平均電圧は2.5V)
255:周期の全てで出力する(平均電圧か5.0V)
という具合です。

デューティ比図1
デューティ比図1
デューティ比図2
デューティ比図2
デューティ比127の時のオシロスコープ測定1
デューティ比127の時のオシロスコープ測定1(未0調)
デューティ比127の時のオシロスコープ測定2
デューティ比127の時のオシロスコープ測定2(未0調)

では、デジタルピン6番を使って、
LEDの明るさを変化させるプログラムをしてみます。

ブレッドボードとArduinoの配線を行います。
※ArduinoのUSBケーブルは抜いておきましょう。
回路図のように配線します。
   この回路図の作図には fritzing を利用させて頂いております。
   https://fritzing.org/home/

回路図1
回路図1

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に書き込みます。

ArduinoIDEでスケッチ
ArduinoIDEでスケッチ

徐々に明るさが変化しましたか。
このプログラムでは、
 analogWrite( 6, i );
の整数型変数iの値を0~255の間で変化させることで、
電圧を変化させ、LEDの明るさを変えています。
また、変数iの値を2ずつ変化させていますが、
特に意味はありません。
もちろん、1ずつで構いません。

続いて、
アナログピンを使って、電圧を測定してみます。
アナログピンは、入力されてくる電圧を、
0~1023の数値に変換して表されます。
 0:0V
 511:2.5V
 1023:5V
といった具合です。

0~1023の数値変換
0~1023の数値変換

アナログピンを使用する場合、
void setup()関数で、ピンのモード設定が必要です。
今回は、アナログ0番ピンを使用しますので、
  pinMode( A0, INPUT ); // アナログ0番ピンを入力用に割り当て
と設定します。

アナログピンに入力されてくる値を読み込むには、
analogRead( ) 関数を使用します。
書式は、
 analogRead( ピン番号 )
となり、読み込まれた数値は、
この関数自身が保持していますので、
int val = analogRead( A0 );
などと使用し、変数に代入して利用します。
この例の場合、analogRead( A0 )が持っている数値を、
代入演算子(=)を使って、整数型変数valに代入しています。

では、2カ所電圧を測定します。
図のように、配線します。

回路図2
回路図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に書き込み実行してみます。

回路図3
シリアルモニタ表示

こんどは、電圧らしき表示になりました。

測定位置を変更します。
今度は、LEDにかかる電圧を測定して見ます。
図のように、アナログA0ピンとの配線(黄色)を、
LEDアノード(+)側へ移動します。
※配線を変更する時は、ArduinoのUSBケーブルは抜いておきます。

回路図3

配線が変更できたら、ArduinoのUSBケーブルを接続し、
電源を供給します。
このとき、プログラムは同じなので、書き込み処理は不要です。
電源供給(USBケーブルを接続)のみでOKです。

シリアルモニタ表示
シリアルモニタ表示
マルチテスターで測定(デジタル)
マルチテスターで測定(デジタル)
マルチテスターで測定(アナログ)
マルチテスターで測定(アナログ)

私の場合ですと、1.9Vくらいの電圧がかかっています。

このとき、シリアルモニタの表示が正しくない
(訳の分からない文字や数値が途中表示のような)場合、
コンソールモニタ右下の出力クリアを押して下さい。
それでも直らない場合は、
マイコンボードへの書き込みを再度行うか、
Arduino本体のリセットボタンを押します。
値自身が正しくない場合には、
回路、プログラムをもう一度確認します。

リセットボタン
リセットボタン

analogWrite( )関数を使って出力している平均電圧を、
参考までに測定してみました。
今回の、測定に使ったデューティ比は、
デューティ比を5等分した辺りの値かな?ということで設定してみました。
( デューティ比:0 → 63 → 127 → 191 → 255 で測定)
0、63、127 は 2.5V レンジ、191、255は 10 Vレンジで測定しています。
※私のマルチテスター(アナログ)では、やや低めの測定値になっています。

 デューティ比:0
デューティ比:0(0V)
デューティ比:63
デューティ比:63(1.2V→1.25V ?)
デューティ比:127
デューティ比:127(2.4V→2.5V ?)
デューティ比:191
デューティ比:191(3.6V→3.75V ?)
デューティ比:255
デューティ比:255(4.8V→5.0V ?)