「7セグメントLEDを買ってみたけど、どのピンをどこにつなげばいいの?」「数字ごとに digitalWrite を7回書いていたら、スケッチが長くなりすぎた…」――そんな経験、ありますよね。

この記事では、Arduinoで1桁の7セグメントLEDに数字を表示し、9→0のカウントダウンを作ります。ポイントは、数字ごとの「どこを光らせるか」をPythonで表(ビットパターン)にしてからArduinoに貼るところです。

難易度:Arduino入門者向け(LEDを光らせたことがあればOK)。Python側は標準のPythonだけで動きます😊

7セグメントLEDのしくみをざっくり整理

seven segment display arduino
seven segment display arduino / Photo by Tanha Tamanna Syed via Pexels

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〜9のビットパターン表とプレビュー
実行結果:0〜9のビットパターン表とプレビュー

実行するとこうなりました。

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ロボット入門のおすすめコース・部品を見る →

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る
Arduinoをはじめよう 第4版 (Make: PROJECTS)

もしも

Arduinoをはじめよう 第4版 (Make: PROJECTS)

Arduino公式推薦の定番入門書

Amazonで見る
徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

もしも

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

電子工作とプログラミングを同時に学べる

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。