メンズワキガ対策専門ブランドD AGICA【ディーアジカ】

 

■電源ユニットに端子板を付ける

余っていたパソコンの電源ユニットを処分しようとしたんだけど、ふと、これ電源装置として使えるよなぁと思ったわけ。で調べてみました。

 

出力は +12V が二系統、+5V、+3.3V が各一系統と -12V 一系統。その他にスタンバイ用の +5VSB があります。

+5VSB は電源 ON で常に 5V が出力されていますが、他は出力していません。PS_ON という信号線を LOW に落とすと冷却ファンが回りだし、すべての出力が ON 。出力が ON になると PWR_OK が HIGH になります。

その他に 3.3Vsence というラインがありますが、これは +3.3V の出力検出用で、マザーボードに挿入するメインコネクタで +3.3V 出力に繋がっていました。

 

参考:ニプロン 製品情報 電源事典 Q&A Q. ATX電源_EPSのピンアサインについて教えて下さい。

 

 

電源ユニットからは、マザーボードや周辺機器を接続するために、さまざまな形のコネクタが付いたハーネスがたくさん出ています。これらを取り外して、出力と制御用に端子板を取り付けることにします。


電源ユニット

 

 

カバーを開けると、基板の出力部周辺はこんな感じ。同じ場所から何本もの電線が束になって出ていることがわかります。


出力線のようす

 

 

基板をひっくり返してみるとこんな感じ。大量のハンダが盛られていて、外し甲斐がありそうです (^_^;)


基板裏面のようす

 

 

電線を取り外しましたが、けっこう大変な作業でした。ハンダを取るとき、周辺の抵抗器などのハンダまで溶かしたり、パターンをショートしたりしないように注意が必要です。

信号線など一本だけ出ているところはそのまま残しています。


電線を取り外した基板

 

 

新たに出力線をハンダ付けし、ケースに戻します。


出力線を取り付け

 

 

ケースに端子板取付用の穴あけをします。ボール盤があればもっときれいにあけられるんですけどねぇ (言い訳 ^_^;)


ケースに端子板用の穴あけ

 

 

端子板を取り付け、出力線をハンダ付けして組み立てたら、完成です。


完成

 

 

端子板は以下のようになっています。3.3Vsence は No.4 端子に接続してあります。

 

No. 1 2 3 4 5 6 7 8 9 10
出力 12V(1) 12V(2) 5V 3.3V GND GND PS_ON 5VSB PWR_OK -12V

 

今回は 10pin の端子板を取り付けたのですが、これだと GND 端子が二つしか取れません。GND 端子は余裕があったほうが使いやすいので、12pin の端子板にしたほうがよかったかなと思っています。あと、端子板の表示をつけないといけませんね。

 


■ArduinoでFizzBuzzしてみた

俺はプログラミングもほとんど初心者に等しいので、そっちの方をもう少し勉強しようと思ってます。

Arduino スケッチは C 言語をベースにしているということなので、C 言語も合わせてやっていきましょう。てなことを考えながら、とりあえず何か書いてみるなら FizzBuzz かなとか (^_^;)

 

FizzBuzz とは、まぁ誰でも知っていると思いますけど、50 まで数えて 3 の倍数のときアホになるというやつです。… じゃぁなくて、100 までカウントして 3 の倍数のとき Fizz 、5 の倍数のとき Buzz、さらに 3 と 5 の倍数のときは FizzBuzz と表示させるといったプログラムのことです。こいつを Arduino でやってみます。

ちょうど 7セグメント LED を使ってみていたので、スタートボタンを押したら 0 から 99 までカウント表示させることにしましょう。3 の倍数のときは FZ 、5 の倍数では BZ 、3 と 5 の倍数のときは FB と表示させることにします。

 

回路図は以下です。特段変わったところはありません。

Arduino の D9 にタクトスイッチをつなぎ、これを ON するとカウントをスタートさせます。

アノードコモンの 7 セグメント LED 表示器が 2個手元にありますので、これをシフトレジスタ SN74LS164 で表示させます。デジットドライブはこれも手持ちの 2N3906 を使用しています。2SA1015 とかでもいいですね。FET でもかまいません。持っているものを適当に使いましょう。でも Arduino で直接駆動するのはちょっと無理があります。

シフトレジスタと LED の接続は、7ビットのデータを LSBFIRST (最下位ビットから送出) させるつもりなので、Qa の出力を未接続にしています。このあたりはプログラムと整合させないとうまく表示できませんので注意します。

 


DizzBuzz_回路図

 

 

スケッチのフローチャートです。

スイッチの ON を検出して 0 から 99 までカウントします。それを 7 セグメント LED で 2 桁表示させます。十の位が 0 のときは表示しないようにしています。2 桁を 1 ミリ秒ずつ表示して 300 回繰り返すので、約 600 ミリ秒ごとにカウントしていくことになります。

その値の倍数かどうかは剰余が 0 かどうかを判断します。3 と 5 の倍数ということは 15 の倍数ということです。ここが FizzBuzz の肝ですね。それぞれの判定結果に従って、表示する値を変えています。

ん〜、なんかもっとすっきりできそうな気がするけど、いまの俺のレベルではこんなもんでしょ (^_^;)

 


FizzBuzz_フローチャート

 

 

スケッチです。

じつは、関数の引数とか戻り値とか初めて使ってみたんですよ (^_^;)

 

// Fizz Buzz on Arduino  2019.06.16 meyon

 

/*  スイッチを押下すると 0 から 99 までカウントする。
    3 の倍数のとき FZ 、5 の倍数のとき BZ 、
    15 の倍数のとき FB と表示させる。
*/

 

const byte segmentData[14] = {
  B1111110, // 0
  B0110000, // 1
  B1101101, // 2
  B1111001, // 3
  B0110011, // 4
  B1011011, // 5
  B1011111, // 6
  B1110000, // 7
  B1111111, // 8
  B1111011, // 9
  B1000111, // F
  B0011111, // B
  B1101100, // Z
  B0000000  // blank
};

 

const int startPin = 9;
const int driverPin[2] = {10, 11};
const int clockPin = 12;
const int dataPin = 13;

 


int judgeNumber(int value) {
  int result;
  if(value == 0) {
    result = 0;
  } else if(value % 15 == 0) {
    result = 15;
  } else if(value % 5 == 0) {
    result = 5;
  } else if(value % 3 == 0) {
    result = 3;
  } else {
    result = value;
  }
  return result;
}

 


void displayNumber(int value) {
  int digit[2];
  if(value == 15) {
    digit[0] = 11;        // B
    digit[1] = 10;        // F
  } else if(value == 5) {
    digit[0] = 12;        // Z
    digit[1] = 11;        // B
  } else if(value == 3) {
    digit[0] = 12;        // Z
    digit[1] = 10;        // F
  } else {
    digit[0] = value % 10;
    if(value / 10 == 0) {
      digit[1] = 13;      // 10 digit is blank
    } else {
      digit[1] = value / 10;
    }
  }

 

  int j=0;
  while(++j < 300) {      // Display cycle
    for(int i=0; i<2; i++) {
      shiftOut(dataPin, clockPin, LSBFIRST, ~segmentData[digit[i]]);
      digitalWrite(driverPin[i], LOW);
      delay(1);
      digitalWrite(driverPin[i], HIGH);
    }
  }
  return;
}

 

 

void setup() {
  pinMode(startPin, INPUT);
  pinMode(driverPin[0], OUTPUT);
  pinMode(driverPin[1], OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  digitalWrite(driverPin[0], HIGH);
  digitalWrite(driverPin[1], HIGH);
}

 


void loop() {
  if(digitalRead(startPin) == LOW) {
    for(int i=0; i<100; i++) {
      int value = judgeNumber(i);
      displayNumber(value);
    }
  }
}

 

 

ついでにブレッドボードです。

7 セグメント LED がピンが左右についている品物なので 2桁並べて置けません。ご愛嬌です。

回路図にはありませんが、IC の電源には 0.1μF のコンデンサをつけてます。またブレッドボードの電源ラインには 10μF 程度の電解コンデンサを置くようにしています。
 


FizzBuzz_ブレッドボード

 

 

電源が写真にはありませんが、12V の AC アダプタの出力から 3 端子レギュレータで 5V を作っています。Arduino の電源は 12V を Vin に供給しています。ただ、USB ケーブルを挿したまま AC アダプタを切っちゃうと Vin から 5V が逆流してしまうので、12V ラインにダイオードを入れて阻止しています。まぁ小ネタですけど。

 


■Arduino Nano 互換機を買ってみた

Amazon で「HiLetgo® 3個セット Mini USB Nano V3.0 ATmega328P CH340G 5V 16M マイクロコントローラーボード Arduinoと互換」を購入しました。結果、何の問題もなく期待通り動作してくれました。

 

廉価な互換機ということなので、Uno との違いもさることながら、正規品との違いも確認しておきたいとググってみたのですが、どうもなにやら良い印象がない (^_^;) 

レビューでも数個に 1個は動作しないとか、USB シリアル変換チップ CH340 用のドライバをインストールしないといけないとか、その CH340 が偽物であるとか、Old Bootloader を選択しないと書き込みできないとか… 使ってみたというサイトを見ても同様の情報が多く、また中国からの配送なので時間がかかるとか、まぁ導入時は多少苦労するかなと覚悟をしていました。

 

が、そんな懸念は一切無用。Ubuntu 18.04.2 LTS のパソコンで、次の設定で動作しています。

 

ボード:Arduino Nano

プロセッサ:ATmega328P

シリアルポート:/dev/ttyUSB0

 

CH340 のドライバのインストールは不要です。ブートローダも Old ではないほうで良いので、新しいものになっているようです。ちなみに CH340 の真贋の判断基準となるとか言われているマークは底の平らな大きな丸でした。見た目も気になるようなところは何もなく、粗悪な安物といった感じはありません。


Arduino nano 互換機

 

USB ケーブル (A to miniB) とその他  1点とともに、注文から約 24時間で到着しました。さすが Amazon's Choice です。寸法はわかっていましたが、実物は思っていた以上に小さく感じました。A コネクタと変わらないですね。

 

まず、3個すべてに Blink を書き込んで正常に動作することを確認しました。

付属のピンヘッダを取り付けて、以前作った 3x3x3 LED Cube につないでみました。これも全く問題なく動作しています。このサイズの基板で実装できそうですね。


3x3x3 LED Cube with 互換機

 

 


■ファンクションボタンの検出

最近よく見かける、上下左右にメニューボタン、中央に決定ボタンがあるような、なんていうのか名前を知らないのですが、ファンクションボタンを作ってみました。

 

タクトスイッチ 6個を「up」「down」「right」「left」「set」「reset」のファンクションボタンとし、どのボタンが押されたかを検出します。今回の肝は電圧分圧方式でのボタン検出で、押したボタンによって入力電圧が変化するという仕組み。ググると考え方や抵抗値の計算方法が出てきますので参考にしてください。

二つ以上のボタンを同時に押した場合は優先順位がありますので、今回は「reset」を最優先のボタンとして並べてみました。

計算上の分電圧と実際の入力値は異なりますので、Arduino の入力値を実測してボタン判断のしきい値を決めています。

どのボタンが押されたかを表示するために、手元にあった 7 セグメント LED (アノードコモン) をシフトレジスタで表示させています。シフトレジスタは前に LED キューブで使っていた SN74LS164 です。こいつはストレージレジスタがありませんので、ドライブ用にトランジスタ 2N3906 を付けました。これによりデータ送信中は LED を表示させないようにしています。セグメントの電流は 7mA 程度、2N3906 は最大コレクタ電流 200mA ですので十分使えます。

 

回路図です。


function-switch 回路図

 

ブレッドボードはこんな感じ。実際はこれを時計方向に 90° 回して実験していますので、右上のタクトスイッチは上下左右に 4 個のボタンと左下に reset 、右下に set という配置になってます。まぁどんな並びでも関係ないんですけど (^_^;)  押したボタンに応じて数字が表示されるという単純なものです。


function-switch ブレッドボード

 

 

フローチャートとスケッチです。ボタン判断のしきい値がフローチャートとスケッチで異なっていますが、最終的にはスケッチの値にしています。

 


画像キャプション

 

// function-switch 2019.06.06 meyon

 

byte segmentData[7] = {
  B1111110, // 0
  B0110000, // 1
  B1101101, // 2
  B1111001, // 3
  B0110011, // 4
  B1011011, // 5
  B1011111  // 6
};

int driverPin = 11;
int clockPin = 12;
int dataPin = 13;
int displyNumber = 0;


int buttonPressed() {
  int inputVoltage = analogRead(A0);

  if (inputVoltage > 947) {
    return 0; //off
  } else if (inputVoltage > 779) {
    return 1; //set
  } else if (inputVoltage > 602) {
    return 3; //up
  } else if (inputVoltage > 436) {
    return 5; //right
  } else if (inputVoltage > 268) {
    return 4; //down
  } else if (inputVoltage > 90) {
    return 6; //left
  } else {
    return 2; //reset
  }
}


void displyButtonNo() {
  digitalWrite (driverPin, HIGH);
  shiftOut(dataPin, clockPin, MSBFIRST, ~segmentData[displyNumber]);
  digitalWrite (driverPin, LOW);
  return;
}


void setup() {
  pinMode (driverPin, OUTPUT);
  pinMode (clockPin, OUTPUT);
  pinMode (dataPin, OUTPUT);

  Serial.begin(9600);
}

 

void loop() {
  Serial.println(analogRead(A0));
  
  if (buttonPressed() != 0) {
    displyNumber = buttonPressed();
  }
  displyButtonNo();
}

 

例によって入力値の確認のためにシリアル出力を使ってます。

シフトレジスタもドライブ用トランジスタも LOW で点灯になります。これ勘違いするとすべてがおかしくなってしまいますので (^_^;)

 


■押しボタンスイッチのアクションの検出

Arduino を使って、押しボタンスイッチの入力アクションの検出を行なってみました。

アクションは「シングル (一回押し) 」「ダブル (二回押し) 」「ホールド (長押し) 」の三種類で、これらを一つのタクトスイッチから検出し LED の点灯・点滅・消灯を制御します。

ググってみると、一定の時間内にスイッチの状態を確認して OFF/ON が変化する時間や回数を調べる方法がとられているようですので、その方法で自分なりに考えてみることにします。

 

 

ますはアクションの検出について。

スイッチに入力があったら、そこから 50ミリ秒毎に 10回チェックを行い、その間にあった変化の回数をカウントすることにします。「シングル」では変化は 1回だけです。「ホールド」では変化はありません。「ダブル」の場合は 2回目の変化があった時点で判断します。


アクションの検出

 

 

次に回路図です。

難しいものではありません。タクトスイッチの入力と、出力で LED を駆動するだけです。

入力ピンの電流を確認してみると HIGH でも LOW でも 0.7mA 程度でしたので、プルアップでもプルダウンでもどちらでもよさそうです。今回は ON 時に HIGH となるようプルダウンとしました。

出力も HIGH 時に LED が点灯するようにしました。もちろん電流値をきちんと確認して Arduino で直接駆動してもかまいませんが、これぐらいの単純なスイッチング回路を作るぐらいは屁でもありませんから (^_^;)


回路図

 


大まかなフローチャートです。

グーグル先生たちはこういうのを書かないのか、あまり見ませんね (^_^;)  上手ではありませんが、考えを整理するためにも簡単に作ると具合がいいです。


フローチャート(全体)


「入力待ち」では、スイッチが押されたかどうかを検知します。待つためにここでプログラムを止めてしまうと LED の点滅の制御ができなくなるので、一度検知したら次の処理を行なってからまた戻ってくるようにします。

スイッチが押されたら「変化を調べる」処理をします。前述のように、一定の時間内にスイッチの状態が変化した回数を調べます。

変化した回数をもとに、「LED表示」で点灯・点滅・消灯の制御を行います。点滅は 150ミリ秒を経過することに点灯・消灯を切り替えます。

 

「入力待ち」はこんな感じです。

入力ピンの状態を読み込んでスイッチが押されたら state_of_button をセットします。押されなければ何もしません。


フローチャート(入力待ち)

 

スイッチが押されたら「変化を調べる」を実行します。押されていないときは何もしません。

50ミリ秒待ってからスイッチの状態が変化 (ON から OFF、または OFF から ON) しているかを調べます。変化なければ、また50ミリ秒待って調べます。これを 10回、都合 500ミリ秒間行ないます。

スイッチの状態が変化していたら number_of_changes を加算します。変化の回数が 2 になれば「ダブル」が確定しますので、ループを抜けます。これで number_of_changes は「シングル」が 1 、「ダブル」が 2 、「ホールド」は 0 となります。

ちなみに、最後の elapsed_time リセットは LED 点滅周期タイマーのスタートです。


フローチャート(変化を調べる)

 

最後は「LED 表示」です。

number_of_changes 値に従って switch case で分岐します。点滅制御は millis() 関数を利用して経過時間を調べ、150ミリ秒を経過していれば light 値を反転させて点灯・消灯を繰り返すという方法をとります。L チカでよくある delay を使う方法では、プログラムがここで止まってしまうのでうまくありません。


フローチャート(LED表示)

 

 

ということでできたスケッチは以下です。

// button-status.ino 2019/05/31 meyon

 

int inputPin = 2;
int outputPin = 13;
boolean state_of_button = 0;
boolean state_of_currently = 0;
int number_of_changes = 0;
unsigned long elapsed_time;
boolean light = 0;

 

void wait_input(){
  state_of_currently = digitalRead(inputPin);
  if(state_of_currently == 1){
    state_of_button = 1;
    number_of_changes = 0;
  }
  return;
}

 

void detect_changes(){
  if(state_of_button == 1){
    for(int i=0; i<10; i++){
      delay(50);
      state_of_currently = digitalRead(inputPin);
      if(state_of_currently != state_of_button){
        number_of_changes ++;
        if(number_of_changes >= 2){
          break;
        }
        state_of_button = state_of_currently;
      }
    }
    while(state_of_currently == 1){
      state_of_currently = digitalRead(inputPin);
    }
    state_of_button = 0;
    elapsed_time = millis();
  }
  return;
}

 

void light_led(){
  switch(number_of_changes){
    case 0:
      light = 0;
      break;
    case 1:
      light = 1;
      break;
    case 2:
      if(millis() - elapsed_time > 150){
        light = !light;
        elapsed_time = millis();
      }
  }
  digitalWrite(outputPin, light);

  return;
}

 

void setup() {
  pinMode(outputPin, OUTPUT);
  pinMode(inputPin,  INPUT);

 

//  Serial.begin(9600);
}

 

void loop() {
  wait_input();
  detect_changes();
  light_led();

 

//  Serial.print(state_of_currently);
//  Serial.print(state_of_button);
//  Serial.println(number_of_changes);

}

 

コメントアウトしてあるシリアル出力はデバック時に変数の値を確認していたものです。このように適当な位置に Serial.print を入れると、その場所で変数がどうなっているかが見えるようになります。うまく動かないときに重宝しますね。

 

ということで、スイッチアクションで制御を切り替えることができるようになりました。

 


■LED Cube 4x4x4 を試してみた

シフトレジスターがうまく動きましたので、LED-Cube 4x4x4 を作ってみます。が、キューブ自体は組み立てる気がないので、ブレッドボード上に 64個の LED を並べて自由なパターンに点灯できるようにしました。

 

回路図です。

LED はアノードコモンで、アノード側のトランジスタ 2SA1015 でレイヤを制御します。レイヤのインターロックは省略しました。まぁ、気分です (^_^;)

シフトレジスタは 2段に繋いで、16コラムを制御しています。


led-cube_4x4x4_回路図

 

スケッチです。

 

#include <MsTimer2.h>

 

int ptn[][4] = {                  // Pattern data
//{LayerA,LayerB,LayerC,LayerD},

  {0x0001,0x0000,0x0000,0x0000},
  {0x0013,0x0000,0x0000,0x0000},
  {0x0137,0x0000,0x0000,0x0000},
  {0x137f,0x0000,0x0000,0x0000},
  {0x37fe,0x0001,0x0000,0x0000},
  {0x7fec,0x0013,0x0000,0x0000},
  {0xfec8,0x0137,0x0000,0x0000},
  {0xec80,0x137f,0x0000,0x0000},
  {0xc800,0x37fe,0x0001,0x0000},
  {0x8000,0x7fec,0x0013,0x0000},
  {0x0000,0xfec8,0x0137,0x0000},
  {0x0000,0xec80,0x137f,0x0000},
  {0x0000,0xc800,0x37fe,0x0001},
  {0x0000,0x8000,0x7fec,0x0013},
  {0x0000,0x0000,0xfec8,0x0137},
  {0x0000,0x0000,0xec80,0x137f},
  {0x0000,0x0000,0xc800,0x37fe},
  {0x0000,0x0000,0x8000,0x7fec},
  {0x0000,0x0000,0x0000,0xfec8},
  {0x0000,0x0000,0x0000,0xec80},
  {0x0000,0x0000,0x0000,0xc800},
  {0x0000,0x0000,0x0000,0x8000},
  {0x0000,0x0000,0x0000,0x0000},

};

 

  unsigned long cycle =200;   // Pattern cycle
  int dataPin = 2;
  int clockPin = 4;
  int layer[4] = {8,9,10,11};
  int nptn = sizeof(ptn) / sizeof(ptn[0]);
  int cptn = 0;

 

void chptn(){
  cptn++;
  if (cptn > nptn-1)
    cptn = 0;
}

 

void setup(){
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);

  for (int i=0; i<4; i++){
    pinMode(layer[i], OUTPUT);
    digitalWrite(layer[i], HIGH);
  }

  shiftOut(dataPin, clockPin, MSBFIRST, 0xff00 >> 8);
  shiftOut(dataPin, clockPin, MSBFIRST, 0xff);

 

  MsTimer2::set(cycle, chptn);
  MsTimer2::start();
}

 

void loop(){
  for (int i=0; i<4; i++){
    shiftOut(dataPin, clockPin, MSBFIRST, ~ptn[cptn][i] >> 8);
    shiftOut(dataPin, clockPin, MSBFIRST, ~ptn[cptn][i]);
    digitalWrite(layer[i], LOW);
    delay(1);
    digitalWrite(layer[i], HIGH);
  }
}

 

パターンデータは 16進数になっています。

起動時にレイヤとコラムをすべて HIGH に初期化し消灯させています。

パターンの切り替えは MsTimer2 で割り込み処理しています。

シフトレジスタへの出力は shiftOut 関数を使います。LOW で点灯なのでパターンデータを NOT しています。シフト出力中に LED が点灯しないように、出力が終わってからレイヤを ON します。

その他、基本的に 3x3x3 と同様ですね。

 

ブレッドボードです。

今回は 0.5mm 単線で配線しました。ストリッパー使ったり面倒っちゃ面倒ですけど、まぁ慣れです。


LED-Cube 4x4x4

 

 


■シフトレジスターSN74LS164Nを使ってみる

LED Cube を制御するためにシフトレジスターを使ってみようと思います。

 

ググると SN74HC595N がよく出てくるのですが、いつも行くパーツ屋さんには在庫がなかった。毎度のことだけど品揃えは悪い。何か代わりはないかなと探して見つけたのが SN74LS164N という TTL のシフトレジスターです。CMOS のもあったのですけど、こっちが安かったから (^_^;) SN74HC595N と比較するとこちらはストレージレジスターがありませんが、まぁ実験に使うには問題ないでしょう。

 

さてとりあえず、あまり考えもせずに下のような回路を組んで動かしてみました。


shift-register-test01_回路図.png

 

スイッチを押すと LED が順番に点灯し、離すと順番に消えていくという回路です。の、はずです。

が、スイッチを押すと 8 個の LED がいっぺんに点灯する… 離すといっぺんに消灯する… しかもクロックの立下りでも反応する… なんでやねん (^_^;) ??? 

さんざん悩んで、ググって、でも SN74LS164N の情報がほとんどない。LED の駆動にバッファを入れたり、スイッチにコンデンサー入れたりしてみたけど、まったく改善しない。

 

そしてようやく見つけたサイトがここ 8-bit shift register 74LS164 not working でした。まさに今の俺と同じ症状です。

原因はクロックの波形が綺麗でないのではないかということ。対策は波形整形のためにシュミット回路を入れてみる、でした。早速シュミットインバータを挿入してみると、みごとに LED が順番に点灯してくれました。

 

そしてもう一つ、この記事に書かれていたのは、SN74LS164N から取り出せる電流の推奨値は 0.4mA だということ。逆に出力へ流し込むように使うほうが良いのだということでした。たしかにデータシートの推奨値を見ると IOH = -0.4mA 、IOL = 8mA となっています。

一般的に TTL の場合、入力は LOW で吐き出し、出力は LOW で吸い込みですから、その通りだと納得です。基本を忘れてはいけません (^_^;) 逆に入力が HIGH では電流がほとんど流れませんから、クリア (CLR) 入力のように直接 +5V ラインにつなげます。

 

ということで、最終的に出来上がったシフトレジスターのテスト回路は以下のようになりました。


shift-register-test02_回路図.png

 

出力 LOW で点灯ですので、データ入力も LOW で点灯、HIGH で消灯となります。クリア入力は常に HIGH にしていますが、これを LOW にすると出力がクリアされます。ただし、クリア時は出力 LOW となり全点灯します。

CMOS で HIGH 時点灯に慣れているとちょっと使いにくいかもしれませんね。

 


■LED Cube 3x3x3 を作ってみた - 組み立て

回路もスケッチもうまくいきそうなので、Cube を組み立ててみました。

 

Cube の組み立てはググるといろいろ出てきますので参考に。今回は LED のリードを折り曲げ加工してはんだ付けで組み立てましたが、数が多くなるとかなり難しいですね。治具に固定して作業するのですが、逆にフレームを作って LED を取り付けていくといった方法を考えたほうが良さそうな気がします。

ケースに収めて仕上げるのも良いのですが、今回はここまでにしようと思います。

 

 

led-cube_3x3x3

 

 

回路は、Arduino で直接駆動できる電流値を確認しているのでバッファをなくしました。その代りスケッチをミスってもレイヤが同時に ON しないようにインターロックを残します。それらを 5cm x 7cm のユニバーサル基板に組んで、ジャンパーで Arduino に繋ぐようにしました。

最終的な回路は以下のようになっています。スケッチは「LED Cube 3x3x3 を作ってみた - Arduino スケッチ」の通りです。

 


led-cube_3x3x3_回路図.png

 

さてと、次は Cube を 4x4x4 にして、シフトレジスターを使ってみようと考えています。

 


■LED Cube 3x3x3 を作ってみた - Arduino スケッチ

LED Cube 3x3x3 を制御する Arduino のスケッチです。

 

// Pattern data
int ptn[][3] = {
//{LayerA,LayerB,LayerC},
    {0525,0252,0525},
    {0252,0525,0252},
    {0525,0252,0525},

    {0777,0000,0777},
    {0070,0777,0070},
    {0707,0707,0707},

    {0272,0272,0272},

    {0555,0555,0555}

 };

 

int colpin[9] = {2,3,4,5,6,7,8,12,13};    // Column output pin
int laypin[3] = {9,10,11};    // Layer output pin

 

void setup() {
    for (int i=0; i<9; i++){
        pinMode (colpin[i], OUTPUT);
    }
    for (int i=0; i<3; i++){
        pinMode (laypin[i], OUTPUT);
    }
}

 

void loop() {
    unsigned long pcycle = 600;    // Pattern cycle (ms)

 

    int nptn = sizeof(ptn) / sizeof(ptn[0]);

    for (int k=0; k < nptn; k++){
        unsigned long ctime = millis();
        while (millis() - ctime < pcycle){
            for (int j=0; j<3; j++){
                digitalWrite (laypin[j], HIGH);
                for(int i=0; i<10; i++){
                    digitalWrite (colpin[i], ptn[k][j]>>i&1);
                }
                for(int i=0; i<10; i++){
                    digitalWrite (colpin[i], LOW);
                }
                digitalWrite (laypin[j], LOW);
            }
        }
    }
}

 

点灯パターンを ptn[][3] に定義しています。

 

LED9 LED6 LED3
LED8 LED5 LED2
LED7 LED4 LED1

 

例えば「0525」では、最初の「0」が 8 進数であることを示し、次の 3 桁が点灯パターンを表しています。初めの「5」は LED9と LED7 を、次の「2」は LED5 を、最後の「5」は LED3 と LED1 を点灯させることを意味しています。これは 2 進数の「101010101」ですので、「0b101010101」と書いてもかまいません。ただし「B101010101」という書き方では 8 ビットしか扱えないようなのでコンパイルエラーになります。

同様に 10 進数でもよいので、「341」であれば LED9、7、5、3、1 が点灯します。ちなみに「0341」は 8 進数なので LED8、7、6、1 が点灯することになります。まぁ 10 進数では直感的にわからないですね (^_^;) 俺は 8 進数表記がわかりやすいです。

ひとつの { } 内の最初の数値が Layer A 、次が Layer B、最後が Layer C に対応するので、{ } が一つの点灯パターンになります。パターンは何行でも、変数メモリがある限り増やせます。

 

この ptn 配列変数をもとにして

 

    for(int i=0; i<10; i++){
        digitalWrite (colpin[i], ptn[k][j]>>i&1);
    }

 

でコラムの 9 列の LED の点灯を制御します。変数 j でレイヤを切り替えて、一つの点灯パターンを完成させています。

そして変数 k の数だけパターンを変化させていきます。ptn の行数は定義していないので、

 

     int nptn = sizeof(ptn) / sizeof(ptn[0]);

 

で行数を算出します。

一つのパターンの表示時間は pcycle で定義してあり、タイマーが  pcycle を超えると次のパターンへ移行します。

 

    unsigned long ctime = millis();
    while (millis() - ctime < pcycle){

        ︙

    }

 

って感じです。

 


■LED Cube 3x3x3 を作ってみた - 回路図

久しぶりに Arduino を引っ張り出して遊んでみようかと思います。今回はとりあえず簡単そうな (^_^;) 3x3x3 の LED Cube を作ってみましょう。

 

ざっとググってみると、LED でキューブを作ったという記事がたくさん出てきますから参考になります。でも、回路とかスケッチとかはやっぱり自分でやってみないとよくわからないなぁって印象でした。まぁ自分なりに考えてみましょう。LED のダイナミック点灯を試してみたいと考えていたので、ちょうど良いタイミングですし。

 

まず回路図を書いてみます。

LED は 9 個をカソードコモンに接続して 1 レイヤとします。それを 3 段重ねてダイナミック点灯させる。つまり各レイヤは同時に同じパターンで HIGH にし、カソード側を順次 ON にするという方法ですね。

9 本のコラム (アノード) と 3 本のレイヤ (カソード) は Arduino のデジタルピン 2〜13 で制御します。1 レイヤ当たりの LED 駆動電流は 60mA 弱ですので Arduino で直接駆動できますが、毎度のように駆動用にバッファを入れることにします。次の段階でこの部分をシフトレジスタに変更してみたいなという考えもあります。

 


led-cube_3x3x3_回路図

 

 

パーツは手持ちのものを使っています。特別なものはまったくありません。

LED 駆動電流は 6.4mA 、レイヤ当たり 57.6mA です。レイヤ制御用トランジスタ (KSC1815Y) のコレクタ電流は 150mA なので十分ですね。ベース側のダイオードはレイヤが同時に ON しないようにするインターロックですが、プログラムで制御しますからやめてかまわないと思います。

バッファ (74VHCT244) は全体で 70mA ほどまで出力できますので、こちらも十分です。バッファの入力は Arduino の電源が落ちた時に不安定になるのでプルダウンしています。

レイヤ制御を 9~11 ピンにしているのはここを PWM にしたら明るさを変化させられるかなという狙いです。

 

これをブレッドボードで組み立てたのが下の写真です。

 


led-cube_3x3x3_ブレッドボード

 

 

次はこれを制御するスケッチを書いてみましょう。

 


| 1/4PAGES | >>

■calendar

S M T W T F S
 123456
78910111213
14151617181920
21222324252627
28293031   
<< July 2019 >>

■search this site.

■recommend

毎日貯まるポイントサイト ECナビ

■recommend

* 楽天ROOM *

■Twitter

■recommend

■recommend

■selected entries

■categories

■archives

■recent comment

■recent trackback

■links

■profile

■others

■mobile

qrcode

■powered

無料ブログ作成サービス JUGEM