●Arduinoでナイトライダーみたいなライトを作成する

ArduinoでLEDがチカチカ往復するイルミネーションを作成します。
ちょっと性能の無駄遣いの気がしますが、Arduino開発環境が素晴らしいので簡単に作成できます。

まずは、回路図を適当に作成します。
デジタルピンのすべてにLEDを取り付けてGNDに接続しました。
速度調整のために可変抵抗を取り付けてアナログピン A0 に接続しました。

一度に複数のLEDが点灯するわけではないためLEDの電流制限抵抗はGND側に取り付けて1本のみにしました。
調整用の可変抵抗を電源間に接続しています、これにより電圧が分圧されますのでアナログピンのA/D変換で値を読み取り速度を調整します。

実際に作成した所


裏面


▼書き込んだプログラム

Arduinoには次のように書き込みました。
void setup() {
  for(int i=2;i<=13;i++){
      pinMode(i, OUTPUT);
  }
}

int count,mode;
void loop() {
  for(int i=2;i<=13;i++){
    digitalWrite(i,0);
  }
  if(mode){
    count--;
  }else{
    count++;
  }
  
  if(count<2){
    count=2;
    mode=0;
  }

  if(count>13){
    count=13;
    mode=1;
  }
  digitalWrite(count,1);
  delay(analogRead( A0 )/5);
}

動作させた所です、可変抵抗を回すと速度が速くなったり遅くなったりします。



■光が尾を引くようにする

ぱっと光らせてぱっと消えるだけではかっこよくないので光が徐々に暗くなって尾を引くようにしたいと思います。
そのために、LED自体を高速で点滅させることにより目の錯覚で薄暗く見える状態を作る必要があります。
まずは実験として、タイマーを使い明るい状態から暗い状態を作成します。
タイマーの使い方はこちらまで。
#include <MsTimer2.h>
int i;
void timer() {
  i++;
  if(i>10) i=0;
  if(i>0) digitalWrite(2,1); else  digitalWrite(2,0);
  if(i>1) digitalWrite(3,1); else  digitalWrite(3,0);
  if(i>2) digitalWrite(4,1); else  digitalWrite(4,0);
  if(i>3) digitalWrite(5,1); else  digitalWrite(5,0);
  if(i>4) digitalWrite(6,1); else  digitalWrite(6,0);
  if(i>5) digitalWrite(7,1); else  digitalWrite(7,0);
  if(i>6) digitalWrite(8,1); else  digitalWrite(8,0);
  if(i>7) digitalWrite(9,1); else  digitalWrite(9,0);
  if(i>8) digitalWrite(10,1); else  digitalWrite(10,0);
  if(i>9) digitalWrite(11,1); else  digitalWrite(11,0);
}

void setup() {
  for(int i=2;i<=13;i++){
      pinMode(i, OUTPUT);
  }
  MsTimer2::set(1, timer);
  MsTimer2::start();
}

void loop() {
}

このプログラムでは、1ミリ秒毎に動作するタイマーにより瞬時にLEDを点滅させ、点滅時間の長さにより仮想的に明暗を作成しています。
実行させると明るい状態から暗い状態までが作成できました。



明るい状態から暗い状態を作成できることがわかりましたので後は適当に作成するのみです。
このようなプログラムを作成しました。
#include <MsTimer2.h>

unsigned int ar[14]={10,10,10,10,10,10,10,10,10,10,10,10,10,10};

void timer() {
  static unsigned int count;
  count++;
  if(count>10) count=0;
  
  for(int i=2;i<=13;i++){
    if(count>ar[i]) digitalWrite(i,1); else  digitalWrite(i,0);
  }
}

void setup() {
  for(int i=2;i<=13;i++){
      pinMode(i, OUTPUT);
  }
  MsTimer2::set(1, timer);
  MsTimer2::start();
}

int count,mode;
void loop() {
  for(int i=0;i<=13;i++){
    ar[i]++;
  }

  if(mode){
    count--;
  }else{
    count++;
  }
  
  if(count<2){
    count=2;
    mode=0;
  }

  if(count>13){
    count=13;
    mode=1;
  }
  ar[count]=0;
  delay(analogRead( A0 )/5);
}

実行するとこのような動作をします。
光が尾を引いており、かなりカッコよくなった気がしました。
ゆっくり動かしても美しく見えます。



■色々なパターンで光るようにする

単純なパターンだけだと面白くないのでパターンを切り替えられるようにしてみます。
まずはアナログピン1番とGND間に押しボタンスイッチを取り付けました。


次にこのようなプログラムを書き込みました。
スイッチを押すと、 全点滅→右に流れる→左に流れる→往復 の順に切り替わります。
#include <MsTimer2.h>
#include <EEPROM.h>

//点灯状態を保持する変数 0が明るく数が大きくなるにつれ暗くなる
unsigned int ar[14] = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10};

//タイマーでLEDを薄暗く表示する処理
void timer() {
  static unsigned int count;
  count++;
  if (count > 10) count = 0;

  for (int i = 2; i <= 13; i++) {
    if (count > ar[i]) digitalWrite(i, 1); else  digitalWrite(i, 0);
  }
}

unsigned int count, mode, pat;
void setup() {
  //前回の状態を復元
  EEPROM.get(0x00, pat);
  if (pat > 3) pat = 0;
  pinMode(A1, INPUT_PULLUP);
  for (int i = 2; i <= 13; i++) {
    pinMode(i, OUTPUT);
  }
  MsTimer2::set(1, timer);
  MsTimer2::start();
}

void loop() {
  //全LEDの明るさを暗くする
  for (int i = 0; i <= 13; i++) {
    ar[i]++;
  }
  //右に流れるか左に流れるかを決める
  if (mode) {
    count--;
  } else {
    count++;
  }
  //表示パターンの切り替え
  if (0 == pat) {
    pattern0();
  } else if (1 == pat) {
    pattern1();
  } else if (2 == pat) {
    pattern2();
  } else {
    pattern3();
  }
  //指定されたLEDを明るさ最大にする
  ar[count] = 0;

  //待ち時間の間にボタンをON/OFFチェックをする
  unsigned long pos = millis() + analogRead( A0 ) / 5;
  while (millis() < pos) {
    if (chatteringCut_pullupPin(A1)) {
      if (pat > 2) {
        pat = 0;
      } else {
        pat++;
      }
      //点灯パターンが変更された場合には保存する
      EEPROM.put(0x00, pat);
    }
  }
}

//全点滅パターン
void pattern0() {
  count = 0;
  static int t;
  if (t < 10) {
    for (int i = 2; i <= 13; i++) {
      ar[i] = 0;
    }

  } else {
    for (int i = 2; i <= 13; i++) {
      ar[i] = 10;
    }
  }
  if (t > 20) {
    t = 0;
  } else {
    t++;
  }
}

//右に流れるパターン
void pattern1() {
  if (count < 2) {
    count = 2;
    mode = 0;
  }
  if (count > 13) {
    count = 2;
    mode = 0;
  }
}

//左に流れるパターン
void pattern2() {
  if (count < 2) {
    count = 13;
    mode = 1;
  }
  if (count > 13) {
    count = 13;
    mode = 1;
  }
}

//往復パターン
void pattern3() {
  if (count < 2) {
    count = 2;
    mode = 0;
  }
  if (count > 13) {
    count = 13;
    mode = 1;
  }
}

//ボタンのチャタリング対策
unsigned int chatteringCut_pullupPin(int pinNo) {
  unsigned int i = 0;
  while (!digitalRead(pinNo)) {
    i++;
    delay(1);
  }
  //1111111111000000 でアンドを取り下位ビットをマスクする
  //つまりループが63を超えるまで0しか返さない
  return i & (~(unsigned int)0x3F);
}

なんだか、100均でよくあるおもちゃの点滅ライトを作成してしまった気分になります(笑)
元々全部のLEDを点灯させるのは想定していなかったため、全点滅は暗くなりますが、 明るくするのならLEDの電流制限抵抗をLED一つ一つに取り付ける必要があります。


▲トップページ > マイコンなど