LoginSignup
16
10

More than 5 years have passed since last update.

秋月電子通商の8ビットシフトレジスタSN74HC595Nを二つ連結してArduinoで16個のLEDを光らせる

Last updated at Posted at 2018-03-04

最近、身近に沢山のLEDを利用した電飾などを作っている人がいて、Arduino Uno(非正規品)でシフトレジスタを使って多くのLEDを制御させてみようと買ってやってみました。

IMG_1029.JPG

この写真ではArduinoで16個のLEDを並列に制御しています。

シフトレジスタは、1つの入力(実際には信号に3ピンは最低使うが)を信号を用いることでパラレルに8個に分割してくれる便利な部品です。また複数個連結することができ、1つの入力からシフトレジスタの個数 x 8個分の出力してくれるというものです。これで1台のArduinoで何十何百というLEDを制御することも出力を得ることもできます。

買ったシフトレジスタはこれです。

一個40円でした。そして、LEDも今後何か作ってみようということで、緑色のLED50個を1350円で購入。早速実装。

ただ、データシートを見てみるものの、どれがデータピン、クロックピン、ラッチピンなのかわからず...。普通のSN74HC595Nとピン名が異なるという状況になっていました。ただラッキーなことに、

にまとめてくれている人がいて、ことなきをえました。

キャプチャ1.PNG

キャプチャ2.PNG

ブログの内容とTEXAS INSTRUMENTのデータシートの情報と合わせると、

ラベル 役割、接続先
VCC 給電が必要なためArduinoの5Vに接続
QA~QH SERからの入力の1~8ビット目に対応する出力を得られる
OE HIGHを入力するとシフトレジスタをハイインピーダンス(抵抗をすごく大きい状態)にするらしいので、 ArduinoのGNDに接続
RCLK ラッチピンで、通信中はLOW、通信終了時はHIGHにする信号を送る必要がある
SRCLK クロックピンで、1ビット書き込んだら、HIGH→LOWとする信号を送る必要がある
SRCLR LOWにすることで書き込みをクリアするので、ずっとArduinoの5Vに接続してHIGHにしておく
QH' SERからの入力の9ビット目以降の信号を出力、この出力を次に連結するシフトレジスタのSERにつなぐことで制御数をどんどん増やしていける
GND 電位0につなぐ必要があるのでArduinoのGNDに接続

とのこと。データシートのFUNCTION TABLEからは残念ながら最初で理解することができませんでした...。↑マークが信号を送るという意味であることを例のブログを見てやっと理解しました。これは初見ではわからない...。

まず一つ目の出力をテストでしてみて、最初抵抗なしで行けるかなぁと思ってLEDにかかる電圧を調べてみたら3.9V、LEDの最大電圧が3.1Vだったので、1KΩの抵抗をつなぐことにしました。

Arduino の実装は以下の通り。最初は標準関数のshiftOut関数を使ったのですが、8ビットまでの出力はうまくいったのですが、9ビット目以降はなぜか1クロック遅れて入力されてしまうという問題があり、hiramine.comさんのサイトの実装をパクって自分でshiftOut関数を実装しました。 (実はこのサイトの平峰さん前職の先輩社員でお世話になっていました)

また標準関数のサンプル実装と同じピン構成で、8をラッチピン、12をクロックピン、11をデータピンにしました。パターンをStringで用意しておき、ラッチピンとクロックピンを駆使しながらデータピンに書き出すようになっています。

int latchPin = 8; // SRCLK
int clockPin = 12; // RCLK
int dataPin = 11; // SER

int patternLength = 8;

String patterns[] = {
  "0000000110000000",
  "0000001001000000",
  "0000010000100000",
  "0000100000010000",
  "0001000000001000",
  "0010000000000100",
  "0100000000000010",
  "1000000000000001"
};

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

void loop() {
  int len = sizeof(patterns);

  for (int j = 0; j < patternLength; j++) {
    //通信中は,latchPinをLOWにする
    digitalWrite(latchPin, LOW);
//    shiftOut(dataPin, clockPin, MSBFIRST, patternToChar(patterns[j])); 
    myShiftOut(dataPin, clockPin, patternToChar(patterns[j]), 16); // 標準のshiftOutではクロックが一つ余計に入るため
    //通信が終了したらlatchPinをHIGHにする
    digitalWrite(latchPin, HIGH);
    delay(30);
  }
}

void myShiftOut(int dataPin, int clockPin, long data, int dataLength) {
  for (int i = 0; i < dataLength; i++ ) {
    digitalWrite(dataPin, !!(data & 1L << i));
    digitalWrite(clockPin, HIGH);
    digitalWrite(clockPin, LOW);
  }
}

long patternToChar(String pattern) {
  int result = 0;
  for (int i = 0; i < pattern.length(); i++) {
    char c = pattern.charAt(i);
    if (c == '1') {
      result += 1 << i;
    }
  }
  return result;
}

以上です。回路の様子はこんな感じです。

IMG_1030.JPG

回路図をFritzingで書こうと思ったのですが、そもそもArduinoにつなぐところは5つしかなく、全出力もLEDと抵抗をそのままつないだだけで簡単なので書きませんでした。

動作する様子はこのようになります。(リンク先が動画になっています)

動作する様子

最終的にこんな感じに動作します。せっかく大量のシフトレジスタとLEDを購入したので今度はもっと大きなものにチャレンジしてみたいと思います。

お読みいただきありがとうございました。

16
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
10