ArduinoのスタートアップといえばLチカですが、さらにもう一歩踏み込んでいつもと異なるLEDのつなぎ方やdigitalwrite以外の関数を使ったLEDの点灯をやってみたいと思います。
目次
ArduinoでLEDを点灯させる繋ぎ方
ArduinoでLEDを点灯させる場合配線をちょっと変えれば別の電源から電力を供給してarduinoで制御することができます。
LEDをGNDに接続したLED点灯回路
図は一般的な回路構成によくある13PINとGNDにLEDをつなげた回路です。
この回路構成だとマイコンの12PINがHighになったときに5Vが供給されるので、スケッチ上でもHighで点灯、Lowで消灯と直感的にLEDのオンオフを把握することができます。
フルカラーLEDやマトリクスLEDでカソードコモンとなっている場合はこのつなぎ方でOKです
5VをLEDに接続したつなぎ方
この回路構成では12PINと5Vを接続しています。この配線の場合、ボードに搭載されている5Vレギュレータから直接電力を供給しています。
この回路構成の場合、Highの時に13PINから5Vが供給され5V側の電圧と釣り合うためLEDは点灯しなくなります。逆に13PINがLowになると5V側からArduino側に電流が流れLEDは点灯します。
マイコンや論理ICは電気を送り出す能力よりも電気を引き込む力の方が強いので、場合によってはこちらの回路構成をとらざるを得ない場合があるかもしれません。また、LEDを点灯させるような状態が多く、マイコンの消費電流を下げたい場合は出力ピンをOFFでLEDを点灯させたほうがいいので、この回路構成にする場合もあります。
また、フルカラーLEDやマトリクスLEDでアノードコモンとなっている場合もこの点灯方法を採用します。
おなじみのdigitalWrite関数でLEDを点滅させる
LED点灯やその他様々なところでお世話になるのがdigitalWrite関数です。
この関数は5VとGNDの出力を制御する関数です。HIGH出力時は5Vを出力し、LOW出力時は0V(GND)となります。
最も簡単なオンとオフを切り替える関数なので様々なところで使います。下の画像はdigitalWite関数でLEDを点滅させている様子です。
void setup() { pinMode(11, OUTPUT); } void loop() { digitalWrite(11, HIGH); // 点灯 delay(1000); digitalWrite(11, LOW); // 消灯 delay(1000); // }
PWMで明るさを調整できるanalogWrite関数
analogWrite関数はデジタル出力をPWMを使って疑似的にアナログ出力を行う関数です。
この関数は安定した方形波を出力する関数です。方形波のデューティ比は関数上で指定できるのでLEDの明るさを自由に調整することができます。
例えば、LEDの明るさを調節したり、ボンヤリ点灯させる際などにも便利です。
void setup() { } void loop() { int a = 0; for (a = 0; a <= 255; a++) //点灯 { analogWrite(11, a); delay(5); } for (a = 255; a >= 0; a--) //消灯 { analogWrite(11, a); delay(5); } delay(500); }
フルカラーLEDを使ってみる
単色LEDの点滅だけでは面白みがないのでフルカラーLEDを使ってみます。フルカラーLEDは赤・青・緑それぞれのLEDが一つのパッケージに収められており、それぞれの色で調光を行うことで様々な色を表現することができます。
さて、通常のLED点滅であれば、digitalWrite関数でON/OFFを指定し、明るさの調整は抵抗の電流制限で行いますが、フルカラーLEDの場合は表現したい色に合わせて3つのLEDの光量を調光しなければいけません。そのためには先述のanalogWrite関数を使用します。
フルカラーLEDは3つのLEDが内蔵されているため、配線もそれに準じて取り付けます。アノードコモンかカソードコモンかで配線が変わるのでこの辺注意しましょう。
今回は秋月電子で購入したフルカラーLED OSTA5131Aを使います。
全色表示できるようなスケッチを考える
さて、せっかくのフルカラーLEDなので本当にフルカラー(1677万7216色)で表示させたいわけなんですが、参考になるサイトを見ても滑らかに色合いを変化して表示できるスイッチてなかなかないんですよね。
よーく調べてみると三色のLEDを全色滑らかに出せるようなアルゴリズムが地味に難しいようです。(for文で逐次色を切り替えたり、rand関数を使えば一発解決ではあるのですが…)
というわけで、簡単にフルカラーを表示できるようなスケッチを考えたのがこちらです↓
#define LED_RED 9 //赤LED PIN番号 #define LED_BLUE 10 //青LED PIN番号 #define LED_GREEN 11 //緑LED PIN番号 #define LED_RED_TIME 5 //赤LED 周期 #define LED_BLUE_TIME 6 //青LED 周期 #define LED_GREEN_TIME 7 //緑LED 周期 int red = 0, blue = 0, green = 0; int f_red = 0, f_blue = 0, f_green = 0; // 初期化 void setup() { // LEDのピンを出力に pinMode(LED_RED, OUTPUT); pinMode(LED_BLUE, OUTPUT); pinMode(LED_GREEN, OUTPUT); } // メインループ void loop() { if (f_red == 0) { red = red + LED_RED_TIME; if (red >= 250) { f_red = 1; } } else { red = red - LED_RED_TIME; if (red <= 0) { f_red = 0; } } analogWrite(LED_RED, red); delay(50); if (f_blue == 0) { blue = blue + LED_BLUE_TIME; if (blue >= 200) { f_blue = 1; blue=200; } } else { blue = blue - LED_BLUE_TIME; if (blue <= 0) { f_blue = 0; blue=0; } } analogWrite(LED_BLUE, blue); delay(30); if (f_green == 0) { green = green + LED_GREEN_TIME; if (green >= 200) { f_green = 1; green=200; } } else { green = green - LED_GREEN_TIME; if (green <= 0) { f_green = 0; green=0; } } analogWrite(LED_GREEN, green); delay(20); }
3色の光量を周期的に変化するようにして、それぞれの周期を微妙にずらして色が滑らかに変化するようにしました。もうちょっと周期の差を無くしたりもっと別の複雑なアルゴリズムにしていけば色の表現度をもっと上げることもできるでしょうが、とりあえず今回はこれで満足です。
カメラ越しにLEDを撮影すると変化がわかりにくいので、丸めた紙を被せて色の変化がわかるようにしました。