NOBのArduino日記!

NOBのArduino日記!

趣味は車・バイク・自転車・ラジコン・電子工作です。

4×4×5 LED CUBEの作製

イメージ 1

図1:とりあえず形になった状態

前回の3×3×3LedCube(LED27個)に引き続き、Arduino pro miniのピンが9本も余っていることから4×4×5LedCube(LED80個)の作製に挑戦してみました。

 

        1.材料

表1:購入品一覧
部品名 必要数 購入先 単価 費用
Arduino pro mini 5V版 1個 Chipworld 380円/個 380円
1kΩ抵抗 5本 マルツ 100円/100本 5円
10kΩ抵抗 1本 マルツ 100円/100本 1円
Cdsセル 5mmタイプ 1個 秋月電子 30円/個 30円
トグルスイッチ 1個 マルツ 100円/個 100円
ユニバーサル基板 Bタイプ 1枚 秋月電子 120円/枚 120円
LED光拡散キャップ3mm白 80個 秋月電子 200円/50個 320円
白色3mmLED 80個 マルツ 500円/100個 400円
電池ボックス 単3×4本 1個 秋月電子 80円/個 80円
単三乾電池eneloop 4本 amazon 1000円/4本 1000円
ICソケット(24P)600mil 1個 秋月電子 200円/10個 20円
M2.6×10なべ小ねじ 2本 ホームセンター 250円/10本 50円
合計 2506円
※その他ニッパー・ラジオペンチ・半田ごて・はんだ・はんだ吸取線・線材が必要です。

 

        2.回路図

表1材料を配線する前にfritzingを用いて回路図を作りましたので参考までに表面(図1)裏面(図2)を載せておきます。
イメージ 2

図2:表面

イメージ 3

図3:裏面

 

        3.作製

3.1LEDの足折り
LEDの足を図4の様に80個折ります。左に曲がっているのがっているのがカソードです。

 

イメージ 4

図4:LEDの足を曲げた状態

3.2治具の作製
LEDの頭を固定する治具を作ります。プラダンが有ったので図5の様に20.32mm(そこまで正確に出来ません8/10inchですのでインチ定規が欲しい・・・)の間隔で16個φ4mmの穴を開けた物を作ります。

 

イメージ 5

図5:LED半田付け用治具

3.3LEDの半田付け
図5の治具に図4で折り曲げたLEDを図6の様にセットし、図7の状態になるまで半田付けします。これを5セット作ったものが図8です。

 

イメージ 6

図6:LEDを治具にセット

イメージ 7

図7:16個半田付けした状態

イメージ 8

図8:5セット完成

3.4Arduinoの準備
前回記事よりArduinoに表面実装されている電源用の赤色LEDは待機電流を4.67mA増加させてしまい、取り外せば待機電流は0.33mAへと大幅に減少することから、図9の様に半田ごて2本を使ってLEDを取り外した状態(図10)にします。
また今回はArduino pro miniに備わっている全ての出力ピンをもれなく使用する為、図11の様にArduino基盤裏面にピンソケットを無理やり半田点けしました。(完成後A6,7はマイコンの構造上出力出来ない事が判明)

 

イメージ 9

図9:半田ごて二刀流!

イメージ 10

図10:LED取り外し後

イメージ 11

図11:Arduino裏面A4,5,6,7にピンソケット半田付け

3.5組立
図3回路図を元に図12の様に2箇所穴開け(φ3mmのドリル使用)と、錫めっき線と被覆線で配線をしておきます。
図12の基盤表に、用意したArduino(赤白の被覆線に、ピンヘッダを1/3位に切った物を半田付けし裏面ピンソケットに差し込む。その後ICソケットに差し込みます)・LED(被覆線を使って各LED段毎に基盤の該当するGNDへ空中配線をします。写真は配線前です)・ICソケット・CdS・抵抗を図4回路図に従って図13の様に半田付けします。
図13の基盤から出た緑の+と-の配線に電池ボックスを図14の様に半田点け後、φ2.6×10mmのねじとナットで基盤に図15の様に固定します。

 

イメージ 12

図12:基盤裏配線後

イメージ 13

図13:基盤表部品取り付け後

イメージ 14

図14:電池ボックス半田付け

イメージ 15

図15:電池ボックスねじ止め

3.6完成?状態
一日掛かってやっと形になりました。

 

イメージ 16

図16:表面

イメージ 17

図17:裏面

イメージ 18

図18:斜め1

イメージ 19

図19:斜め2

 

        4.スケッチ

Arduino制御用のスケッチはこのようになっています。
int BASE_0 = 5; //6変更前
int BASE_1 = 9; //7変更前
int BASE_2 = 8; //8変更前
int BASE_3 = 7; //9変更前
int BASE_4 = 6; //5変更前
int LED_0  = 4;
int LED_1  = 3;
int LED_2  = 2;
int LED_3  = 20; //A6
int LED_4  = 12;
int LED_5  = 11;
int LED_6  = 10;
int LED_7  = 21; //A7
int LED_8  = 16; //A2(A3はcdsの電圧読み取り)
int LED_9  = 14; //A0
int LED_10  = 13;
int LED_11  = 18; //A4
int LED_12  = 1; //Tx
int LED_13  = 0; //Rx
int LED_14  = 15; //A1
int LED_15  = 19; //A5
int BASE_LIST[5] = {BASE_0,BASE_1,BASE_2,BASE_3,BASE_4};
int LED_LIST[16] = {LED_0,LED_1,LED_2,LED_3,LED_4,LED_5,LED_6,LED_7,LED_8,LED_9,LED_10,LED_11,LED_12,LED_13,LED_14,LED_15};
int val =0;
// LEDキューブの状態.HIGH or LOWを格納
int led_state[5][4][4];
int LED_NUM = 80;

float COUNT_MAX = 30;//66行目で変化
int count = 0;

void setup(){
    // 各pinのIN/OUT設定
    pinMode(BASE_0,OUTPUT);
    pinMode(BASE_1,OUTPUT);
    pinMode(BASE_2,OUTPUT);
    pinMode(BASE_3,OUTPUT);
    pinMode(BASE_4,OUTPUT);
    pinMode(LED_0 ,OUTPUT);
    pinMode(LED_1 ,OUTPUT);
    pinMode(LED_2 ,OUTPUT);
    pinMode(LED_3 ,OUTPUT);
    pinMode(LED_4 ,OUTPUT);
    pinMode(LED_5 ,OUTPUT);
    pinMode(LED_6 ,OUTPUT);
    pinMode(LED_7 ,OUTPUT);
    pinMode(LED_8 ,OUTPUT);
    pinMode(LED_9 ,OUTPUT);
    pinMode(LED_10 ,OUTPUT);
    pinMode(LED_11 ,OUTPUT);
    pinMode(LED_12 ,OUTPUT);
    pinMode(LED_13 ,OUTPUT);
    pinMode(LED_14 ,OUTPUT);
    pinMode(LED_15 ,OUTPUT);

    // LEDキューブの状態初期化
    int i=0,j=0,k=0;
    for(i=0; i<5; i++){
        for(j=0; j<4; j++){
            for(k=0; k<4; k++){
                led_state[i][j][k] = LOW;
            }
        }
    }
    randomSeed(analogRead(0));
}

// openFrameworks風にループ内を分割
void loop(){
    update();
    action();
}

// 状態の更新
void update(){
    if(count >= COUNT_MAX){
        COUNT_MAX=random(10,50);
        if (analogRead(3)>500){ //壱番は500、弐番は670、参番は500
            // LEDキューブの状態初期化
            int i=0,j=0,k=0;
            for(i=0; i<5; i++){
                for(j=0; j<4; j++){
                    for(k=0; k<4; k++){
                        led_state[i][j][k] = LOW;
                    }
                }
            }
            randomSeed(analogRead(3));
            action();
            delayWDT(9);
        }else{
        // ランダムに状態変化
        led_toggle(random(LED_NUM));
        count = 0;
        }
    } else {
        count++;
    }
 }

// 状態の反映
void action(){
    blink_cube();
}

// LEDキューブをダイナミック点灯
void blink_cube(){
    int i=0,j=0,k=0;
    for(i=0; i<5; i++){
        // i番目の段以外はHIGH
        digitalWrite(BASE_0,HIGH);
        digitalWrite(BASE_1,HIGH);
        digitalWrite(BASE_2,HIGH);
        digitalWrite(BASE_3,HIGH);
        digitalWrite(BASE_4,HIGH);
        digitalWrite(BASE_LIST[i],LOW);
        
        // 同一段内の9つのLEDを制御
        for(j=0; j<4; j++){
            for(k=0; k<4; k++){
                digitalWrite(LED_LIST[j+k*4], led_state[i][j][k]);
            }
        }
        // 気持ち程度delay.なくてもok
        delay(1);
    }
}

// 指定番号のLEDの状態をトグル
void led_toggle(int num){
    int i,j,k;
    i = num / 16;  // 元「i = num / 9」要検討
    j = (num % 16) / 4;  //元「(num % 9) / 3」要検討
    k = num % 4;  //元「num % 3」要検討
    if(led_state[i][j][k] == HIGH){
        led_state[i][j][k] = LOW;
    } else {
        led_state[i][j][k] = HIGH;
    }
}

//delayWDTここから
#include <avr/sleep.h>
#include <avr/wdt.h>
void delayWDT(unsigned long t) {        // パワーダウンモードでdelayを実行
  delayWDT_setup(t);                    // ウォッチドッグタイマー割り込み条件設定
  ADCSRA &= ~(1 << ADEN);               // ADENビットをクリアしてADCを停止(120μA節約)
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // パワーダウンモード
  sleep_enable();
  sleep_mode();                         // ここでスリープに入る
  sleep_disable();                      // WDTがタイムアップでここから動作再開 
  ADCSRA |= (1 << ADEN);                // ADCの電源をON (|=が!=になっていたバグを修正2014/11/17)
}
void delayWDT_setup(unsigned int ii) {  // ウォッチドッグタイマーをセット。
  // 引数はWDTCSRにセットするWDP0-WDP3の値。設定値と動作時間は概略下記
  // 0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms
  // 6=1sec, 7=2sec, 8=4sec, 9=8sec
  byte bb;
  if (ii > 9 ){                         // 変な値を排除
    ii = 9;
  }
  bb =ii & 7;                           // 下位3ビットをbbに
  if (ii > 7){                          // 7以上(7.8,9)なら
    bb |= (1 << 5);                     // bbの5ビット目(WDP3)を1にする
  }
  bb |= ( 1 << WDCE );
  MCUSR &= ~(1 << WDRF);                // MCU Status Reg. Watchdog Reset Flag ->0
  // start timed sequence
  WDTCSR |= (1 << WDCE) | (1<<WDE);     // ウォッチドッグ変更許可(WDCEは4サイクルで自動リセット)
  // set new watchdog timeout value
  WDTCSR = bb;                          // 制御レジスタを設定
  WDTCSR |= _BV(WDIE);
} 
ISR(WDT_vect) {                         // WDTがタイムアップした時に実行される処理
  //  wdt_cycle++;                        // 必要ならコメントアウトを外す
}
//delayWDTここまで

 

        5.動作確認

Arduinoに4.スケッチを書き込み、動作確認した結果、正常に動作を確・・・認・・・出来ませんでした。

 

イメージ 1

図20:一応動作?

ArduinoのD13からは弱々しく(ほぼ見えない)出力されており、A6,7からは出力されていない御様子。
原因としてはArduinoのD13は表面実装LEDによる電圧降下で点灯せず(前回D13は避けていたのに忘れていました。電源LEDの様に除去せねば、しかし見たところ難易度が高い。OUTではなくGNDにすれば・・・いける?)、A6,A7についてはAnalogReadだけの機能しかなかった為、DigitalWriteとしては機能しないそうです。
詳細はhttp://www.atmel.com/images/doc8161.pdfの1.1.9に書いてありました。

 

〇原文
ADC7:6(TQFP and QFN/MLF Package Only)In the TQFP and QFN/MLF package, ADC7:6 serve as analog inputs to the A/D converter.These pins are powered from the analog supply and serve as 10-bit ADC channels.

 

Google先生翻訳
ADC76(TQFPとQFN/MLFパッケージのみ)TQFPとQFN/MLFパッケージでは、ADC7:6は、A/Dコンバータのアナログ入力として機能します。これらのピンはアナログ電源から給電され、10ビットのADCチャネルとして機能しています。

 

〇自己理解
A0~5はAnalogReadもDigitalWriteも可能だが、A6,7はAnalogReadのみ可。

 

        6.まとめ

D13についてはGNDとして機能させれば行けるのではないかと楽観、D6についてはD3(CdSのAnalogReadに使用)と入れ替えれば行けそう。D7についてはArduino単体で行けそうにありません・・・(泣)。しばらく解決策を考えてみます。(そのまま放置になりそう)
 
イメージ 1 イメージ 3
励みになりますのでよければクリック下さい(^o^)/

↩【NOBのArduino日記!】目次に戻る