もう少し効率の良いLEDの接続方法はないか? ということで考え出されたのがダイナミック点灯と呼ばれる方式である。6LEDの場合、例えば図1のような構成となる。

図1:

ちょっと便宜上、初期状態、つまりすべてのLEDが消灯している状態では、5つのピンに図2の様な電圧設定を行っておく。ここで便宜上LEDに左から1~6という番号を振っておくが、初期状態ではアノード(+側)に0V、カソード(-側)に5Vが掛かっているから、逆接状態となり、すべてのLEDに電流は流れず、点灯しないというわけだ。ここでD03ピンを0V、D06ピンを5Vに切り替えると、図3の様に6番のLEDだけが点灯する仕組みだ。この6番のみ、アノードに5V、カソードに0Vとなるからだ。1/2番は引き続きアノードに0V、カソードに5Vの逆接状態となる。3番のLEDはアノードとカソード、両方に5Vが掛かっているため、アノードとカソードの電位差は0Vで、事実上何も電圧が掛かっていないのと同じことになり、やはり点灯しない。また4/5番はアノード、カソード共に0Vなので、やはり電流は流れず点灯しないというわけだ。

図2:
図3:

表1に各ピンの設定と点灯するLEDの関係をまとめたが、前回よりもちょっと回路や制御が複雑になってはいるものの、利用するピンは1本、抵抗は半分に減った形になる。実際の配線の具合は図4の様な形になり、この上のSketchはList 1の様になる。Sketchの先頭でTable[][]という二次元配列を定義しているが、ここで表1の電圧をテーブルとして格納している。あとはこのテーブルを参照しながら、順次点灯→消灯を繰り返すという仕組みである(Tableの1つ目には5Vにすべきpin番号、2つ目には0Vにすべきpin番号がついており、配列の0番目、つまりLED 1ならば4番pinを5V、2番ピンを0Vにすれば点灯するという訳だ)。実際このSketchを動かすと、Movie01の様にうまく動作する。

■表1
Arduinoのピン電圧 点灯するLED
D02 D03 D04 D05 D06 LED 1 LED 2 LED 3 LED 4 LED 5 LED 6
5V 0V 5V 0V 0V × × × × ×
5V 0V 0V 5V 0V × × × × ×
5V 0V 0V 0V 5V × × × × ×
0V 5V 5V 0V 0V × × × × ×
0V 5V 0V 5V 0V × × × × ×
0V 5V 0V 0V 5V × × × × ×
図4:

List 1:

int Table[6][2]={{4,2},{5,2},{6,2},
                 {4,3},{5,3},{6,3}};

void setup()
{
  int lpCnt;

  for(lpCnt=2; lpCnt<4; lpCnt++)  /* Pin 2~3が対象 */
  {
    pinMode(lpCnt, OUTPUT); /* 当該PinをDigital Outに設定 */
    digitalWrite(lpCnt, HIGH);  /* 初期値は消灯 */
  }

  for(lpCnt=4; lpCnt<7; lpCnt++)  /* Pin 4~6が対象 */
  {
    pinMode(lpCnt, OUTPUT); /* 当該PinをDigital Outに設定 */
    digitalWrite(lpCnt, LOW);  /* 初期値は消灯 */
  }
}

void loop()
{
  int lpCnt;
  for(lpCnt=0; lpCnt<6; lpCnt++)
  {
    digitalWrite(Table[lpCnt][0], HIGH);
    digitalWrite(Table[lpCnt][1], LOW);
    delay(500);                 /* 500ms待機 */
    digitalWrite(Table[lpCnt][1], HIGH);
    digitalWrite(Table[lpCnt][0], LOW);
  }
}

動画
Movie01:

さて、同時に点灯するLEDが1個だけでよければそれでも可能だが、複数LEDを「同時」に点灯したい、なんて場合にはちょっと困ることになる。こうした場合に良く使われるのが、きわめて高速に点滅を繰り返すことで、見かけ上複数のLEDが同時に点灯しているように見せる方法だ。例えば6個のLEDを全部点灯させたいと思った場合、

「1点灯」→「2点灯」→「3点灯」→「4点灯」→「5点灯」→「6点灯」→「1点灯」→…

をきわめて高速に繰り返せば、見かけ上は全部のLEDが同時に点灯しているように見える筈である。

ということで、List 2にこの場合のSketchを示す。loop()の中が3重のforループになってしまい、ちょっとわかり難い事はご容赦いただきたい。これを起動すると、Movie02の様に見かけはだんだん点灯するLEDの数が増えているが、良く見ると次第にLEDの明るさが暗くなってゆくのがお分かりだろうか? 同時に点灯するLEDの数は1つだから、複数個に分散させれば次第に明るさが減ることは免れない。ためしに210fpsでスローモーション撮影したのがMovie03で、1~5個まではなんとか常時点灯に見えているが、6個点灯するとさすがにLED1~6で点滅を繰り返しているのが見えてしまう。

List 2:

int Table[6][2]={{4,2},{5,2},{6,2},
                 {4,3},{5,3},{6,3}};

void setup()
{
  int lpCnt;

  for(lpCnt=2; lpCnt<4; lpCnt++)  /* Pin 2~3が対象 */
  {
    pinMode(lpCnt, OUTPUT); /* 当該PinをDigital Outに設定 */
    digitalWrite(lpCnt, HIGH);  /* 初期値は消灯 */
  }

  for(lpCnt=4; lpCnt<7; lpCnt++)  /* Pin 4~6が対象 */
  {
    pinMode(lpCnt, OUTPUT); /* 当該PinをDigital Outに設定 */
    digitalWrite(lpCnt, LOW);  /* 初期値は消灯 */
  }
}

void loop()
{
  int lpCnt, lpCnt2, lpCnt3;

  for(lpCnt=1; lpCnt<7; lpCnt++)  /* 「同時」に点灯するLEDの数 */
  {
    for(lpCnt2=0; lpCnt2

動画
Movie02:

動画
Movie03:

List 2の仕組みを簡単に説明すれば、LED自体は1ms毎に点滅を繰り返している。で、トータルで500ms毎に点灯するLEDの数を変更しているので、1個なら500回、2個なら250回、3個なら166回、点滅を繰り返せばトータルで500msになるというわけだ。lpCntは点滅するLEDの数、lpCnt2は点滅の繰り返し数、lpCnt3は個別のLEDの制御をそれぞれ行っているというわけだ。

点滅が見えてしまう、というのは例えばdelay(1)(1ms待機)の代わりにdelayMicroseconds(100)(0.1ms待機)とかにして、その代わり繰り返し数を10倍に増やせばほとんど見えなくなるが、それはそれとして輝度が減ることそのものは原理上免れない。ただ、これはもう少し賢い方法がある、ということで以下次回。

(続く)