Arduino編
その4 アナログ出力でLEDの明るさをふわーっと変えてみる
Arduinoにはデジタルピンとアナログピンがあります。デジタルピンはON時に5Vもしくは3.3V、OFF時には0Vになります。一方アナログピンは、アナログと言うくらいなのですから、その辺りが可変なのかなぁなんてイメージしています。この章ではその辺りを調べつつ、LEDの明るさをアナログに変化させてみようと思います。
@ アナログピンの仕様
本家HPのReferenceにFunction(関数)の項目があり、そこに「Analog I/O」というのがあります。ここにある関数を調べてみましょう。
○ analogReference関数
アナログ入力の参照電圧をフラグで設定します。参照電圧を100%とした時の実際の入力電圧をプログラム内で数値化するのに必要です。
analogReference( type );
typeには参照電圧を指定するフラグを渡します。設定できるフラグは以下の通り:
フラグ 意味 DEFAULT 参照電圧を5Vもしくは3.3Vに設定します(電圧は基板のデフォルト値) INTERNAL 組み込み電圧に設定(ATmega168もしくはAtmega328は1.1V、Atmega8では2V) INTERNAL1V1 組み込み電圧を1.1Vに設定(Arduino Megaのみ) INTERNAL2V56 組み込み電圧を2.56Vに設定(Arduino Megaのみ) EXTERNAL AREFピンに適用された電圧(0Vもしくは5Vのみ)を参照電圧として使用
これを見ると、まぁ普通はDEFAULTでいいのかなぁと思います。
○ analogRead関数
アナログ入力ピンの値を読み込みます。
analogReference( pin );
pinには値を読み込みたいピン番号を指定します。Arduino UNOの場合アナログ入力ピンは6つなので0〜5を指定できます。
Arduinoのアナログピンに入力された電圧はADコンバータ(アナログデジタルコンバータ)によって10bitの整数値に変換されるようです。10bitなので0〜1023までの1024段階という事です。デフォルトでは5Vがマックスで1023、0Vが0に変換。0.049Vが1単位になります。読み込み速度は最速で100マイクロ秒、つまり1描画んに10000回更新する事ができるそうです。お〜〜
○ analogWrite関数
アナログ値をデジタルピンに出力します。
analogWrite( pin, value );
pinにはアナログ値を出力するデジタルピン番号を指定します。Arduino UNOだと3,5,6,9,10,11ピンです。
valueには0〜255の整数を指定します。0だと出力ゼロ、255だと出力100%です。
「アナログなのにデジタルピンに出力とはこれいかに?」と思うかもしれません。analogWrite関数のvalueで指定された整数値は「矩形波のDuty比」というのを調節する値です。どういう事か以下で説明します。
デジタルピンに出力する時に、例えば50%だから2.5V…のような電圧をコントロールする器用な出力は出来ません。これをするには可変抵抗器が必要です。そこで、物凄い勢いでONとOFFを繰り返すことで擬似的にアナログを再現します。例えば、valueに128を入れるとデジタルピンには次のような矩形波が出力されるようになります:
赤いラインが1周期で、基本的には490Hzだそうです。つまり1秒間に490回この周期が繰り返される速さという事です。ただしデジタルピンの5番と6番はこれが980Hzと倍速になっているとリファレンスにあります。精度を要求される場合はこのピンで、という事でしょうね。
このような矩形波にすると、例えばモーターなどは実質の駆動時間が半分になりますよね。という事は、モーターの回転速度が半分になります(擬似的に)。LEDも点いている時間が半分で、人の目にはこんなハイスピードの周期の点滅は見えないので、暗く光っているように見えます。valueに小さな値を入れる程に1周期で100%である時間が短くなっていきます。逆に大きな阿多にするとその時間が長くなっていきます。
A LEDの明るさを変化させてみよう
では、LEDの明るさを周期的に変えるプログラムを作ってみましょう。
LEDを1秒間線形に明るくしていき、次の1秒で線形に暗くするという周期を繰り返す仕様にします。これを実現するにはタイマーが必要です。Arduinoにはmillis関数というArduinoが起動してからの経過ミリ秒をunsigned longで返してくれる関数が用意されていますので、それを使う事にしましょう:
int led = 3;
void setup() {
pinMode( led, OUTPUT );
}
void loop() {
unsigned long def = millis() % 2000;
def = ( def <= 1000 ? def : 2000 - def );
analogWrite( led, (int)( def / 1000.0 * 255 ) );
}
まずsetup関数で3番ピン(アナログ出力可能なピンの一つ)を出力ピンとして設定します。loop関数では現在の時刻を2000ミリ秒単位に区切ってdefに格納しています。もしdefが1000ミリ秒以内だったらそのまま、1001ミリ秒〜1999ミリ秒だったら2000から引く事でdefが小さくなるようにしています。後はそれを0〜255段階に変換してanalogWrite関数に渡せばOK。
これをAnduino基板に流し込んで3番ピンにLEDを繋げると:
ふわ〜っとアナログチックに明滅しています!面白い。
という事で、アナログ出力もテストできました。これはモーターを制御するなど色々使えそうです。