Arduinoで7セグメントLEDに数字を表示!配線とPythonで作るビットパターン表でカウントダウン
「7セグメントLEDを買ってみたけど、どのピンをどこにつなげばいいの?」「数字ごとに digitalWrite を7回書いていたら、スケッチが長くなりすぎた…」――そんな経験、ありますよね。
この記事では、Arduinoで1桁の7セグメントLEDに数字を表示し、9→0のカウントダウンを作ります。ポイントは、数字ごとの「どこを光らせるか」をPythonで表(ビットパターン)にしてからArduinoに貼るところです。
難易度:Arduino入門者向け(LEDを光らせたことがあればOK)。Python側は標準のPythonだけで動きます😊
7セグメントLEDのしくみをざっくり整理

7セグメントLEDは、7本の細長いLED(a〜g)を「日」の字に並べた部品です。イメージとしては、7個のLEDが1つのケースに入っているだけ。どれを光らせるかで数字の形が決まります。
- 上が a、右上 b、右下 c、下 d、左下 e、左上 f、真ん中 g(右下の点は dp)
- たとえば「1」は b と c、「8」は a〜g の全部を光らせる
部品には大きく2種類あるので、ここが重要です👇
| 種類 | 共通ピン(COM)のつなぎ先 | セグメントが光る条件 |
|---|---|---|
| カソードコモン | GND | ピンを HIGH にすると点灯 |
| アノードコモン | 5V | ピンを LOW にすると点灯 |
どちらなのかは、商品ページやデータシートで必ず確認しましょう。ピン配置も製品によって違うことがあるので、データシートの図を見ながら配線するのが安全です。
配線:セグメントごとに抵抗を1本ずつ
この記事ではカソードコモンの1桁タイプを使う前提で、次のようにつなぎます。
| セグメント | a | b | c | d | e | f | g | COM |
|---|---|---|---|---|---|---|---|---|
| Arduinoのピン | D2 | D3 | D4 | D5 | D6 | D7 | D8 | GND |
- a〜g の各線に 220Ωの抵抗を1本ずつ入れる(全部で7本)
- D0・D1 はシリアル通信と共用なので使わない
- COM のピンが2本ある部品は、どちらか1本をGNDにつなげば動きます
「COM側に抵抗を1本だけ入れれば楽では?」と思うかもしれません。ですがそれだと、光るセグメントの数で電流が分け合われて、「1」は明るく「8」は暗いという表示になってしまいます⚠️ セグメントごとに1本ずつ入れるのが基本です。
参考までに、赤色LED(順方向電圧 約2V)に5Vと220Ωなら、1セグメントあたりの電流は (5 − 2) ÷ 220 ≒ 約14mA の計算です。
Pythonで「どこを光らせるか」の表を作る
数字ごとに digitalWrite を7回ずつ書くと、10個の数字で70行になってしまいます。そこで、1つの数字を1バイトの数値で表すことにします。
つまり、a を1の位(bit0)、b を2の位(bit1)…g を bit6 として、光らせるセグメントのビットを1にした数値を作るわけです。この計算をPythonに任せましょう。
ポイントをまとめるとこんな感じです👇
1 << 番号で「その位置だけ1」の数値を作り、|=で重ねていくf"{b:07b}"で7桁の2進数として表示できる- 最後に、Arduinoにそのまま貼れる配列の形で出力する
- ついでに、ターミナルに数字の形を描いて、表が合っているか目で確かめる
# 7セグメントLEDの「どこを光らせるか」表を作るスクリプト
SEGMENTS = "abcdefg" # bit0=a, bit1=b, ... bit6=g
# 数字ごとに光らせるセグメント
DIGITS = {
0: "abcdef",
1: "bc",
2: "abdeg",
3: "abcdg",
4: "bcfg",
5: "acdfg",
6: "acdefg",
7: "abc",
8: "abcdefg",
9: "abcdfg",
}
def to_byte(lit):
"""光らせるセグメントの文字列を1バイトの数値に変換する"""
value = 0
for seg in lit:
value |= 1 << SEGMENTS.index(seg)
return value
def preview(lit):
"""セグメントの点灯をターミナルに描く(3行×3文字)"""
def on(seg, ch):
return ch if seg in lit else " "
return [
" " + on("a", "_") + " ",
on("f", "|") + on("g", "_") + on("b", "|"),
on("e", "|") + on("d", "_") + on("c", "|"),
]
codes = []
for n, lit in DIGITS.items():
b = to_byte(lit)
codes.append(b)
print(f"{n}: {lit:<7} -> 0b{b:07b} (0x{b:02X})")
# Arduinoにそのまま貼れる配列を出力
body = ", ".join(f"0b{b:07b}" for b in codes)
print()
print(f"const byte DIGIT_CODES[10] = {{{body}}};")
# 0〜9を横に並べてプレビュー
print()
rows = ["", "", ""]
for lit in DIGITS.values():
for i, line in enumerate(preview(lit)):
rows[i] += line + " "
print("\n".join(rows))

実行するとこうなりました。
0: abcdef -> 0b0111111 (0x3F)
1: bc -> 0b0000110 (0x06)
2: abdeg -> 0b1011011 (0x5B)
3: abcdg -> 0b1001111 (0x4F)
4: bcfg -> 0b1100110 (0x66)
5: acdfg -> 0b1101101 (0x6D)
6: acdefg -> 0b1111101 (0x7D)
7: abc -> 0b0000111 (0x07)
8: abcdefg -> 0b1111111 (0x7F)
9: abcdfg -> 0b1101111 (0x6F)
const byte DIGIT_CODES[10] = {0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110, 0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111};
_ _ _ _ _ _ _ _
| | | _| _| |_| |_ |_ | |_| |_|
|_| | |_ _| | _| |_| | |_| _|
プレビューで0〜9がちゃんと数字に見えれば、表は正しいということです。たとえば「7」は 0b0000111、右から a・b・c の3つが1になっていますね。
手で 0b1101101 のような値を書くと、1か所の書き間違いで「5」が別の形になってしまいます。表をプログラムで作って、目で確かめてから貼ると、配線のミスと表のミスを切り分けやすくなります🚀
Arduinoで9→0のカウントダウンを作る
Pythonが出力した DIGIT_CODES の行を、そのままスケッチに貼ります。ここが重要です👇
bitRead(値, i)で i 番目のビットを読み、1ならHIGH・0ならLOWにするCOMMON_ANODEを true にすると、HIGH と LOW を入れ替える(アノードコモン用)- delay() ではなく
millis()で1秒を測るので、あとからボタン処理などを足しても止まらない
// 7セグメントLEDで 9→0 のカウントダウン
// a〜g を D2〜D8 につなぐ(それぞれ 220Ω の抵抗を入れる)
const int SEG_PINS[7] = {2, 3, 4, 5, 6, 7, 8}; // a, b, c, d, e, f, g
// Pythonで作った表をそのまま貼る(bit0=a … bit6=g)
const byte DIGIT_CODES[10] = {0b0111111, 0b0000110, 0b1011011, 0b1001111, 0b1100110,
0b1101101, 0b1111101, 0b0000111, 0b1111111, 0b1101111};
const bool COMMON_ANODE = false; // アノードコモンの部品なら true にする
int count = 9;
unsigned long lastChange = 0;
const unsigned long INTERVAL = 1000; // 1秒ごとに数字を変える
void showDigit(int n) {
for (int i = 0; i < 7; i++) {
bool on = bitRead(DIGIT_CODES[n], i); // i番目のビットを読む
if (COMMON_ANODE) on = !on; // アノードコモンはLOWで点灯
digitalWrite(SEG_PINS[i], on ? HIGH : LOW);
}
}
void setup() {
for (int i = 0; i < 7; i++) {
pinMode(SEG_PINS[i], OUTPUT);
}
Serial.begin(9600);
showDigit(count);
}
void loop() {
unsigned long now = millis();
if (count > 0 && now - lastChange >= INTERVAL) {
lastChange = now;
count--;
showDigit(count);
Serial.print("表示: ");
Serial.println(count);
}
}
書き込むと、最初に「9」が表示され、1秒ごとに 8、7…と減って「0」で止まります。シリアルモニタ(9600bps)には、次のように表示されます(表示例)。
表示: 8
表示: 7
表示: 6
(中略)
表示: 0
もし数字の形が崩れたら、表ではなく配線を疑いましょう。たとえば「1」を出したのに左側が光るなら、b・c と e・f の線が入れ替わっている可能性が高いです。
アノードコモンの部品だったときは?(つまずきポイントつき)
スケッチの COMMON_ANODE を true にすれば動きますが、表そのものを反転したいこともありますよね。Pythonで試してみましょう。
これ、実行せずに答えられますか? ~0x3F(0b0111111 の反転)は、いくつになるでしょう?
# カソードコモン用の表を、アノードコモン用に反転する
CATHODE = [0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F]
for n, b in enumerate(CATHODE):
inv = ~b & 0x7F # 下位7ビットだけ0と1を入れ替える
print(f"{n}: cathode 0b{b:07b} -> anode 0b{inv:07b}")
# 「~」だけで反転すると、負の数になってしまう
print("~0x3F =", ~0x3F)

0: cathode 0b0111111 -> anode 0b1000000
1: cathode 0b0000110 -> anode 0b1111001
2: cathode 0b1011011 -> anode 0b0100100
3: cathode 0b1001111 -> anode 0b0110000
4: cathode 0b1100110 -> anode 0b0011001
5: cathode 0b1101101 -> anode 0b0010010
6: cathode 0b1111101 -> anode 0b0000010
7: cathode 0b0000111 -> anode 0b1111000
8: cathode 0b1111111 -> anode 0b0000000
9: cathode 0b1101111 -> anode 0b0010000
~0x3F = -64
答えは -64 でした⚠️ Pythonの整数には「何ビット」という決まりがないので、~ は「符号まで含めて反転」した負の数になります。
- 7ビットだけ反転したいときは
~b & 0x7Fのように、下位7ビットだけを取り出す - 「0」のアノードコモン用は
0b1000000、つまり g だけ消灯(HIGH)で残りを点灯(LOW)。理屈どおりですね
まとめ
- 7セグメントLEDは a〜g の7個のLED。カソードコモンはHIGHで点灯、アノードコモンはLOWで点灯
- 抵抗はセグメントごとに1本ずつ(COMに1本だけだと明るさがそろわない)
- 数字の形は1バイトのビットパターンで表すと、スケッチが短くなる
- 表はPythonで作ってプレビューで確かめてから貼ると、ミスの切り分けがしやすい
- Pythonで7ビット反転するときは
~b & 0x7F
1桁が動いたら、次は2桁・4桁の表示やタイマー作りにも広げられます。「むずかしそう」を「できそう」に変える第一歩として、ぜひ試してみてください😊
こちらも読まれています
📡 Arduinoをもっと深く学ぼう!
Arduino・ラズパイ・ロボットプログラミングを体系的に学びたい方へ。おすすめのUdemyコースや電子部品もまとめています。
Arduinoロボット入門のおすすめコース・部品を見る →📚 関連商品・おすすめ書籍
※本記事にはアフィリエイトリンクが含まれます。




