シフトレジスタ (74HC595) と Arduino を使って複数の LED を制御する方法
シフトレジスタで何ができるの?
シフトレジスタを使うと、少ない出力ピンでたくさんの出力を制御することが可能になります。
このページではシフトレジスタと Arduino UNO を用いて、8 個の LED を制御する方法を説明します。
ここで説明する内容で、次のように 8 個の LED を順番に点灯させることができます。
LED はシフトレジスタに接続してあります。Arduino 側では 5V の電源や GND の他は、シフトレジスタの制御用に、たった 3 本しかデジタルピンを使っていません。
ここでは、シフトレジスタとして代表的な 74HC595 を用います。
さっそく、使い方を見ていきましょう。
シフトレジスタ 74HC595 のピン配置
シフトレジスタ 74HC595 のピン配置は次の通りです。
電源 VCC は 16 番です。5V に接続して使います。GND は 8 番です。
デジタル出力は \(Q_A\) から \(Q_H\) の 8 個です。ピン番号は \(Q_A\) から順番に 15、1、2、\(\cdots\) 7 です。 ここに 8 個の LED と電流制限用の抵抗を接続します。
9 番の \(Q_{H'}\) はカスケード用のシリアル出力です。今回は使いません。
カスケード接続については「シフトレジスタ (74HC595) のカスケード接続」をみてください。74HC595 を2個カスケード接続 (数珠つなぎ) にして、 16 個の LED を制御する方法を説明しています。
14番ピン SER はシリアルデータ入力です。このピンを使って Arduino から 8 ビットのデータを入力します。
後で説明しますが Arduino のプログラムでは shiftOut() 関数にデータ 1 バイトを渡して呼ぶだけです。
12番ピン RCLK (ストレージ・レジスター・クロック) はいわゆるラッチです。データをセットする前に LOW にしておき、変更を有効にするときに HIGH にします。
11番ピン SRCLK (シフト・レジスター・クロック) は 74HC595 内部の D タイプストレージレジスタにデータをセットしていくためのクロックです。
SRCLK と RCLK は両方ともポジティブエッジトリガーです。クロックの立ち上がりでレジスターに値がセットされます。
13番は OE (Output Enable) ピンです。LOW のときに出力が有効になります。今回は常に有効するので GND に接続しておきます。
10番は SRCLR (シリアルクリア) です。 これを LOW にすると直ちに出力をクリアできます。今回は 5V に接続して常に HIGH にしておきます。
ちなみに、ピン名の上にバーが書いてあるときはアクティブ・ロー (Active Low) を意味します。LOW のときにそのピンの機能が有効になるということです。
Arduino からシフトレジスタ 74HC595 を使う方法
Arduino からシフトレジスタ 74HC595 を使うには、具体的にどうしたら良いでしょうか。 具体的に 8 個の LED を点灯、消灯させる例で説明します。
Arduino と 74HC595 と LED の配線
Arduino からシフトレジスタ 74HC595 を介して 8 個の LED を制御するためには、 74HC595 の出力ピン \(Q_A\) から \(Q_H\) に LED を接続します。
電流を制限するために、ここでは 470 Ω の抵抗を接続しています。
Arduino との接続は、3つのデジタルピンを使います。Arduino で使うデジタルピンの番号は任意ですが、ここでは 8 番、9番、10番を使います。
Arduino のデジタル8番ピン (D8) には、74HC595 の SER (14番) を接続します。 SER はシリアルデータ入力ピンです。
Arduino のデジタル9番ピン (D9) には 74HC595 の RCLK (12番) を接続します。これはラッチになります。
Arduino のデジタル10番ピン (D10) には 74HC595 の SRCLK (11番) を接続します。これはクロックになります。
その他は、電源、OE、SRCLR、GND などを 5V または GND に接続していきます。
シフトレジスタ 74HC595 に 8 ビットのデータを入力
74HC595 の 8 個の出力をコントロールするためには、1バイト (8 ビット) のデータを SER ピンに入力します。 この 8 ビットがそれぞれ \(Q_A\) から \(Q_H\) までの8個の出力の ON/OFF を決めます。
シフトレジスタにデータをセットするためには shiftOut() 関数が使えます。
このとき shiftOut() を呼ぶ前にラッチを LOW にします。shiftOut() の後にラッチを HIGH にすることで、 出力が有効になります。
const int PIN_SER = 8; const int PIN_LATCH = 9; const int PIN_CLK = 10; void setup() { pinMode( PIN_SER, OUTPUT ); pinMode( PIN_LATCH, OUTPUT ); pinMode( PIN_CLK, OUTPUT ); byte b = B11000000; digitalWrite(PIN_LATCH, LOW); shiftOut(PIN_SER, PIN_CLK, LSBFIRST, b); digitalWrite(PIN_LATCH, HIGH); } void loop() { }
この例ではセットするデータとして B11000000 としました。 このうち先頭の B は、二進数のデータであることを示しています。
従って、セットしたデータは二進数で 11000000 です。これは 10 進数で 192 ですから、 次のように 10 進数で初期化しても同じです。
byte b = (byte) 192; // B11000000 と同じ
MSB が先か、LSB が先かで出力される場所が違う
さて二進数で 11000000 をセットした場合、出力 \(Q_A\) から \(Q_H\) のどこが HIGH になり、 どこが OFF になるのでしょうか。
これは shiftOut() 関数を呼ぶときに渡すフラグで変わります。
二進数で 11000000 と書いたとき、左端のビットを MSB (Most Significant Bit, 最上位ビット)、 右端のビットを LSB (Least Significant Bit, 最下位ビット) といいます。
shiftOut() 関数は引数として、左から「シリアルデータ入力ピン番号」、「シフトレジスタークロックピン番号」、 「ビット順」、「値」を受け取ります。
ビット順は MSBFIRST か LSBFIRST か、どちらかを指定します。
もし値が B11000000 で、ビット順が LSBFIRST である場合には、LSB の 0 から入力されて、 はじめに \(Q_A\) にセットされます。
次のクロック (の立ち上がり) で \(Q_A\) にセットされていた出力が \(Q_B\) にシフトし、新しく入力された最下位ビットから数えて2番目の 0 が \(Q_A\) にセットされます。
次のクロックで、\(Q_B\) の値は \(Q_C\) へ、\(Q_A\) は \(Q_B\) へ・・・、と、ひとつずつシフトしていきます。
こうして最終的に、\(Q_A\)、 \(Q_B\)、 \(\cdots\)、\(Q_H\) それぞれに、1、1、0、0、0、0、0、0 が順番にセットされることになります。
74HC595 ではこのように、シリアルで入力して、パラレルで出力を取り出せます。このタイプを SIPO (Serial-In Parallel-Out) シフトレジスタといいます。
ビット順に MSBFIRST を指定した場合は、MSB からデータが入力されるので、LSBFIRST の場合と逆の順番になります。
8 個の LED を順番に点灯させる例
ここまでの説明で Arduino UNO とシフトレジスタ 74HC595 と LED などの配線、データの設定方法といった、基本的な項目について説明できました。
最後に、冒頭のビデオでみたように左から右へ LED が流れるように光るようにするためのサンプルコードを記載しておきます。
const int PIN_SER = 8; const int PIN_LATCH = 9; const int PIN_CLK = 10; byte patterns[] = { B00000000, B10000000, B11000000, B11100000, B11110000, B11111000, B01111100, B00111110, B00011111, B00001111, B00000111, B00000011, B00000001, B00000000 }; void setup() { pinMode( PIN_SER, OUTPUT ); pinMode( PIN_LATCH, OUTPUT ); pinMode( PIN_CLK, OUTPUT ); } void loop() { for ( int i=0; i<sizeof(patterns)/sizeof(byte); i++ ) { digitalWrite( PIN_LATCH, LOW ); shiftOut( PIN_SER, PIN_CLK, LSBFIRST, patterns[i] ); digitalWrite( PIN_LATCH, HIGH ); delay(200); } }
点灯する LED のパターンをバイトの配列で保持します。その配列の要素の値を順番に shiftOut() でシフトレジスタにセットしています。
以上、ここではシフトレジスタ 74HC595 を用いて、複数の LED を制御する方法を説明しました。