はじめに
ArduinoでLチカした際に、delay()
関数の数値を十分小さくすると点滅から点灯に変わるかと思います。このように十分に短いスパンでの点滅は人間の目には点滅と認識できなくなります。
この原理を用いてLEDの明るさを変えたりする方法をLEDのダイナミック点灯と呼び、PWM出力によって機能させています。
今回はこのPWMについて少しだけ解説します。
ArduinoにおけるPWM
パルス幅変調(パルスはばへんちょう、英語: pulse width modulation、PWM)とは変調方法の一つであり、パルス波のデューティ比を変化させて変調すること。
パルス幅変調 – Wikipedia
機械工学などにおいては、スイッチオン/オフの比率を変化させる手法。
シンセサイザーで、パルス波のデューティ比を変化させること。
わかりにくいですが、デジタル出力を高速にON / OFFを切り替え、さらにそのONの時間とOFFの時間の割合を変えることができる、ということですね。
このONとOFFの割合のことをduty比と呼びます。
はじめに書いたようにdelay()
などを使って自分でON/OFFを切り替えるタイミングを作っても良いのですが、Arduinoには初めからそのようなパルスを出力するデジタルピンが備わっています。
デジタルピン(PWM対応)などと表記されており、Arduinoボードのピン番号に「~」のマークが付いているピンはPWMの出力に対応しています。
Arduino UnoではPin番号「3, 5, 6, 9, 10, 11」が対応するピンです。
5,6番ではPWMの周波数(「On/OFF」の繰り返し周期)は977Hz、3,9,10,11番では490Hzだそう。つまり約1 – 2msの周期でPWMを生成することができます。
この周波数は変更させることができますが、この変更によりArduinoのシステム内部に影響を与えることがあるので、基本的には変更させずに使うのが良いです。詳しくは この辺。
また5,6ピンはdelay()
やmil()
関数といった時間系の処理にも使われるので、処理の割り込みによりPWMが綺麗に出ないことがあるとのこと。
5番と6番ピンで生成したPWM出力は,設定したデューティー比よりも高くなる場合があります. これは,PWM出力に使用している内部タイマーが,同じタイマーを使用する
https://www.arduino.cc/reference/jp/language/functions/analog-io/analogwrite/millis()
やdelay()
などの関数によって割り込まれるからです.これらは,低デューティー比の場合(0から10)のときに多く現れ,5番と6番ピンでデューティー比を0に設定しても完全にはオフにならない可能性があります.
まあ、いってしまえば普通に使う分には気にせずにPWM出力が使える、というわけですね。
ArduinoのPWMのduty比は256段階(8bit)で調整できます。
さてこのduty比ですが、一定時間のONの割合が変わる、ということからLEDがそのduty比によって明るさが変わる、ということにつながります。
duty比が小さい間はONの割合が少ないので、LEDは点いている時間は消えている時間に比べて短いので薄く点灯、逆にduty比が大きい間は濃く点灯します。
このようなLEDの制御方法をダイナミック点灯と呼ばれ、様々な場所で使われています。
PWM変調によるLED出力の作成
はじめに
今回はPWMを使ってLEDを調光します。
基本的にはLチカの発展なのでそこまで難しくはないですね。
PWMの値を変えるとLEDの明るさが変わる様子を確かめましょう。
用意するもの
Arduino本体 (今回はArduino Uno互換機)
Akizuki : http://akizukidenshi.com/catalog/g/gM-07385/
LED(今回は青色LED)
Akizuki : http://akizukidenshi.com/catalog/g/gI-01321/
抵抗(220Ω)
Akizuki : http://akizukidenshi.com/catalog/g/gR-25221/
ブレッドボードとケーブル
Akizuki : http://akizukidenshi.com/catalog/g/gP-00315/
Akizuki : http://akizukidenshi.com/catalog/g/gC-05371/
Arduino ボード
接続方法はほとんどLチカの時と同じですね。
Lチカの時は慣例的に13番ピンにつなげていましたが、今回はPWM出力に対応している3番ピンからLEDを制御します。
Arduino IDE
コードの全体
int const LED = 3;
void setup() {
pinMode(LED, OUTPUT);
}
void loop() {
for(int i = 0; i < 256; i++){
analogWrite(LED, i);
delay(10);
}
}
setup()
関数まではLチカとほとんど同じですね。
LEDピンの変数(定数)の宣言、setup()
内でピン番号の宣言です。
loop()関数にはfor()
文による繰り返しが行われています。
for文には3つの引数を取り、
for( 初期化 ; 継続条件 ; 増分処理 ){
文
}
というような形を取ります。
今回だと、はじめにi
という変数を宣言しi = 0
を代入します (つまり i = 0
から始まる)。
for文の中は 2番目の引数の条件の間繰り返されます。今回はi
が256を超える手前まで繰り返されるというわけですね。
さてfor文ですが、for文の中の処理が終わるごとに第3引数の処理が行われます。今回は i++
なので、for文の中の処理が終わるごとに i
が1増えるというわけですね。
analogWrite(LED, i);
ArduinoはPWM出力端子に関してはdigitalWrite()
の代わりにanalogWrite()
という関数が使えます。
analogWrite()
はdigitalWrite()
同様に2つの引数をとることができますが、digitalWrite()
の時と違って第2引数をHIGH, LOWではなく0 から 255までの256段階(8bit)の数値をとることができます。
この数値がPWMのduty比になります。
今回は第2引数に i
を取っているので、PWMのduty比は i
( 0 – 255 ) の間を動くというわけですね。 i
はfor文が終わるごとに1増えるのでduty比も1ずつ増えていく、つまりLEDは少しずつ明るくなっていくというわけですね。
まとめ
PWMは今回のダイナミック点灯の制御以外にも、あらゆる機器の制御に使われています。
PWMの基本がわかればそういった機器の制御も簡単に理解できるようになりますね。