Arduino 入門
Lesson 20
【8bitシフトレジスタによる複数LED制御編】
「Arduino」を使ったマイコンプログラミングを子供と一緒に学習するブログ。
少しずつ、子供と一緒に楽しみながら気長にアップしてく予定です。
本日は「Lesson 20 シフトレジスタによる複数LED制御編」です。
複数のLEDを直接Arduinoに抵抗と合わせて接続して制御するということではありません。
これをしてしまうと、Arduino UNOのピンが足りなくなり、センサーやボタンなど他電子部品を接続できないためピン不足になってしまいます。
そこで、「74HC595」のICを使うことでArduino UNOのピンを節約します。
「74HC595」は8bitのシフトレジスタです。
※シリアル・パラレル・コンパレータとも、呼ばれます。
本Lesson解説で使用しているのはArduino互換品です。
互換品とは言え、Arduinoはオープンソースであり複製して販売するのもライセンス的に問題なし。
そのため互換品の品質も悪くなく、それでいて値段は安いです。
正規品本体の値段程度で豊富な部品が多数ついています。
はじめに
今回は8bitシフトレジスタについて理解したいと考えています。
ネットで検索する場合は「74HC595」で検索してみてください。
Amazonでも購入できますので確認してみてください。
メーカは多種多様です。
学術的に「シフトレジスタ」とは何か?
言葉の定義については、Wikipediaにおまかせします。
シフトレジスタ(英: Shift register)とは、複数のフリップフロップをカスケード接続し、データがその回路内を移動(シフト)していくよう構成したデジタル回路のこと。
Lesson 20 目標
8bitシフトレジスタの「Arduinoでの使い方を理解」します。
また、「8bitシフトレジスタを使い複数のLEDを制御することを理解」します。
最後に、本Lessonも、「遊ぶというところが一番大事」なところです。
準備
ではLessonの準備に取り掛かりましょう。
今回も部品は多くないので、すぐに実践に移ることができます。
必要なもの
- USB接続用のPC(IDE統合環境がインストールされたPC)
→管理人が勝手に比較したBTOメーカーを紹介しています。 - UNO R3(以下UNO)、おすすめUNO互換品(ELEGOO)
- PCとUNOを接続するUSBケーブル
- ブレッドボード安価(大)、ブレッドボード安価(中)
※おすすめブレッドボード(大)、おすすめブレッドボード(中) - SN74HC595N IC 8bitシフトレジスタ
- LED 8個
- 抵抗 220Ω 8本
- M-M Jumper wire(UNOと部品をつなぐための配線)
Jumper wire、抵抗は今後も頻繁に利用します。
Jumper wireはできれば、「オス-メス オス-オス メス –メス」の3種類を揃えておくことをお勧めします。
短めが使いやすい場合も。
抵抗も単品で揃えるよりはセットをおすすめします。
抵抗、LEDなどを個別でセット品を購入しても、そんなに使わない!
という方は、「電子工作基本部品セット」が使い勝手が良い。
使用部品説明
8bitシフトレジスタについて説明していきます。
本Lessonで使用するICは「SN74HC595N」となります。
本Lessonでのシフトレジスタの使用目的は以下となります。
少ないピンで多くの出力制御をする。
※直列入力並列出力(SIPO:Serial In Parallel Out)と呼ばれます。
SN74HC595N 8bitシフトレジスタ 仕様
下の写真が、8bitシフトレジスタ「SN74HC595N」です。
データシートは以下から入手可能です。
「SN74HC595N」で検索してみてください。
端子は全部で16ピンあります。
メーカのデータシートによって端子名は異なります。
以下に端子の説明を示します。
メーカーによってピン名などは異なりますが、基本的な使い方は同じです。
ピン番号 | IC ピン名前 |
fritzing ピン名 |
入出力 | 内容 |
---|---|---|---|---|
1~7 15 |
QB~QH QA |
Q1~Q7 Q0 |
出力 | パラレル出力。 |
9 | QH’ | Q7′ | 出力 | シフトレジスタの最上位ビットの状態を出力。 シフトレジスタを何個も繋げて使う時に使用。 |
10 | SRCLR | MR | 入力 | シフトレジスタのクリア(リセット)。 Lでシフトレジスタの全bitがLに初期化。 |
11 | SRCLK | SH_CP | 入力 | シフトレジスタのクロック信号。 立上りエッジに同期してシフトレジスタが動作。 |
12 | RCLK | ST_CP | 入力 | ラッチクロック。 ストレージレジスタのクロック信号。 RCLK信号の立ち上がりに同期して、シフトレジスタの出力がストレージレジスタに転送されます。 8bitのデータを送信順に出力 |
13 | OE | OE | 入力 | 出力の有効化。 全パラレル出力が切断状態になる。 ※ハイインピーダンス状態 |
14 | SER | DS | 入力 | シリアル入力。 SRCLK信号の立ち上がりに同期して、シフトレジスタの初段Dフリップフロップに取り込まれる。 |
8 | GND | GND | – | グランド(UNOのGNDに接続) |
16 | VCC | VCC | – | 電源(UNOの5Vに接続) |
ピンがたくさんあり、混乱しそうですがシフトレジスタの動作で必要なのは以下だけです。
- シリアル入力 ・・・ データを入れる
- パラレル出力 ・・・ データ出力
- シフトレジスタクロック ・・・ データの入力先を次のアドレスに移動
- ラッチクロック ・・・8bitのデータを送信順に出力
この4種類を制御することで、シリアルデータをパラレルデータに変換することができます。
今回のLessonではShiftOut関数を使います。
これによって、意識するピンはラッチクロックだけとなります。
8bitシフトレジスタの使い方
ここでは簡単に使い方のみ説明します。
shiftOut関数を利用することで簡単に制御することが可能です。
この関数は8bit分のデータを一括でシフトレジスタに送ることができます。
RCLK以外のシフトレジスタの制御をshiftOut関数が担ってくれるのです。
そのため、サンプルコードとして意識する動作は以下のみとなります。
データ送信中はLow。
2.shiftOut関数を使って8bit分のデータをシフトレジスタに送る。
動作としては点灯するLEDを選択するということ。
3.RCLK(ST_CP)をHighにする。
送信終了。
たったこれだけです。
補足
実際はRCLKでフリップフロップの状態を更新する制御をしています。
タイミングチャートなどであらわすと、もっと複雑なのですがその辺がわかっていなくても動かせてしまうのがArduinoです。
参考にタイミングチャートを載せておきます。
ただし、何かをさせるために応用しようとする場合、動作理解が必要です。
学習する時間のあるかたは下記サイトを参照ください。
ここで説明も考えましたが、
まじめに、説明しようと思うとシフトレジスタだけで記事ができてしまうので・・・。
またの機会に。
シフトレジスタについて下記サイトにて詳しく記載されています。
実践 回路作成とコード作成
最初に回路図を確認してください。
次に、回路図に合わせて部品を接続します。
最後にコードを書いて、LEDの点灯、消灯で動作を確認していきましょう。
Arduinoのピン配置を確認したい方は番外編02を参照してください。
回路図
回路図がこちら。
LEDと抵抗が多いので接続が大変ですが、ある意味繰り返しの接続なので単純と言えます。
LEDが焼き切れるのを防ぐために電流制限抵抗は忘れずに入れてください。
こちらがブレッドボード図。
※M-M jumper wireのみで結線できます。
回路図は「fritzing」を利用しています。
「fritzing」の使い方は下記を参照してください。
接続
下図に示すように、用意した部品を使用して接続しましょう。
部品は8bitシフトレジスタ、LED、抵抗です。
LEDと抵抗の数が多いですが、頑張って接続しましょう!
使用するポートは、デジタル入出力ピンの「9、11、12」。
電源の「5V」、「GND」です。
穴に挿入しづらいときは、ラジオペンチなどを使用してください。
コードの書き込み
接続が終わったら、USBケーブルを使用してUNOにプログラムを書き込んで行きましょう。
今回は、Arduino公式サイトのShiftOutコードなどを参考に2つのサンプルコードを書いてみました。
参考にして、実践してみてください。
もちろん、サンプルコードをそのまま使っていただいてかまいません。
サンプルコードは一例です。
書き方は色々ありますので、ネットなど検索して見るのもよいかと思います。
コマンド説明
今回新たにでてくるコマンドを説明しておきます。
コマンド | 説明 |
---|---|
byte | 0から255までの8bitの数値を格納。 負の数値は扱えません。 例 変数に18(10進数)を代入。 byte value = B10010; ※Bは2進数を表しています。 |
bitSet(x,n) | 指定したビットをセットします。 セットする値は1です。 x:対象となる数 n:セットするビットの位置 右端(LSB)から数えて何ビット目か。 戻り値:なし 例 変数xの2ビット目を1にする。 bitSet(x,1); |
bitClear | 指定したビットをクリアします。 セットする値は0です。 x:対象となる数 n:クリアするビットの位置 右端(LSB)から数えて何ビット目か。 戻り値:なし 例 変数xの2ビット目を0にする。 bitClear(x,1); |
shiftOut(dataPin, clockPin, bitOrder, value) | 1バイト分のデータを1ビットずつ「シフトアウト」する。 最上位ビット(MSB)と最下位ビット(LSB)のどちらからもスタート可能。 各ビットはまずdataPinに出力され、その後clockPinが反転して、そのビットが有効になったことが示されます。 dataPin:各ビットを出力するピン clockPin: クロックを出力するピン。 dataPinに正しい値がセットされたら、このピンが1回反転します bitOrder: MSBFIRSTまたはLSBFIRSTを指定。 Most Significant Bit Firstは最上位ビットから送ること、Least Significant Bit Firstは最下位ビットから送ることを示す。 value:送信したいデータ (byte) 戻り値:なし |
サンプルコード1
サンプルコード1を下記に示します。
こちらは、LEDを順番に点灯させるサンプルコードです。
点灯するLEDは1つのみです。
//Lesson 20-1 8bitシフトレジスタを使ってLEDを順番に点灯1 //https://omoroya.com/ int tDelay = 200; //200ms遅延設定 int rclkPin = 11; // (11) ST_CP [RCLK] on 74HC595 int srclkPin = 9; // (9) SH_CP [SRCLK] on 74HC595 int dsPin = 12; // (12) DS [SER] on 74HC595 byte leds = 0; //ledsをbyte型としてb00000000で定義 void setup() { pinMode(rclkPin, OUTPUT); //11番ピンをOUTPUTとして定義 pinMode(dsPin, OUTPUT); //12番ピンをOUTPUTとして定義 pinMode(srclkPin, OUTPUT); //9番ピンをOUTPUTとして定義 } void loop() { // LED1からLED8までを順に光らせる。 for (int i = 0; i < 8; i++) { bitSet(leds, i); //bitbyte操作関数で指定したビットを1にする digitalWrite(rclkPin, LOW); //送信中のRCLKをLowにする shiftOut(dsPin, srclkPin, LSBFIRST, leds); //シフト演算を使って点灯するLEDを選択 digitalWrite(rclkPin, HIGH); //送信終了後RCLKをHighにする delay(tDelay); bitClear(leds, i); //点灯させたLEDのbitを0にして消灯させるための設定 } }
サンプルコード2
サンプルコード2を下記に示します。
こちらも、LEDを順番に点灯させるサンプルコードですが、
LEDが順番に全て点灯します。
その後、全てが消えて繰り返す動作となっています。
全て点灯したら消灯するようになっています。
//Lesson 20-1 8bitシフトレジスタを使ってLEDを順番に点灯2 //https://omoroya.com/ int tDelay = 200; //200ms遅延設定 int rclkPin = 11; // (11) ST_CP [RCLK] on 74HC595 int srclkPin = 9; // (9) SH_CP [SRCLK] on 74HC595 int dsPin = 12; // (12) DS [SER] on 74HC595 byte leds = B00000000; //ledsをbyte型としてb00000000で定義 void setup() { pinMode(rclkPin, OUTPUT); //11番ピンをOUTPUTとして定義 pinMode(dsPin, OUTPUT); //12番ピンをOUTPUTとして定義 pinMode(srclkPin, OUTPUT); //9番ピンをOUTPUTとして定義 } void loop() { // LED1からLED8までのレジスタを初期化。 leds = 0; //初期化設定、b00000000(8bitを0にする) digitalWrite(rclkPin, LOW); //送信中のRCLKをLowにする shiftOut(dsPin, srclkPin, LSBFIRST, leds); //全てのLEDを消灯 digitalWrite(rclkPin, HIGH); //送信終了後RCLKをHighにする delay(tDelay); // LED1からLED8までを順に光らせる。 for (int i = 0; i < 8; i++) { bitSet(leds, i); //bitbyte操作関数で指定したビットを1にする digitalWrite(rclkPin, LOW); //送信中のRCLKをLowにする shiftOut(dsPin, srclkPin, LSBFIRST, leds); //シフト演算を使って点灯するLEDを選択 digitalWrite(rclkPin, HIGH); //送信終了後RCLKをHighにする delay(tDelay); } }
サンプルコード1とサンプルコード2の違いを考えてコードを読んでみると理解がし易いと考えます。
動作確認
では、さっそく動作を確認していきます。
といっても、動画ではないので順番に点灯しているのを表現するのは難しい・・・。
ぜひ、実践して確かめてみてください。
サンプルコード1の結果
点灯するLEDは1つのみです。
順番に左から右へ点灯が移っていきます。
一番右までいったら、始めに戻り繰り返します。
サンプルコード2の結果
こちらは、左から順番にLEDが点灯します。
全て点灯したら消灯して、始めに戻り繰り返します。
いかがでしょうか?
色んな色のLEDを使うととっても綺麗です!
まとめ
今回は以下の内容について理解しました。
今回も項目3の遊ぶことが一番の目標でした。
2.「8bitシフトレジスタを使い複数のLEDを制御することを理解」する。
3.楽しんで遊ぶ。
1.に関しては、時間をかけてゆっくりと理解してみてください。
参考になるサイトはたくさんあります。
最後に、本Lessonも、「遊ぶというところが一番大事」なところです。
いかがだったでしょうか。
Lesson 20 シフトレジスタによる複数LED制編はここまで。
ぜひ、みなさんも子供と一緒にやられてみることをお勧めします。
8bitシフトレジスタについては、別記事にて詳細を説明できればなと考えています。
しかし、ボリュームがありすぎて躊躇しています・・・。
次回Lesson 21は【シリアルモニタによるLED制御編】です。
最後に
疑問点、質問などありましたら気軽にコメントください。
この電子部品の解説をしてほしい!などなどなんでもOKです。
リンク切れ、間違いなどあればコメントいただけると助かります。
Arduino入門編、番外編、お役立ち情報などなどサイトマップで記事一覧をぜひご確認ください。
Arduino入門編、Arduino入門編2で使用しているUNOはAmazonにて購入可能です。
Arduino入門編では互換品を使用。
Arduinoはオープンソース。
複製して販売するのもライセンス的に問題なし。
そのため互換品の品質も悪くなく、それでいて値段は安いです。
正規品本体の値段程度で豊富な部品が多数ついています。
学習用、遊び用、お試し用には安価な互換品がおすすめです。
ELEGOO UNO キット レベルアップ チュートリアル付 uno mega2560 r3 nanoと互換 Arduino用
上記のものでも十分に多数の部品が入っていますが、最初からもっと多数の部品が入っているこちらもお勧めです。
Arduino入門編2では「Arduino UNO R4 Minima」「Arduino UNO R4 WIFI」にて遊ぶため今のところは正規品を使用。(まだ互換品が・・・ほぼない)
Amazonでお得に買う方法
Amazonでお得に購入するならAmazon Mastercard、Amazonギフト券がおすすめです。
時期により異なりますが、様々なキャンペーンを実施しています。
\Amazonギフト券/
Amazonギフトカード キャンペーン
\Amazon Mastercard お申込み/
Amazon Mastercard 申し込み
いずれの場合もプライム会員である方がお得!!
\Amazon Prime 30日間の無料会員を試す/
無料会員登録
コメント
趣味で電子工作を楽しんでいる者です。
おもろ家さんの記事はとても分かりやすく今まで何度も何度も助けられております。
要望なのですが、ぜひ74HC595のデイジーチェーン(数珠繋ぎ)制御について取り上げて頂けないでしょうか!!
1つの74HC595で制御できるのは8ピンと限りがあるため、多くのLEDや7セグを使いたい場合には出力ピン数が不足してしまいます。
他ブロガーさんにも74HC595のデイジーチェーンについて書かれている方はいらっしゃるのですが、記事を参考に回路やプログラムを組んでもなぜか上手く動かないものが多く、解説もおもろ家さんのそれと比べると初心者にとっては説明不足なものが多いのです。
ぜひご検討いただければと思います!
コメントありがとうございます。
最近、色々とあり更新が滞りがちです・・・。
8月は時間ができそうな予感・・・。
検討してみます。
といっても、期待せずお待ちください。
こんにちは。
初心者の佐藤と申します。
おバカな質問をするかもしれませんが、よろしくお願いします。
早速ですが、質問をします。
「RFID-RC522」の部品を使った、サンプルスケッチが、まだ入ってなかったら、ご迷惑おかけしますが、作ってくださりたいんですが・・・いいでしょうか?
コメントありがとうございます。
申し訳ないですが、手元に「RFID-RC522」がありません。
こんにちは
記事、とても参考になりましたありがとうございました。
しかし、2点ほど質問したいことがあるので迷惑でなければお願いします。
まず1点目
今回の回路でdigitalpinを挿すピンを変えても動きますか?
2点目
今回はLEDを光らせるということでOUTPUTで使われていましたがINPUTにして、複数のセンサー情報を逆に読み込むようなことは可能でしょうか?
迷惑でなければよろしくお願いします。
こんんちは。
記事を読んでいただいてありがとうございます。
1点目、使用するピンとスケッチの対応がとれていれば変えても動きます。
2点目、8bitシフトレジスタで複数センサを制御してセンサの情報を読み取るということでしょうか?
であれば難しいと考えます。
omoroya様
初めてコメントします。素人の工作者なのですが、このサイトにたどり着いて参考にさせていただいています!わかりやすくてとても助かっています。
ご迷惑でなければ一つ質問があるのですが・・・
シフトレジスタを使用して増やしたLEDをぼんやり点灯→消灯しながら光が流れるようにするのは可能なのでしょうか?LEDを個別のアナログピンでPWM制御する方法までは分かったのですが、ピンの数以上のLEDを制御したくて・・・
素人なので質問内容自体が間違っていたり意味不明かもしれません。お時間がありましたらお答えいただけると幸いです。
これからも応援しています!
アオキノコ
コメントありがとうございます。
記事更新のはげみになります!
色々な方法があると思いますが、Lesson 20のスケッチを利用する場合は
for文を2重ループにすればできるのではと考えます。
内側のfor文でPWM制御、外側のfor文で点灯させるLEDを制御する見たいな感じです。
時間ができたら、スケッチを作成してみます。