Arduino

Arduinoを使ったPWM制御

前回までは、スイッチを使ってLEDを点灯・消灯する回路とプログラムを作りました。LEDの光り方として『点灯』と『消灯』の2種類でしたが、実際にはもっときめ細かな光り方があります。例えば、ノートパソコンがスリープ状態になっている時には電源ランプが徐々に暗くなりその後、徐々に明るくなる光り方をします。

今までのLEDの光り方は点灯(HIGH)と消灯(LOW)の2値のデジタルで表していましたが、ノートパソコンのスリープ状態時の電源ランプのようなLEDの光り方は、0~254の値を使ったアナログで表します。

今回はこのアナログでLEDの光り方を制御する、PWM制御について書いていきたいと思います。

PWM制御とは

PWM制御とは、パルス変調幅(Pulse Width Modulation)制御の略称です。具体的には、入力電圧から一定周期のパルス列のON/OFFを作り、このON/OFFの比率を変化させることです。

例えば、下図のようにON:OFF = 50:50のパルス列があったとします。これはONの時間が1周期の50%、同様にOFFも1周期の50%となります。

これをON:OFF=75:25のパルス列にすると下図のようになります。

このようにPWM制御では、ON/OFFのパルス列の比率を変化することによって任意の電圧得ることが出来ます。

Arduinoでは、3,5,6,9,10,11のピンにPWM出力が割り当てられています。これらのピンを使うことによってPWM制御が出来ます。

PWMで制御するLEDを使った回路

今回作成する回路は、LEDが徐々に明るくなった後、徐々に暗くなるという明るさの制御をします。具体的にはLEDのONのパルス列の比率を1%,2%,3%…100%と変化した後に、100%,99%,98%…0%と変化します。

必要な機器・端子

使用した機器・端子は以下の通りです。

Arduino マイコン搭載の小型コンピュータ
フレットボード 抵抗・ジャンパー線などを使って回路を作る基板
LED 順方向に電圧を加えると発光する半導体
ジャンパー線 電気を中継する線
抵抗10kΩ 電圧を下げる端子
回路をくむ

Arduinoの9番ピンとフレットボードの(f,18)をジャンパー線でつなぎ、LEDを(h,18)と(h,17)にカソードとアノードをそれぞれ差し込みます。LEDが燃えないように抵抗を(i,17)と(i,13)に差し込み、最後に(j,13)とArduinoのGNDをジャンパー線でつなぎます。

プログラムコード

プログラムコードは以下の通りです。

const int MAX = 255;//カウントアップの最大値
const int MIN = 0;//カウントアップの最小値
int LED = 9;//LEDを9番ポート
int i = 0;//カウントアップ用変数

void setup() {
// put your setup code here, to run once:
pinMode(LED,OUTPUT);//9番ポートを出力モード
}

void loop() {
// put your main code here, to run repeatedly:

//徐々にLEDを光らせる処理
for(i = 0; i < MAX; i++) {
analogWrite(LED,i); delay(10);
}

//徐々にLEDを暗くさせる処理
for(i = MAX;i > MIN;i–)
{
analogWrite(LED,i);
delay(10);
}

}

PWM制御をするには、analogWrite関数を使います。

analogWrite(LED,i);

冒頭では、ON/OFFの比率を%で変更すると説明しましたが、ここではanalogWriteを使って0~255の値を使ってPWM制御をしています。つまり、100%を255段階で表していることになります。具体的にはONが0%の場合はanalogWrite(LED,0)となり、100%の場合はanalogWrite(LED,255)となります。ONが50%の場合は、analogWrite(LED,128)となります。

実行結果

実行結果は以下のようになります。

PWMで制御するLEDとスイッチを使った回路

さて、ここではもう少し応用的な回路を組みたいと思います。今回作成する回路の要件は以下の通りとします。

・スイッチを押すことでLEDが点灯・消灯をする
・LEDが点灯時にスイッチを長押しすると徐々にLEDの明るさが上がる
※最大値になると0になる

完成した回路は下図の通りです。

必要な機器・端子

この回路を構成するにあたって必要な機器・端子は以下の通りです。

Arduino マイコン搭載の小型コンピュータ
フレットボード 抵抗・ジャンパー線などを使って回路を作る基盤
LED 順方向に電圧を加えると発光する半導体
ジャンパー線 電気を中継する線
抵抗10kΩ 電圧を下げる端子
スイッチ ボタンのON/OFF
LEDをつける

まず、Arduinoの9番ピンとフレットボードの(f,18)をつなぎ、LEDを(h,18)と(h,17)に設置します。次に抵抗を(i,17)と(i,13)に設置し、(j,13)とArduinoのGNDをジャンパー線でつなぎます。

スイッチをつける

はじめにスイッチを(f,7)、(f,5)、(e,7)、(e,5)につけます。次にArduinoの5Vとフレットボードの(j,7)をジャンパー線でつなげ、Arduinoの7番ピンと(j5)をジャンパー線でつなぎます。(g,5)と(g,1)に抵抗を設置し、ArduinoのGNDと(j,1)をジャンパー線でつなぎます。

プログラムコード

プログラムコードは以下の通りです。

const int BTN = 7; //スイッチを7番ピン
const int LED = 9; //LEDを9番ピン
const int MAX = 255;//PWM制御の最大値
const int MIN = 0; //PWM制御の最小値
const int WAIT_T = 500; //スイッチを押している時間の基準値

int val = 0; //今回のスイッチ状態
int old_val = 0; //前回のスイッチ状態
int states = -1; //LED点灯の状態を記憶
int startTime = 0; //スイッチを押した時間を記憶
int brightness = 128; //LEDの明るさを記憶

void setup() {
// put your setup code here, to run once:
pinMode(LED,OUTPUT);//LEDを出力モード
pinMode(BTN,INPUT);//スイッチを入力モード
}

void loop() {
// put your main code here, to run repeatedly:
val = digitalRead(BTN);//7番ピンの状態を読み取る

//①スイッチを押したかどうか
if(val == HIGH && old_val == LOW)
{
states = states * -1;//1:LED点灯、-1:LED消灯
startTime = millis();//スイッチを押した時間を記憶
delay(50);//バウシング対策
}

//②スイッチを押しっぱなしにしているか
if(states > 0 && val == HIGH && old_val == HIGH)
{
//③WAIT_T時間より長く押しっぱなしか
if((millis() – startTime) > WAIT_T)
{
brightness++;//LEDの明るさを上げる
delay(50);

//LEDの明るさが最大を超えたら0に強制的に戻す
if(brightness > MAX)
{
brightness = 0;
}
}
}
old_val = val;//スイッチ状態を前回に入れる

if(states > 0)
{
analogWrite(LED,brightness);
}else
{
digitalWrite(LED,MIN);
}

}

全体のプログラムの流れは前回の記事で作ったものと大差はありませんが、スイッチを押したかどうかの判定文に新しい関数millis()があります。

startTime = millis();//スイッチを押した時間を記憶

これはマイコンがリセットされた後から何msec経過しているかをマイコンが記憶しており、現時点での経過msecを取得する関数です。

その他のポイントとして、スイッチを押しっぱなしかどうかの判定があります。

if(states > 0 && val == HIGH && old_val == HIGH)

statesが1より大きいということはLEDが点灯する状態であること、valとold_valがHIGHのままということはスイッチが押され続けていることを条件にしています。

また、その後の条件文では現在のリセット後からの経過時間とstartTimeの差分が500msecより大きいかを判定しています。これは、プログラムはものすごいスピードで実行されるため、スイッチを押した行動とスイッチを長押しした行動を明確に切り分けるためにあえて500msec待つようにしています。

if((millis() – startTime) > WAIT_T)

 

実行結果

実行結果は以下の通りです。

まとめ

今回は、ON/OFFのパルス列の比率を変えてLEDの明るさを変える、PWM制御について説明しました。ArduinoではPWM出力が3,5,6,9,11ピンに割り当てられており、255の値を使ってコントロールすることが出来ます。PWM制御はLEDに限らず、モーター制御にも使われているため、是非ともマスタすべき技術であります。

参考書籍