Arduino 4( サンプル:Fade )
前回に引き続き、いまだに重い腰を上げてArduinoのスケッチ例を試してArduinoの使い方を学んでみる。今回はスケッチ例:Fade を動かしてみる。FadeはPWMを利用してゆっくり点滅するサンプルプログラム。
スケッチ例:Fade
スケッチ例を起動する
前回と同様に、ファイル➡スケッチ例➡01.Basic➡Fade をクリック
場所がわからない場合は前回記事を参照
Fadeを開いたら下の様な画面が出てくる。
上部のコメント箇所にはざっくり意訳すると下のような内容が書かれている。
この例は、analogWrite()関数を用いてpin9でLEDを徐々に消す方法を示す。
analogWrite()関数はPWMを使う。なので、使用するピンを変更したい場合は
別のPWM機能があるピンを使用する必要がある。
ほとんどのArduinoは、PWMピンを”~”記号で示されている。
例):~3,~5,~9,~10,~11 説明はこのURL http://www.arduino.cc/en/Tutorial/Fade
PWM (Pulse Width Modulation)
PWMとは、下図のように2つの電圧レベル(例:0Vと5V)でその中間の電圧レベルを実現するための手法。つまり、0Vと5Vしか出力できないマイコンで2Vや4.2Vという中途半端な電圧を疑似的に出力することが出来る。下図のようにパルスからパルスまで時間を”パルス周期”や”PWM周期”とよび、高い電圧レベル側の時間を”ON時間”と呼ぶ。そして、ON時間 / パルス周期 を”Duty比”と呼ぶ。このDuty比に、高い側の電圧を掛けた値が出力電圧となる。
このPWMは、RCサーボの角度を指令したり今回のようにアナログ値に変換したりと、制御には欠かせない重要な要素なのでArduinoでも早めにできるようになった方がよい。
プログラム解説
下にFadeのプログラムを引用する。 まず、変数の宣言部を見てみる。
int led = 9; // the PWM pin the LED is attached to int brightness = 0; // how bright the LED is int fadeAmount = 5; // how many points to fade the LED by
変数:led
LEDを接続するPIN番号の設定(この場合はpin9)でプログラムの実行中は変更できない。変数:brigthness
LEDに入力するPWMのDuty比を設定する変数(値範囲0~255)。この変数はプログラム実行中に変化してLEDの明るさも変わる。変数:fadeAmount 一回の処理でbrigthnessを変化させる量。この値はLEDが明るく変化するときは5、LEDが暗く変化するときは-5の値になる。
次に、setup関数を見てみる。
void setup() { // declare pin 9 to be an output: pinMode(led, OUTPUT); }
ここでは、pinMode関数でledを接続するpinの設定を行っている。変数ledの値は今、9なのでpin9を出力端子設定に変更する処理を行う。
さらに、最も重要な処理をしているloop関数を見てみる。
void loop() { // set the brightness of pin 9: analogWrite(led, brightness); // change the brightness for next time through the loop: brightness = brightness + fadeAmount; // reverse the direction of the fading at the ends of the fade: if (brightness <= 0 || brightness >= 255) { fadeAmount = -fadeAmount; } // wait for 30 milliseconds to see the dimming effect delay(30); }
とりあえず、上から見ていく。
analogWrite(led, brightness);
analogWrite関数がPWMについて操作する関数で引数に、出力ピン番号とDuty比をとる。出力ピン番号はコメントに書いてあった通り、PWMが出力可能なピンを指定する必要がある。またDuty比は0~255で与えるひつようがある、0~100%の値をそのまま入れたら高い電圧が出ないので注意が必要。なぜ、0~255という範囲というと、このPWM出力が8bitTimerというものを使っているからだ。8bitTimerは8bitの範囲でカウントしていくので2の8乗で256の分解能ということになる。だから、0~255の範囲でDuty比を与える必要がある。
brightness = brightness + fadeAmount;
ここでは変数 brightness に fadeAmount を足して、brightness に代入している。つまり、この処理をするたびに brightness は fadeAmount の値で増加する。そしてbrightnessは先のanalogWrite関数でDuty比となっているので、fadeAmountが正の値ならだんだんLEDが明るくなる。負の値ならだんだん暗くなる。
if (brightness <= 0 || brightness >= 255) { fadeAmount = -fadeAmount; }
この箇所はif文で条件分岐をしている。条件式は ”brightness が0以下または brightness が 255以上”となっているので、これに当てはまると{}の中の処理を行う。この条件式の意味はDuty比の下限以下か上限以下かということ。また、{}の中の処理はfadeAmountの符号を反転させるというものなので、LEDがだんだん明るくなるか、暗くなるかの制御をここで行っている。
つまり、この3行でLEDを明るくしてから暗くなることを繰り返す処理をしている。もしもこの処理がなかった場合はゆっくり明るくなり、brightness の値が上がり続けてオーバーフローしたらいきなり暗くなり、また明るくなっていくということを繰り返す。つまり、ゆっくり暗くなるという工程がなくなり、点滅周期も変わってしまう。(int型のbit数が判らないのでどのくらい周期が変わるかわからないが、)
delay(30);
最後にdelay関数がある。この関数は引数の数値の量だけ処理を止めるという関数で単位はミリ秒。つまりこの処理では30ミリ秒処理を止める。これによりloop関数の処理周期を約30ミリ秒とすることが出来る。この処理を止めるとう作業を行わないと、点滅周期が早すぎてFadeではなく高速のBlinkになってしまう。
因みに、点滅の周期は 2256/530 = 3027 [msec.]となるので、約1.5秒かけて明るくなり約1.5秒かけて暗くなる。じっさいにプログラムを動作させてもその程度の時間で変化していく。つまり、この計算を逆算して delay() の引数と fadeAmount の初期値の値を変更することで、周期を自由に変えることが出来る。
配線
今回のサンプルプログラムではLEDをpin9に接続すればよい。しかし、ここで2通りの配線が考えられる。つまり、LEDのアノード側を+5Vに接続してカソード側をpin9に接続する方法と、アノード側をpin9に接続してカソード側をGNDに接続する方法だ。
ここで重要となるのはLEDを介してマイコンに流れるもしくは流す電流の大きさだ。CMOS回路の特性上、電流を吐き出すよりも吸い込む方が電流を流せる。なので、ひと昔前は電流を少し流す用途ならば吸い込み側で使うことを推奨されていた。これは原理上NchFETのほうが、PchFETよりも同じ素子の大きさで流せる電流が大きいからだ。 しかし、最近のマイコンのデータシートだと吐き出し側と吸い込み側で電流値が分かれていないので、定格以内ならばどちらでも良い。しかし、高輝度LED等は必要な電流が大きく、計算せずに200Ωの抵抗を直列接続した場合は定格値を超えてしまう場合があるので、LEDに流れる電流値は毎回計算したほうが良い。
LED電流の求め方
LEDに流れる電流の求め方は下の式のように求める。LEDの順方向電圧とは、順方向(アノードからカソードに向かう方向)に電流を流したときに電流の大きさに関係なくダイオードで電圧降下する量のこと。LEDの順方向電圧はシリコンダイオードやショットキーバリアダイオードと比べて倍以上大きく、2~3.5V程度ある。
また、順方向電圧はLEDによって個体差があるので同じ型番のLEDで同じ抵抗を接続しても明るさが異なることがある。その時はLEDドライバーや定電流ダイオードを用いると良い。そして、配線の件に今回使用するLEDと抵抗の場合は順方向電圧2.9V、抵抗値680Ωなので約3mA となる。
LED配線回路決定
先の計算よりLEDに流れる電流、つまりマイコンに流れる電流が3mA と分かった。この値は定格以内なので、マイコンに直接接続できる。今回配線はアノード側をマイコンに接続した。配線写真を下に示す。
実行結果
まとめ
今回はLEDをゆっくり点滅させるFadeを介してPWMの設定方法について学べた。前述した通りPWMは制御には欠かせない要素なので他の出力方法もないのか調べる必要がありそうだ。実は今回の8bitの分解能では粗すぎて、モータ等の動くものの制御に用いようとすると上手く制御することはできない。
前回記事