かわいい正方形のつぶつぶLEDで文字や絵を表示できる、ちっちゃな電子回路をつくってみました。Arduinoがベースとなっており、プログラムを組んで自由にシャープ製LT-5003DドットマトリクスLEDで遊べます。
イントロダクション
手軽にガジェットを自作できるArduinoの入門としてLチカはお約束。
流行りの表示デバイスはOLED(有機ELディスプレイ)や電子ペーパーですが、電子工作で光らせるならやっぱり赤色LEDな気がします。そこで、以前から秋月電子で販売されている10×10ドットマトリクスLEDに火入れしてみることにしました。僕の知るかぎり2000年末には既に販売されており、“光り物”が大好きなので結構な数を購入後コレクションとして保管すること二十数年。まだお店には在庫が1万個以上あるらしく、しばらく売り切れることは無さそうです。
シャープ製LT-5003D、1個100円。
赤色のLEDが縦に10つぶ、横に10つぶ、計100個も並んでいます…かわいい!

検索してもあまり作例が見つかりません。
というのも、8×8とか8×16ならLEDドライバIC一発で動かせるのですが10×10となると扱うのが地味に面倒。実は2007年にdsPICを使って英文のスクロール表示を実現したものの、ドライバにMAX7219CNGを使ったためLEDは8×8の範囲しか点灯できておらず…まさかそのまま18年も放置してしまうとは。

きちんと10×10を光らせるとなるとLEDのサイズに比べて大きな周辺回路になりそうです。そこで今回は極小のチップ部品と専用基板を起用することでコンパクトに収めてみました。
I/Oは大半をドットマトリクスの駆動に充てており、残りの2本をタクトスイッチ、1本を圧電スピーカー、2本をユニバーサル基板に引き出してみました。本ページでは回路図のほか、ドットマトリクスLEDをダイナミック点灯させるサンプルプログラムとしてArduino用スケッチも合わせて公開しました。末尾には基板頒布のご案内を掲載していますので、製作に関心がある方は合わせてご覧ください。
回路図
まずは回路図を示します。
LEDのアノード側にシフトレジスタを使い、カソード側をコモンとしてマイコンのI/Oで直接制御しています。

※ 大きな回路図のダウンロードは こちら から
※ CN3はコネクタではなく4×4のユニバーサル基板エリアに引き出されています(後述)
アートワーク
表面実装用のパーツを多用するのでPCBを起こしました。
マイコンの書込みに必要となる配線は基板の端に9ピンでまとめてあり、PCと接続してブートローダーを焼いたりスケッチを更新する際の便をはかりました。ガーバーデータは公開しませんが、以下にアートワークを掲載しますので設計の参考になれば幸いです。

完成例
LEDの表示例を動画で示します。
立方体が回転しているアニメーションです。実際はもっと高速でも鮮明に見えますが、ダイナミック点灯のリフレッシュレートに対して撮影するカメラのフレームレートを十分遅くできないために遅めのアニメーションになっています。(ダイナミック点灯をきれいに撮影する方法をご存じの方はぜひ教えてください)
この基板はスイッチやスピーカーを搭載したArduinoであり、センサーなども追加できるので使い道は限定されません。既にいろんなおもちゃを何台も完成させているので、応用例は別の機会に紹介したいと思います。(写真のように、基板は黒と緑の二色あります)

つくり方
世界中で親しまれているArduinoがベースなので製作しやすく応用の幅も無限大。一般的なデバイスで構成されており部品点数も少ないため回路図通り組めば完成するはずです。ただし、まったく同じサイズで仕上げようとなるとハンダ付けにピン間0.65mmという高い実装技術が要求されます。電子工作経験者でも半分以上のひとは手ハンダできないんじゃないかな…と煽っておきます。
製作のポイントを示しながら、設計上の工夫をいくつか紹介します。
ATmega328P
Arduinoを使うためのマイコンとしてマイクロチップ社のATmega328Pを使用。半導体が値上がりして、お値段はとうとう400円台に乗ってしまいました。

表面実装用のチップ部品であるATmega328P-AUを使っていますが、ブレッドボードなどで組むならDIP型のATmega328P-PUを。
まずはこの四角いのを貼り付けます。

水晶発振子
クリスタル(水晶発振子)は16MHz。
よく売られているHC-49/S3型パッケージのほかに手持ちの都合でチップ型クリスタルも載せられるようにしました(下の写真、右側)。ただし、パッドがほとんど外に出ていないこいつを手ハンダするのは至難の業なので(後述する最薄仕様にするのでなければ)普通の金属缶のやつにしたほうが無難です。

クリスタルの手前のBUZZERという部分には圧電スピーカーを付けられます。こちらもリード足の出ているものとチップ部品の両方に対応していますが、リード足タイプは裏面に取付けないとLEDに干渉します。圧電スピーカーのお気に入りは村田製作所製PKLCS1212E4001-R1で、最近はこいつの表面実装ばかりです(1個100円)。
ATmega328Pブートローダー書込み
ATmega328P-AUは空っぽのAVRマイコンなので、開発環境としてArduino IDEを使うにはブートローダーを入れてあげる必要があります。ATmega328Pと水晶のほか、基板裏側のすべてのキャパシタ(C1、C4~6)とRESETピンのプルアップ抵抗(R1)をくっつけた段階でブートローダーを焼くのが良いと思います。

書込み結線例は上の写真を参考に。
基板にコネクタやピンヘッダも立てられますが、一度きりならスルーホール用テストワイヤ(写真の手前に写っているような、先端部がバネ状になっている特殊な線材)を使うと経済的です。
※ 仮にすべての部品を実装した後でも(LEDをソケットから抜けば)ブートローダーの書込みには支障がない回路設計になっています
8ビットシフトレジスタ 74HC595
ドットマトリクスLEDをドライブするためには行と列それぞれ10本の信号線が必要ですが、ATmega328PのI/Oでは本数も電流も不足します。そこで、列データはシリアルで出力したものを外付けのシフトレジスタでばらします。74HC595はシフトレジスタICとして定番中の定番。1つぶ50円前後ですかね、ただし10ビットをまかなうために2つぶをカスケード接続して用います(回路図参照)。

問題はそのサイズ。昔からの電子工作でよく使われるDIP型のほか、幅が半分となる表面実装用のSOP型も一般的ですが、今回は完成サイズにこだわっておりTSSOP型を選びました。SOPにTが付くと厚みが薄くなり、TSOPにSが増えると幅がさらに半分になります!
もはや髪の毛より細いので、これ半田ごてで手ハンダできたら大したものですよ…と再び煽っておきますが、少なくとも顕微鏡は必須です。

電源
電源周りにはスイッチを付けたり三端子レギュレータやDC-DCコンバータを挟めるようにしました。
下の写真で右側は乾電池から5Vへの昇圧DC-DCコンバータを載せています。PCBの表面にパスコン用、裏面にレギュレータ用のパッドを設けたので、写真の左のように5V(あるいは3.3V)への降圧回路も簡単に組めます。

※ スイッチの型番はSK-12D11VG3
※ 写真のチップ型レギュレータは日清紡マイクロデバイス製JM12888F05(5V300mA)
※ レギュレータを使わないなら写真の真ん中のようにI-O間をジャンパします
※ 給電はXHコネクタを使うとパーツの角が基板のふちにぴったり揃います(でかいコネクタは邪魔なので使っていませんが)
※ 3.3V駆動のときにダイナミック表示でLEDがチラつかない動作速度を維持できるのかどうかは検討していません
そのほかのパーツ
あとはLEDのほかにスケッチに応じて好きな部品たちを並べればOKです。
下の写真は表面実装タイプの圧電スピーカーと、ユニバーサル基板の部分に電源供給用のUSB Type-Cコネクタを取付けた例。

4×4のユニバーサル基板エリアのうち一番上の列のランドは、表面左から GND、D14またはA0(回路図での表記はAポート)、D15またはA1(同、Bポート)、+5V に接続されており、センサーなどを追加する際に結線しやすくなっています。さらに左右のタクトスイッチ用ランドも接続先をD2、D3とすることで、プログラムで割込みの機能を使えるように考慮しました。
最薄仕様
実はこの基板、もっとも小さく組むとLT-5003DドットマトリクスLEDの外寸にせまる設計になっています。
下の写真が作例で、チップ型クリスタルを使い、スピーカーを実装せず、LT-5003Dはソケットに刺さずに直付け。PCBの上下は無くても動作に支障のないアートワークにしてあるので、写真の黒線のところでバッサリ切り落とせば基板を丸ごとLEDの裏側に収めてしまえます。

LEDの電流とICの定格について(重要)
電源が5Vで電流制限抵抗が150Ωのとき、LT-5003DのLEDには一つぶ当たり21.9mA流れます(実測値)。この回路ではLEDのコモン側をマイコンに直結しているため、LEDをいくつも並べて点灯させたりすればたちまち「1ピン当たり最大40mA」というATmega328Pの絶対最大定格を超えます。ではマイコンが壊れるのかというと、実際のところATmega328Pの出力ピンのシンク電流は60mA辺りで飽和してそれ以上流れなくなるようですが、回路設計としては問題ありでしょう。製作される際は電流制限抵抗をもっと大きくしたり、スペースに余裕があればマイコンとドットマトリクスLEDの間にきちんとバッファ(具体的にはシンクタイプのトランジスタアレイなど)を挿入することをおすすめします。(そのほうがLEDも明るく点灯できます)
※ 列当たり一灯のみ点灯と全点灯で明るさに違いが生じるのはこの手抜きが原因だと考えられます
※ もっときちんとしたドットマトリクスLEDの回路は電光掲示板の製作記事を書くときにでも紹介できればと思います
※ ダイナミック表示のとき一般にLEDには大きめの電流を流しますが、プログラムが停止したとき意図せずスタティック表示となる可能性があることにも留意するべきです
プログラム作成例
本機のピン接続は以下のArduino用スケッチを参考にしてください。
このままボードに書込めば静止した立方体がデモ表示されるはず。パターンをお好みで書き換えてみてください。
// This sketch uses dynamic scanning to drive a 10x10 LED matrix
// LT-5003D via 74HC595 shift registers.
// Ver 1.0, 20 Dec. 2025 (Tested on Arduino Uno) by Kitagawa
// --- Pin assignment ---
const int dataPin = 8; // --> 74HC595 14pin: SER
const int latchPin = 7; // --> 74HC595 12pin: Register clock (positive edge trigger)
const int clockPin = 6; // --> 74HC595 11pin: Shift register clock (positive edge trigger)
const int colPins[10] = {14, 4, 18, 19, 17, 9, 10, 11, 12, 13}; // LOW = LED ON
const int switchLPin = 2; // D 2 (PD2) --> Left switch (active L)
const int switchRPin = 3; // D 3 (PD3) --> Right switch (active L)
const int buzzerPin = 5; // Piezo speaker
// --- Time setting ---
// ON time per line for dynamic scanning
// Note: too long causes flicker, too short makes LEDs dim
int lineDuration = 1500;
// OFF interval between lines during dynamic scanning
int lineInterval = 0;
// --- Cube pattern (10x10) ---
// 1 = LED ON, 0 = LED OFF
uint16_t cubePattern[10] = {
0b0000110000,
0b0011001100,
0b1100000011,
0b1110000111,
0b1001111001,
0b1000010001,
0b1000010001,
0b1100010011,
0b0011011100,
0b0000110000
};
void setup() {
// --- I/O configuration ---
pinMode(dataPin, OUTPUT);
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
for (int i = 0; i < 10; i++) pinMode(colPins[i], OUTPUT);
// Switch input pins (internal pull-up enabled)
pinMode(switchLPin, INPUT_PULLUP);
pinMode(switchRPin, INPUT_PULLUP);
// Piezo speaker output pin
pinMode(buzzerPin, OUTPUT);
// Initialization - Turn all columns OFF (Note: active LOW)
for (int c = 0; c < 10; c++) digitalWrite(colPins[c], HIGH);
digitalWrite(latchPin, LOW);
digitalWrite(clockPin, LOW);
digitalWrite(dataPin, LOW);
}
void loop() {
// Example code for reading button input
bool leftPressed = (digitalRead(switchLPin) == LOW);
bool rightPressed = (digitalRead(switchRPin) == LOW);
// Pattern display
displayMatrix(cubePattern);
}
// --- Display one full frame (dynamic scanning) ---
void displayMatrix(uint16_t *pattern) {
for (int col = 0; col < 10; col++) {
displayCol(col, pattern);
}
}
// --- Light a specific column (select one column and output row data) ---
// Note: The entire pattern is passed as a pointer for rotation processing
void displayCol(int col, uint16_t *colData) {
// Generate data rotated 90 degrees clockwise
uint16_t rotatedColData = 0;
for (int row = 0; row < 10; row++) {
// Shift right and extract the least significant bit
int bit = (colData[row] >> (9 - col)) & 0x01;
// Fill bits from LSB upward
rotatedColData |= (bit << row);
}
// Output ON/OFF state for each row in the column
for (int row = 0; row < 10; row++) {
// Extract bits from LSB upward
int bit = (rotatedColData >> row) & 0x01;
// Output bit value to data pin
digitalWrite(dataPin, bit ? HIGH : LOW);
// Clock pulse
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
// Latch output
digitalWrite(latchPin, HIGH);
digitalWrite(latchPin, LOW);
// Activate the selected column (Note: LOW = ON)
digitalWrite(colPins[col], LOW);
delayMicroseconds(lineDuration); // ON time per line
digitalWrite(colPins[col], HIGH);
delayMicroseconds(lineInterval);
}
開発のヒント
本機はCol単位(縦方向のLED列)でダイナミック点灯を行なっています。したがって、パターンをそのまま送出するとマトリクスLEDの左辺がパターンの天となり、つまり反時計回りに90°回転して表示されます。これを解決するためにはマトリクスLEDを時計回りに90°回転させて実装する方法もありますが、アートワーク作成上の都合(基板の横側に書込み用ランドを設けたい、など)によりソフトウェアで表示パターンを回転させています。
その処理を担うのが以下のコードですが、このビット操作について補足説明します。
for (int row = 0; row < 10; row++) {
int bit = (colData[row] >> (9 - col)) & 0x01;
rotatedColData |= (bit << row);
}
colData[row] は元パターンのrow行目に並ぶ10ビットの横方向データを表しており、(9 - col) ビット目を右シフトによって最下位ビット(LSB)へ移動し、0x01とのAND演算によってその1ビットだけを抽出しています(これを「ビットをマスクする」なんて表現します)。これは、元の2次元座標でいえば (row, col) に対応する点灯情報を取り出す操作に相当します。次に、そのビットを左シフトによって新しいデータのrow番目のビット位置へ送り込み、rotatedColData にOR演算で積み上げていきます。このように、元パターンの各行から同じ列のビットを集め、縦方向のビット列として構成することで、表示系の都合に合わせたデータの再配置を実現しています。結果として、この処理全体は「元の (row, col) を新しいビット位置へ対応づける写像」をビット演算のみで実装したものであり、動作としてはパターンを時計回りに90°回転させたのと等価になっています。
※ ビット演算が理解しづらい場合はループを入れ子にして二次元配列を代入し直していくコードのほうが直感的かもしれません
※ 関数を呼び出す際、比較的大きな配列は変数ではなくスケッチ例のように「ポインタ渡し」にするとメモリ効率や処理速度の面で有利です
基板頒布のご案内
製作に必要な情報はすべて記載しましたが、リードタイプの部品で組むと完成サイズが大きく、かといって1個つくるために自分でPCBを設計・製造するのはちょっと大変かもしれません。本作例のPCBは余剰がありますので、在庫限り有償にて提供の用意があります。(基板のみ1枚1,000円、送料別)
また、TSSOP型の74HC595はパーツ店などで小売りされておらず入手がやや困難です。(ご自身で設計されるならSOP型までにしておくと秋月電子などで簡単に購入できます)僕が使ったTSSOP型のICはオンセミコンダクター社のMM74HC595MTCXという型番のもので、時間はかかりますが個人でもDigiKeyなどを通して輸入できます。こちらもPCBとの同梱に限り1つぶ200円にて頒布しますので、希望される方はコメント欄からご連絡ください。
