最近、身近に沢山のLEDを利用した電飾などを作っている人がいて、Arduino Uno(非正規品)でシフトレジスタを使って多くのLEDを制御させてみようと買ってやってみました。
この写真ではArduinoで16個のLEDを並列に制御しています。
シフトレジスタは、1つの入力(実際には信号に3ピンは最低使うが)を信号を用いることでパラレルに8個に分割してくれる便利な部品です。また複数個連結することができ、1つの入力からシフトレジスタの個数 x 8個分の出力してくれるというものです。これで1台のArduinoで何十何百というLEDを制御することも出力を得ることもできます。
買ったシフトレジスタはこれです。
一個40円でした。そして、LEDも今後何か作ってみようということで、緑色のLED50個を1350円で購入。早速実装。
ただ、データシートを見てみるものの、どれがデータピン、クロックピン、ラッチピンなのかわからず...。普通のSN74HC595Nとピン名が異なるという状況になっていました。ただラッキーなことに、
にまとめてくれている人がいて、ことなきをえました。
ブログの内容と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;
}
以上です。回路の様子はこんな感じです。
回路図をFritzingで書こうと思ったのですが、そもそもArduinoにつなぐところは5つしかなく、全出力もLEDと抵抗をそのままつないだだけで簡単なので書きませんでした。
動作する様子はこのようになります。(リンク先が動画になっています)
最終的にこんな感じに動作します。せっかく大量のシフトレジスタとLEDを購入したので今度はもっと大きなものにチャレンジしてみたいと思います。
お読みいただきありがとうございました。