今回は、Iduinoスタータキットに入っていた、LED表示装置の中から、7SEG表示器を使ってみようと思います。
7SEGについては、「第4回 シフトレジスタを使ってみる」で少し触れました。あの時は、最初に購入したELEGOOスタータキットの中に7SEGが入っていなかったので、普通のLED×8個で実験しました。今回使うのは、以下の様な1桁表示の7SEG LEDです。
7SEGって言ってしまいますけど、実際には、ピリオドが追加されているので、8セグメント(8SEG?)です。例によって、データシート探しからスタートです。側面に印字された「5611AS」が型番と見て検索したところ、データシートが見つかりました。
5611Axと5611Bxがある様です。"x"の部分のアルファベットはLEDの色で、"S"は「Super Red」だそうです。5611Aと5611Bの違いは、コモン(共通)端子がカソード(5611A)か、アノード(5611B)か、の違いでした。ここまでわかったら、以下の様な回路図を引くことができます。
アノードコモンの場合は、回路と使い方が異なるのでご注意ください。
ブレッドボード上に構成します。
「第4回 シフトレジスタを使ってみる」で作成したプログラムがそのまま使えますので、実行してみます。
プログラム:shift_8led.ino
Arduinoにプログラムを転送したら、シリアルモニタを開いて16進数2桁(a〜fは小文字)を入力して送信します。送信した数値がLSBファーストでシフトレジスタ74595にシフトインされますので、数値のMSBがQA、LSBがQHにセットされます。入力する数値と点灯するセグメントの関係を以下図に示します。
シリアルモニタで「84」を送信すると、上図でAとFのセグメントが点灯するはずです。後はこの調子で、0〜9の数字に見える点灯パタンをテーブルに起こします。
表示する数字 | 点灯させるセグメント | コード |
0 | A+B+C+D+E+F | 0xfc |
1 | B+C | 0x60 |
2 | A+B+G+E+D | 0xda |
3 | A+B+G+C+D | 0xf2 |
4 | F+G+B+C | 0x66 |
5 | A+F+G+C+D | 0xb6 |
6 | A+F+E+D+C+G | 0xbe |
7 | F+A+B+C | 0xe4 |
8 | A+B+G+E+D+C+F | 0xfe |
9 | A+F+G+B+C+D | 0xf6 |
A | E+F+A+B+C+G | 0xee |
b | F+E+G+C+D | 0x3e |
C | A+F+E+D | 0x9c |
d | B+C+G+E+D | 0x7a |
E | A+F+E+G+D | 0x9e |
F | A+F+E+G | 0x8e |
16進数1桁分を表示できるように、拡張してあります。うまく表現できないため、"b"と"d"だけ小文字です。表示に使用するコードは、全てが偶数になっていて、コード+1して奇数にすると、ピリオド部分のセグメントが点灯します。
7SEG表示用に先ほどのプログラムをちょっと修正してみます。
7SEG表示プログラム:shift_7seg.ino
Arduinoへコンパイル&書き込みしたらシリアルモニタを開いて、今度は16進数1桁を打ち込んで送信します。数字の後ろにピリオドを付けて送信すると、ピリオド部分が光ります。
Iduinoスタータキットには、もう一つ、4桁表示できる7SEGが入っていました。
端子数12本。こちらも、側面に印字してある「SMA420564L」が型番とみて検索したのですが、こちらは見つかりません。あまり出回っていない部品なのでしょうか?少しづつ文字を削ったりして検索してみたところ、「SMA42056」のデータシートが見つかりました。
「SMA42056」は、1桁の7SEG LED表示器で、カソードコモンタイプだとわかりました。だとすると、最後に付加された「4L」は、4桁表示を表している可能性が高いと推測しました。
今度は、他の一般的な4桁表示7SEG LEDのデータシートを探して、端子の割り当てを確認しました。同じ端子数なら、たぶん同じ接続でしょ?っていう、安易な考えです。
上図は、端子配置を確認しているところ。UNOが映り込んではいますが、電源をもらっているだけです……。端子にGNDと、プルアップしたジャンパ線を当ててみて、光るセグメントを確認しています。
確認した結果は、他の一般的な4桁7SEG表示器と同じピン配置で、確かにカソードコモンでした。
ここで、ハタと困ることになります。端子数12本は、圧倒的に少なすぎます。8個のLEDが4桁分ですので、カソードをコモンにしたとしても、優に33本(=8LED×4桁+1コモン)は必要なはずです。一般的な4桁LEDのデータシートを見てみたところ、各桁同じセグメント(LED)のアノードが共通につながっています。これでは、4桁とも同じ数値しか表示できません。
データシートのアプリケーションノートに載っている回路図を見て、やっと意味が通じました。以下回路図の様に使用する必要があるみたいです。
4つのNPNトランジスタは、スイッチとして使います。Arduinoのデジタル端子で、NPNトランジスタのON/OFFを制御して、各桁のコモンカソードをGNDに落とすかどうか、選択します。NPNトランジスタがONして、GNDに落ちた桁だけが光ります。以下図のように、ある瞬間は左端が光り、次の瞬間は左から2番目が光り、……と、時分割で光る桁を変えて表示します。
この切り換えを非常に高速に行うと、人間の目の残像によって、全ての桁が光っているように見えます。
原理はわかりましたが、大変ですね……。さっきの1桁7SEGの様に、一度端子設定したらその表示状態を維持し続けてくれるのと違って、4桁7SEGは、ずっとArduinoが面倒を見てやらないと、表示を継続できないということです。
なるほど、そのためにMAX7219があるんですね。MAX7219については、「#2-6 ドットマトリクスLEDを使う」で使用しましたので、ご覧ください。MAX7219を使うと、表示すべきデータを送信しさえすれば、勝手にその表示状態を維持してくれます。8×8 LEDに搭載されているMAX7219はICソケット実装でしたので、ソケットからひっこ抜いてきて使うこともできますが、MAX7219は既に一度使ったので(SPI叩くだけで簡単だったし……)、今回はアプリケーションノート通り、上に示した回路図で表示させてみます。
Iduinoスタータキットの中に、NPNトランジスタが10個、マーク"2222A"×4個とマーク"S8050"×6個が入っていました。正直、CMOSロジック専門でしたので、トランジスタの選び方がわかりません└(1^^;)┘。データシートで絶対最大定格等を見比べてみましたが、所詮、電気的スイッチとしてしか使わないし、LED 8個分しか電流も流れないので、「どっちでもいいな」って結論です……。数量的に余裕のある"S8050"を使うことにしました。
※S8050は1E,2B,3Cの並び順でした。
最初の1桁7SEGとの合わせ技なのですが、シフトレジスタ74595を使っているので、毎回シフトインしてください。また、シフトインしたデータをラッチするRCLKと、NPNトランジスタをON/OFFするタイミングをうまいことコントロールしてください。
さっき使ったshift_7seg.inoでは、シフトイン関数の中で、シフトイン直後にラッチ(RCLK)してしまっていたので、このあたりの関数は少し手を加える必要があります。
各桁の表示(点灯)時間をパラメータmsec_digit(単位ms)に保持して、変更可能にしておきます。自然、4桁のリフレッシュレートは、1/(4×msec_digit)[kHz]になります。
他にもいくつか実験してみたいことがあるので、以下の様なコマンドを受け付けるようにしておきます。
回路図で、Arduino側のデジタル端子(番号)が飛んでいたのでお気づきかもしれませんが、UNOでPWM出力可能な端子を選んでいます。他の機体で使う場合には、ピンアサインを変更する必要があるかもしれません。【pwm】コマンドでデューティを設定すると、LEDの明るさを調整することができます。
プログラム:shift_7seg4d.ino
実行サンプル:【 】内はシリアルモニタからの送信データ
【dsp,1234】
OK: 1234 …… "1234"が表示
【dsp,abcd】
OK: ABCD …… "AbCd"が表示
【msc,20】
OK: 20ms, 12.50Hz …… 表示がちらつく
【pwm,64】
OK: 64, x0.25 …… 暗くなる
時分割で各桁(4桁)を表示している関係で、理論上、元の明るさの1/4程度に暗くなっています。時分割で表示するには、ちょっと、LEDの電流制限抵抗が大きかったかもしれませんね。筆者が使ったのは5.1kΩでした。【pwm】コマンドで最大輝度【pwm,255】を設定しても、あんまり明るくありません……。必要に応じ、抵抗値で調整してください。
【msc】コマンドでリフレッシュレートを落とす(【msc,15】)と、ちょっと表示がちらつくのですが、それが昔の真空管表示器みたいで、逆にお洒落です。
「#2-5 リアルタイムクロックを使ってみる」で使ってみた、RTCモジュールがありましたね。RTCと組み合わせて、時計を表示してみます。既に、結構派手にI/Oポートを使ってしまっているのですが、RTCに必要なI/Oポートは3端子でしたので、ギリギリ何とかつながります。
デジタル端子14本の内、7SEG表示に8本使用しています。RTCに3本を追加して11本、更に2本は非同期シリアル通信用のRX/TXですので、残るは1本のみ、ギリギリでした。やはり、色々なモジュールを繋ぎ始めると、I/Oポートが足りませんね。表示に8本も使うのは、かなり厳しいです。
デュポンワイヤでRTCモジュールを繋いだだけですので、回路図と回路写真は省略します。
Arduino | 接続 | RTCモジュール(DS1302) |
5V | → | VCC |
GND | ⇔ | GND |
D8 | → | CLK |
D12 | ⇔ | DAT |
D13 | → | RST |
時計表示プログラムをリンクしておきます。
時計表示プログラム:rtc_clock.ino
あまり頻繁にRTCにアクセスしないよう、一度RTCから読み出した時刻と、millis()の対応を取ったら、millis()だけで時刻を更新するようにしてあります。RTCの時刻はmsec_rtcrd=60分×60s×1,000ms(=1時間)毎に読み出して、同期し直しています。もし、millis()の精度(≒ATmegaにつながる16MHzクロックの精度?あと、割り込み処理上の精度?)が悪くて、ずれが気になるようなら、msec_rtcrdの値をもう少し小さくして見てください。
ちなみに、シリアルモニタからは、「#2-5 リアルタイムクロックを使ってみる」で作ったRTCのコマンドと、上(shift_7seg4d.ino)で作成した4桁7SEG表示コマンドの両方を受け付けるようになっています(【help】コマンドも追加しておきました)。また、時刻合わせとか、操作の必要が無ければ、シリアルモニタを開かなくても自立するので、電源だけ供給しておけば、ただの時計になります。
筆者はここで止めておきますが、ここまで来たら、U/Iが欲しくないですか?
沢山スイッチほしいですね?でも、もうI/Oポートは1本しか残ってませんので、つけたとしても、スイッチは1個だけです。アレ?そうでしたっけ? …… 「#2-2 スイッチを検出する」読んでいただけましたか?アナログ端子は余っているので、スイッチ、追加できますよ。
プログラムメモリ(Flash)容量にもまだ余裕がありますので、挑戦してみてください。
4桁7SEG LEDを使ってみたかっただけなのに、ずいぶんと大掛かりな大作になってしまいました。電子工作が楽しくて、止まりません。