こんにちは、「メカのりまき」です。

この記事では、「7セグメントLED」と「シフトレジスタ(74HC595)」の使用方法について、説明したいと思います。

本記事で使用するもの

本記事で私が使用した物は以下の通りです。

  • 「Arduino IDE2.1.0」をインストールしたPC(Windows11)
  • USBケーブル
  • Arduino Uno R3(ELEGOO UNO R3でも可)
  • 7セグメントLED
  • シフトレジスタ(74HC595)
  • 抵抗器
  • ブレッドボード
  • ポテンショメータ(可変抵抗器)
  • ジャンパーワイヤー

「Arduino Uno R3」の互換ボードであれば、「ELEGOO UNO R3」以外のボードでも、本記事と同様な手順で動作可能だと思われますが、動作検証はしていないので、その点はご了承ください。

以下のリンクのスターターキットを購入した場合、上記で述べた使用するものは、PC以外すべて入手することができます。

Arduinoをまだ購入していないという方やArduinoで動かすことができるたくさんのパーツが欲しいという方は、購入を検討してみてください。

7セグメントLEDの説明

7セグメントLEDは、以下の画像のような見た目をした部品で、英数字を表示させるときなどに使用されます。

7セグメントLEDの写真

7セグメントLEDは、7個のLED(ドット表示を入れると8個のLED)を1つの部品にまとめたものであり、それらのLEDの点灯を制御することにより、英数字を表示させることができます。

7セグメントLEDの表示

7セグメントLEDのピンは、それぞれ各LEDと共通で使用される線に繋がっています。

ここで、線の繋がり方は、LEDのカソード側(マイナス側)が共通となっている「カソードコモン」、アノード側(プラス側)が共通となっている「アノードコモン」の2種類があるので注意が必要となります。

7セグメントLEDの接続

本記事では、上記で紹介したスターターキットの中に、入っている「カソードコモン」の7セグメントLEDを使用して説明をしていきたいと思います。

「アノードコモン」の7セグメントLEDをお使いになる方は、これから説明する回路やスケッチを、少し訂正する必要があるので、注意をしてください。

7セグメントLEDを試す

まず初めに、以下の動画のように、7セグメントLEDに0~9の数字とドット( . )を表示させる方法について説明したいと思います。

空のスケッチを書き込む

回路を作成する前に、空のスケッチ(「ファイル」タブの「New Sketch」をクリックしたときに出てくる何の処理も書かれていないスケッチ)を書き込みます。

空のスケッチを書き込む

そうすることにより、前に書き込んだスケッチが、新しく作成しようとしている回路に影響を及ぼすことを防げます。

新しい回路を作成するときは、いつもこの作業をやっておくと、安全に回路を作成することができます。

回路を作成する

以下の回路を作成してください。

7セグメントLEDを制御する回路(カソードコモン)

上記の回路は「カソードコモン」の7セグメントLEDを使用した場合のものです。

「アノードコモン」のものを使用する場合は、共通の線に繋がるピンを「GNDピン」ではなく、「5Vピン」に接続します。

7セグメントLEDを制御する回路(アノードコモン)

また、同じ1桁表示の7セグメントLEDでも、ピンの配置が異なる場合がございますので、仕様書などを確認して、それぞれの接続の対応を確認して回路を作成してください。

抵抗器の電気抵抗の高さは、LEDの順電圧と順電流から計算で求めます。

以下に、直列に繋げる抵抗器の電気抵抗の高さを計算するツールを用意しましたので、ご活用ください。

順電圧VF

[V]

順電流IF

[mA]

直列に繋げる抵抗器の電気抵抗

R = [Ω]

回路で使用する抵抗器は、上記のツールで求めた電気抵抗よりも少し高い電気抵抗のものを使用します。

上記のツールが行っている電気抵抗の計算方法については、以下のリンク先の記事で説明していますので、気になる方はご覧になってください。

ここで、電気抵抗の計算が行えない場合は、電気抵抗が高いもの(大体1[kΩ])から順番に接続していき、ちょうど良い明るさになるものを探していきます。

その際、電気抵抗を低いものにすれば、その分点灯が明るくなるのですが、電気抵抗が低すぎるもの(大体100[Ω]を下回るくらい)の場合、LEDの寿命を縮めてしまったり、破壊してしまったりすることがあるので注意してください。

今回、私は220[Ω]の抵抗器を使用しています。

スケッチを書き込む

回路の作成が終わりましたら、以下のスケッチを書き込んでください。

上記のスケッチは「カソードコモン」の7セグメントLEDを使用した場合のものです。

「アノードコモン」のものを使用する場合は、LEDの点灯、消灯と出力の「HIGH」と「LOW」の関係が逆となるため、「bool Output_~[]={~}」の{ }内の「0」と「1」を全て反転させる必要があります。

例:「bool Output_0[]={1,1,1,1,1,1,0,0}」を、「bool Output_0[]={0,0,0,0,0,0,1,1}」のように変更する。

もしくは、「digitalWrite()」の中の「Output_~[i]」の前に「!」を追加し反転させるという方法もあります。

例:「digitalWrite(LED_pin[i],Output_0[i])」を、「digitalWrite(LED_pin[i],!Output_0[i])」のように変更する。

スケッチと回路が正しければ、先程の動画のように、0~9の数字とドット( . )が、一定の間隔で表示されていくのが確認できます。

スケッチの解説

今回行っている処理は、「digitalWrite()」でLEDの点灯を制御しているだけなので、LEDの制御を行ったことがある方にとっては、それほど難しいものではありません。

ただし、スケッチをコンパクトで見やすいものにするために、「配列」というものを使用していますので、その辺りについて、説明していきたいと思います。

ここで、LEDの制御を行ったことが無いという方は、以下のリンク先の記事で、LEDを制御する方法を説明していますので、是非ご覧になってください。

では、今回スケッチで使用した配列について、説明をしていきたいと思います。

「配列」というのは同じ型の要素(変数など)をまとめたものです。

例えば、2行目に記述している「int LED_pin[8]={2,3,4,5,6,7,8,9}」は「int型」の要素(変数)を8個まとめたものとなっています。

配列の説明

宣言した配列の要素には、0から順に番号が割り振られており、読み書きを行う際に割り振られた番号を指定します。

配列の要素の説明

ここで、今回のスケッチの「void setup()」を見てみると、以下のような文が記述されています。

これは、「for文」と配列を利用して、「LED_pin」に入れた8個の番号のピンを出力ピンとして設定をしています。

上記の文の処理の流れとしては、以下のようになります。

数字を表示させる処理の説明

次に「void loop()」内にある、各数字を表示させる文について、説明をしたいと思います。

スケッチの28行目から30行目を見ると以下のような文が記述されています。

こちらも、「for文」と配列を使うことにより、各ピンの出力を制御しています。

「digitalWrite()」の2番目の引数は、「LOW」、「HIGH」という文字以外にも、「0」、「1」や「false」、「true」などを入れて出力を制御することができます。

今回のスケッチでは、「bool型」の「Output_~[]」という配列を用意して、表示させたい数字に対応するように出力を制御しています。

7セグメントLEDと出力ピンの接続
表示される数字7セグメントLEDの対応ABCDEFGDP
for文の変数 i01234567
LED_pin[8]23456789
0Output_0[8]11111100
1Output_1[8]01100000
2Output_2[8]11011010
3Output_3[8]11110010
4Output_4[8]01100110
5Output_5[8]10110110
6Output_6[8]10111110
7Output_7[8]11100000
8Output_8[8]11111110
9Output_9[8]11110110
.Output_dot[8]00000001
※「OUTPUT_~[8]」の数値が「1」のとき「HIGH」,「0」のとき「LOW」

よって、「1」から「9」までの数字と「 . 」が、間隔を空けながら順番に表示されるということになります。

シフトレジスタ(74HC595)の説明

次は、シフトレジスタ(74HC595)を使って、7セグメントLEDを制御する方法について説明したいと思います。

シフトレジスタ(74HC595)は、以下の画像のような見た目をした部品で、マイコン側で使用する出力ピンの数を節約したいときなどに使用されます。

74HC595の写真

シフトレジスタ(74HC595)には、データを受け取るためのピンと出力をするためのピンがあり、受け取ったデータに応じて出力を制御します。

その際、マイコン側は3個の出力で、データを送信することで、8個の出力を制御するといったことができるため、マイコン側は出力ピンの節約ができるということになります。

シフトレジスタの入力と出力

シフトレジスタ(74HC595)の各ピンの役割は以下のようになっています。

74HC595のピン名称
ピンの名称ピンの役割
VCC電源の+(今回は5V)
GND電源の-(GND)
QA~QH出力ピン
QH‘シフトレジスタの最上位ビットの状態を出力(今回は使用しない)
OEHIGH:出力を無効
LOW:出力を有効
(今回は出力を常に有効にするためGNDに接続)
RCLK出力の状態を切り替える際に使用するクロック信号を入力
SER出力を制御するためのデータを入力
SRCLKデータを取り込むタイミングを制御するためのクロック信号を入力
SRCLRHIGH:データを保持する
LOW:データをクリアする
(今回はデータを常に保持するため5Vに接続)

今回は、Arduinoで3個の出力ピンを制御することにより、シフトレジスタの8個の出力を制御します。

これから行おうと思っているデータの送信と出力の流れは、以下のような感じになります。

74HC595の入力と出力の関係

ここで、「SER」と「SRCLK」のデータ送信は、「shiftOut()」という関数を使うことにより、簡単に行うことができます。

よって、今回スケッチで行うのは、「shiftOut()」を使った「SER」と「SRCLK」への出力と「digitalWrite」を使った「RCLK」への出力の制御ということになります。

74HC595で7セグメントLEDを制御する

では、以下の動画のようにシフトレジスタ(74HC595)を使って、7セグメントLEDに0~9の数字とドット( . )を表示させる方法について説明したいと思います。

空のスケッチを書き込む

回路を作成する前に、Arduinoに差し込んでいるピンを抜いた状態で、空のスケッチ(「ファイル」タブの「New Sketch」をクリックしたときに出てくる何の処理も書かれていないスケッチ)を書き込みます。

空のスケッチを書き込む

そうすることにより、前に書き込んだスケッチが、新しく作成しようとしている回路に影響を及ぼすことを防げます。

新しい回路を作成するときは、いつもこの作業をやっておくと、安全に回路を作成することができます。

回路を作成する

以下の回路を作成してください。

74HC595で7セグメントLEDを制御する回路(カソードコモン)

上記の回路は「カソードコモン」の7セグメントLEDを使用した場合のものです。

「アノードコモン」のものを使用する場合は、共通の線に繋がるピンを「GNDピン」ではなく、「5Vピン」に接続します。

74HC595で7セグメントLEDを制御する回路(アノードコモン)

スケッチを書き込む

以下のスケッチを書き込んでください。

上記のスケッチは「カソードコモン」の7セグメントLEDを使用した場合のものです。

「アノードコモン」のものを使用する場合は、LEDの点灯、消灯と出力の「HIGH」と「LOW」の関係が逆となるため、「byte Output_Num[11]」内の「0」と「1」を全て反転させる必要があります。

例:「B11111100」を、「B00000011」のように変更する。

もしくは、「byte Output_Num[11]」内の「B~」の前に「~」を追加し、反転させるという方法もあります。

例:「B11111100」を、「~B11111100」のように変更する。

「~」はビット演算に使用される記号で、全てのビット(「0」と「1」)を反転させることができます。

スケッチと回路が正しければ、先程と同様に、0~9の数字とドット( . )が、一定の間隔で表示されていくのが確認できます。

スケッチの解説

7セグメントに対しての出力は、先程のスケッチと同様ですが、シフトレジスタ(74HC595)を介しているので、出力を制御する方法が異なります。

では、シフトレジスタ(74HC595)の出力を制御している部分について説明したいと思います。

37行目から39行目を見ると以下のような文が記述されています。

これが、上記で説明をした、データの送信と出力の切り替えを行っている部分となります。

処理の内容としては、まず、「RCLK」に接続しているピンの出力を「LOW」にして、その後、「shiftOut()」という関数を使うことで、出力に関わるデータを「SER」、「SRCRK」で送信しています。

そして、最後に、「RCLK」に接続しているピンの出力を「HIGH」にすることによって、出力の切り替えを行い、各数字を表示させているという流れになります。

ここで、「shiftOut()」について、もう少し説明をしたいと思います。

「shiftOut()」の引数は4つあり、それぞれ以下のように指定をします。

shiftOut関数

今回のスケッチでは、1番目の引数を「SER」、2番目の引数を「SRCRK」に接続したピン番号としています。

また、4番目の引数は配列「Output_Num[i]」とすることにより、繰り返しの回数に応じた1バイト(8ビット)のデータを送信しています。

ここで、3番目の引数は、「LSBFIRST」としています。

3番目の引数は、データを送信する順番を指定するためのもので、今回の場合、送る順番が異なるとシフトレジスタの出力結果が異なります。

「LSBFIRST」でデータを送信した場合と、「MSBFIRST」で送った場合の出力の違いを図にまとめると以下のようになります。

LSBFIRSTのときの出力
MSBFIRSTのときの出力

このように、データを送る順番によって、受け取る側が認識するデータは異なってきます。

よって、データを送る順番は、受け取る側の仕様を理解した上で決める必要があるので注意してください。

4桁の7セグメントLEDの説明

続いて、以下の画像のような、4桁の7セグメントLEDを制御する方法について、説明したいと思います。

4桁の7セグメントLEDの写真

この7セグメントLEDは、見た目の通り、各LEDを制御することで、4つの英数字を表示させることができます。

よって、使用されるLEDは、8×4で32個なのですが、ピンの数が12本しかありません。

(ピンの数が異なるものの場合は、以下で説明する方法では動作しないと思われますのでご注意ください。)

では、どのようにして、32個のLEDを12本で制御するのか説明したいと思います。

まず、この7セグメントLEDの線の繋がりを確認すると以下のようになっています。

4桁の7セグメントLEDの接続(カソードコモン)

なんと、各桁の「A」~「G」と「D.P.」のLEDがすべて繋がっています。

これでは、一番左の桁に「0」と表示させようとしたときに、他の桁も「0」と表示されてしまうと思われる方もいらっしゃるかもしれませんが、大丈夫です。

各桁の共通の線である「DIG~」を出力ピンに接続することによって、各桁のLEDの点灯を制御することができます。

4桁の7セグメントLEDの表示(カソードコモン)

でも、「1234」のように、別々の数字を同時に表示させるにはどうすれば良いのだろうと思われる方がいらっしゃるかもしれません。

結論を先に述べると、4桁で異なる数字を同時に表示させることはできません。

しかし、4桁で異なる数字を同時に表示させているかのように見せることは可能です。

以下で、4桁の7セグメントLEDを制御する方法と4桁で異なる数字を同時に表示させているかのように見せる方法について、説明をしていきたいと思います。

本記事では、上記で紹介したスターターキットの中に、入っている「カソードコモン」の7セグメントLEDを使用して説明をしていきたいと思います。

「アノードコモン」の7セグメントLEDをお使いになる方は、これから説明するスケッチを、少し訂正する必要があるので、注意をしてください。

「アノードコモン」の場合は、以下のような線の繋がりになっています。

4桁の7セグメントLEDの接続(アノードコモン)
4桁の7セグメントLEDの表示(アノードコモン)

4桁の7セグメントLEDを制御する

では、以下の動画のように、4桁の7セグメントLEDの表示を制御する方法について説明したいと思います。

回路を作成する

以下の回路を作成してください。

4桁の7セグメントLEDを制御する回路

ダイナミック点灯を行う4桁の7セグメントは、共通の線も出力ピンに接続して、出力の制御をするため、「カソードコモン」、「アノードコモン」のどちらの場合も同じ回路になります。

ただし、同じ4桁の7セグメントLEDでも内部の配線の仕方が異なる場合がございますので、仕様書などを確認し、上記で説明した配線と一致しているかを確認してください。

ピンの数が異なるものなどは、今回説明する回路やスケッチでは動作しないと思われますので、ご注意ください。

スケッチを書き込む

以下のスケッチを書き込んでください。

ここで、配列「Output_Num」に全ての出力を「LOW」にするための要素を追加しているので、注意してください。

配列の要素を追加する際、要素数の変更や「カンマ( , )」の追加を忘れないように注意してください。

上記のスケッチは「カソードコモン」の7セグメントLEDを使用した場合のものです。

「アノードコモン」のものを使用する場合は、LEDの点灯、消灯と出力の「HIGH」と「LOW」の関係が逆となるため、先程と同様に「byte Output_Num[12]」内の「0」と「1」を全て反転させる必要があります。

また、「DIG_~」の「HIGH」と「LOW」についても全て逆になるので、注意してください。

例:「digitalWrite(DIG_1,LOW)」を「digitalWrite(DIG_1,HIGH)」のように変更する。

スケッチと回路が正しければ、先程の動画のように、1~4の数字が、間隔を空けながら表示されていき、最後には4つの数字が同時に表示されているように見えるのが確認できます。

スケッチの解説

今回のスケッチでは、先程のスケッチのような各LEDに対しての出力だけではなく、各桁の共通の線に対しての出力も追加で制御しています。

各桁に数字を表示させる流れは以下の図のようになります。

4桁の7セグメントに1234を表示させる処理の流れ

ここで、各桁のLEDを点灯させる間隔は、「delay(2000/i/i+1)」によって制御しており、「for文」による繰り返し回数が多くなると待機時間は短くなっていきます。

ここで、「2000/i/i」の部分は「int型」なので、計算結果が「1」を下回ると値は「0」となり、「+1」の部分により、「delay(1)」となります。

繰り返した回数と待機時間の関係をグラフにすると以下のようになります。

繰り返しの回数と待機時間の関係

ここで、後半部分の「1234」が同時に表示されている部分というのは、「delay(1)」の状態で繰り返されている部分になります。

実は、各桁の点灯を切り替えるスピードが速すぎると、人間はそれを目で追うことができなくなります。

よって、待機時間がある値より短くなると、各桁の数字が同時に表示されているように見えるということになります。

4桁同時に表示されているように見える理由

カウントした値を4桁の7セグメントLEDで表示する

上記までの説明で、4桁の7セグメントLEDに数字を表示させる方法については、理解していただけたかと思います。

次は、以下の動画のように、4桁の7セグメントLEDに表示させている数値を、時間に応じて変化させる方法について説明したいと思います。

実は、先程説明したダイナミック点灯には、大きな弱点があります。

それは、常にLEDを点灯させる処理を行い続けなければ、4桁の表示を行うことができないというところです。

例えば、1秒ごとに表示されている数値を変化させていくような処理をしようと思い、「void loop()」の中に、delay(1000)などを入れると、LEDの表示が止まってしまうという結果になってしまいます。

表示させる処理を途中でやめた場合

また、ダイナミック点灯を行っている速いループの中で、数値を変化させた場合、数値の変化を目で追うことができず、数字が重なって見える現象が生じてしまうので、ある時間以上の間隔を空けながら数値を変化させる必要がでてきます。

(数値の変化が速すぎる場合、先程の動画の1桁目のような感じになります。)

よって、ダイナミック点灯を使用しつつ、数値を変化させるような処理をしたい場合は、タイマ割り込みなどを利用して、4桁の表示を行う処理を邪魔しないように、数値を変化させていく必要があります。

スケッチを書き込む

今回は、「MsTimer2」ライブラリを利用して、0.01秒ごとに表示されている数値を1増やすようなスケッチを、作成します。

「MsTimer2」のインストール方法や使い方については、以下のリンク先の記事で説明していますので、「MsTimer2」を使用したことがないという方は、先に以下のリンク先の記事をご覧になってください。

以下のスケッチを書き込んでください。

上記のスケッチは「カソードコモン」の7セグメントLEDを使用した場合のものです。

「アノードコモン」のものを使用する場合は、LEDの点灯、消灯と出力の「HIGH」と「LOW」の関係が逆となるため、先程と同様に「byte Output_Num[12]」内の「0」と「1」を全て反転させる必要があります。

また、「DIG_~」の「HIGH」と「LOW」についても全て逆になるので、注意してください。

スケッチが正しければ、先程の動画のように、一番右の数字は目で追うことができず、数字が重なって見えていますが、表示されている数値が増えていくのが確認できます。

スケッチの解説

「void loop()」内にあるLEDの点灯を制御する部分については、基本的に先程のスケッチと同じです。

明るさ調節のために「delay()」を入れていますが、無くても表示は行うことができます。

ただし、「delay()」が無い場合、LEDが点灯している時間が相対的に短くなるため、LEDの明るさは「delay()」があるときと比べて、若干暗くなります。

「delay()」での待機時間が、長い方がLEDの明るさは明るくなるはずですが、長くしすぎると今度は点滅が気になります。

私の体感ですが、「delay()」と点滅の認識の関係は以下のような感じになります。

待機時間と点滅の見え方

どうしても、LEDの明るさが気になる場合は、電気抵抗の小さい抵抗器に変えるなど、抵抗器を調節するほうが良いかもしれません。

ただし、電気抵抗を小さくしすぎて、LEDを破壊しないように注意してください。

表示されている数値は、「MsTimer2」を使い、0.01秒ごとに「Count_Up()」という関数が実行させ、countを1増やしていくことにより変化をさせています。

ただし、countの値を表示させる際には、1桁の数字に分解していく必要があります。

1桁ずつに分解しているのは、145~148行目の以下の文になります。

上記の文は、「count」の値を、1桁ずつ分解して、配列「Count_Num[0]」に格納するという処理を行っています。

処理内容をまとめると以下のようになります。

桁ごとに数字を分解する方法

そして、配列の要素に格納した値を、「void loop()」内にある「Output_Num[]」の要素指定を行う際に利用することにより、「count」に応じた数値を表示させているということになります。

終わりに

皆さん上手く数字を表示させることはできたでしょうか。

今回の最後のスケッチでは、時間に応じて変化する数値の表示を行いましたが、測定にかかる処理時間が短いものであれば、割り込み処理時に呼び出される関数「Count_Up()」の中身を変更することで、一定間隔ごとに、何かを測定して表示させるといったことも可能です。

ただし、一番右の数値は変化が速すぎるせいで、目で追うことができず、数字が重なって見える現象が生じています。

また、右から2番目の目の数値は、目で追うことはできますが、少し読みづらいです。

よって、何かの測定結果を、4桁の7セグメントで表示させる際には、状況によりますが、0.1秒以上は間を空けて、数値を変化させたほうが、良いと考えられます。

数値を変化させるタイミングは、58行目の「MsTimer2::set(10,Count_Up)」の数値を変えることで、変更することができるので、色々と試してみてください。

次回の記事では「チルトスイッチ」の使い方について説明したいと思います。

本記事はここまでです。ご清覧ありがとうございました。

広告

楽天モーションウィジェットとGoogleアドセンス広告です。

気になる商品がございましたら、チェックをしてみてください。