2011年3月23日水曜日

小さなイルミネーション

Arduino作品第一号です
心休まるテーマを・・・と思い、小さなイルミネーションを作りました

/* 概要 */
ツリー状に取り付けたLED(今回は15個)を、さまざまなパターンで点灯します

/* ツリー本体 */
1mmのメッキ線で幹1本+枝7本のツリーを作ります
そのツリーに、枝2個・幹頂1個:計15個のLED(カソード側)を半田付けします
よってツリー本体がGndとなります

/* 回路図 */
Arduinoのメインチップ(ATmega168p)をスタンドアロンで使います
それ以外は、変わったところはありません

※LTSpiceにArduinoのシンボルを登録して作成しました

/* ソース(スケッチ)リスト */
これも特に変わったところはありません
しいて工夫した点と言えば以下です

・ポート番号を配列にして変更を容易にする
・グローバル変数で経過時間を監視・処理
・random()関数を利用してランダム点灯パターンを実装


// グローバル変数
int iLEDPORT[] = {2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 18, 19};
unsigned long lgSTARTMILSEC = 0;

// 各関数

////////////////////////////////////////////////////////////////////////
// 開始時間をグローバル変数に保存する
////////////////////////////////////////////////////////////////////////
void StartMilSecCount()
{
  lgSTARTMILSEC = millis();
}

////////////////////////////////////////////////////////////////////////
// 指定ミリ秒経過したかチェックする
////////////////////////////////////////////////////////////////////////
boolean IsElaspedMilSecOver(unsigned long lgCountMilSec)
{
    unsigned long lgPresentMilSec = millis();
    unsigned long lgElapsedMilSec = lgPresentMilSec - lgSTARTMILSEC;
    if(lgElapsedMilSec > lgCountMilSec)
      return true;
     
    return false;
}

////////////////////////////////////////////////////////////////////////
// LED 全点滅パターン
////////////////////////////////////////////////////////////////////////
void ILUMI_AllBlink(unsigned int iOnTime, unsigned int iOffTime, unsigned long lgInterval)
{
  StartMilSecCount();
 
  for( ; ; ){
   
    for(int n = 0; n < 15; n++){
      digitalWrite(iLEDPORT[n], HIGH);
    }
    delay(iOnTime);
    for(int n = 0; n < 15; n++){
      digitalWrite(iLEDPORT[n], LOW);
    }
    delay(iOffTime);
 
    if(IsElaspedMilSecOver(lgInterval))
      break;
  } 
}

////////////////////////////////////////////////////////////////////////
// LED 交互点滅パターン
////////////////////////////////////////////////////////////////////////
void ILUMI_HalfBlink(unsigned int iOnTime, unsigned int iOffTime, unsigned long lgInterval)
{
  StartMilSecCount();
 
  for( ; ; ){
   
    for(int n = 0; n < 15; n++){
      digitalWrite(iLEDPORT[n], 0x0001 & ~bitRead(n, 0));
    }
    delay(iOnTime);
    for(int n = 0; n < 15; n++){
      digitalWrite(iLEDPORT[n], bitRead(n, 0));
    }
    delay(iOffTime);
    for(int n = 0; n < 15; n++){
      digitalWrite(iLEDPORT[n], LOW);
    }
 
    if(IsElaspedMilSecOver(lgInterval))
      break;
  } 
}

////////////////////////////////////////////////////////////////////////
// LED シーケンス点灯パターン(1)
////////////////////////////////////////////////////////////////////////
void ILUMI_Sequence1(unsigned int iOnTime, unsigned int iOffTime, unsigned long lgInterval)
{
  StartMilSecCount();


  for(int n = 0; ; ){
    digitalWrite(iLEDPORT[n], HIGH);
    delay(iOnTime);
    digitalWrite(iLEDPORT[n], LOW);
    delay(iOffTime);
   
    if(++n >= 15){
      if(IsElaspedMilSecOver(lgInterval))
        break;
      else
        n = 0;
    }
  }
}

////////////////////////////////////////////////////////////////////////
// LED シーケンス点灯パターン(2)
////////////////////////////////////////////////////////////////////////
void ILUMI_Sequence2(unsigned int iOnTime, unsigned int iOffTime, unsigned long lgInterval)
{
  StartMilSecCount();
 
  int j = 1;
 
  for(int n = 0; ; ){
   
    digitalWrite(iLEDPORT[n], HIGH);
    digitalWrite(iLEDPORT[j], HIGH);
    delay(iOnTime);
    digitalWrite(iLEDPORT[n], LOW);
    digitalWrite(iLEDPORT[j], LOW);
    delay(iOffTime);
    if(++j >= 15) j = 0;
 
    if(++n >= 15){
      if(IsElaspedMilSecOver(lgInterval))
        break;
      else
        n = 0;
    }
  }
}

////////////////////////////////////////////////////////////////////////
// LED シーケンス点灯パターン(3)
////////////////////////////////////////////////////////////////////////
void ILUMI_Sequence3(unsigned int iOnTime, unsigned int iOffTime, unsigned long lgInterval)
{
  StartMilSecCount();
 
  int j = 2;
  int k = 4;
  int m = 6;
 
  for(int n = 0; ; ){
   
    digitalWrite(iLEDPORT[n], HIGH);
    digitalWrite(iLEDPORT[j], HIGH);
    digitalWrite(iLEDPORT[k], HIGH);
    digitalWrite(iLEDPORT[m], HIGH);
    delay(iOnTime);

    digitalWrite(iLEDPORT[n], LOW);
    digitalWrite(iLEDPORT[j], LOW);
    digitalWrite(iLEDPORT[k], LOW);
    digitalWrite(iLEDPORT[m], LOW);
    delay(iOffTime);
   
    if(++m >= 15) m = 0;
    if(++k >= 15) k = 0;
    if(++j >= 15) j = 0;
 
    if(++n >= 15){
      if(IsElaspedMilSecOver(lgInterval))
        break;
      else
        n = 0;
    }
  }
}

////////////////////////////////////////////////////////////////////////
// LED ランダム点灯パターン
////////////////////////////////////////////////////////////////////////
void ILUMI_Random(unsigned int iOnTime, unsigned int iOffTime, unsigned long lgInterval)
{
  StartMilSecCount();
 
  for( ; ; ){
   
    int n = random(0, 15);
    digitalWrite(iLEDPORT[n], HIGH);
    delay(iOnTime);
    digitalWrite(iLEDPORT[n], LOW);
    delay(iOffTime);
  
    if(++n >= 15){
      if(IsElaspedMilSecOver(lgInterval))
        break;
      else
        n = 0;
    }
  } 
}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// run once, when the sketch starts
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
void setup()
{
  for(int n = 0; n < 15; n++){
    pinMode(iLEDPORT[n], OUTPUT);
  }
 
  for(int n = 0; n < 15; n++){
    digitalWrite(iLEDPORT[n], HIGH);
  }
 
  delay(2500);
 
  for(int n = 0; n < 15; n++){
    digitalWrite(iLEDPORT[n], LOW);
  }
 
  //Serial.begin(9600);
  delay(1500);
}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// run over and over again
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
void loop()
{
   unsigned long lgInterval = 40000;
   unsigned long lgDelay = 1200;

  // シーケンスパターン(2)
  ILUMI_Sequence2(40, 25, lgInterval);
  delay(lgDelay); 

  // 交互点滅パターン
  ILUMI_HalfBlink(750, 750, lgInterval);
  delay(lgDelay);

  // シーケンスパターン(1)
  ILUMI_Sequence1(20, 5, lgInterval);
  delay(lgDelay);

  // シーケンスパターン(3)
  ILUMI_Sequence3(500, 20, lgInterval);
  delay(lgDelay);

  // ランダムパターン
  ILUMI_Random(15, 10, lgInterval);
  delay(lgDelay);
 
  // 全点滅パターン
  ILUMI_AllBlink(800, 700, lgInterval);
  delay(lgDelay);
 
}


/* 動作例 */
点灯時間を10秒程度に編集しています
手ぶれと、少し暗いのをご了承ください・・・



/* 所感 */
メッキ線は、細いものを撚って作ったほうが良いかも知れません
⇒ 単線だと、熱が伝わり過ぎて先に付けた枝が溶け外れてしまいます これ閉口しました…

15個ではちょっと寂しいかもと思いましたが、プログラムの設定で美しく光ってくれました

Arduinoを使えば、作りたいテーマが容易に実現できることを実感しました

以上です