電子工作
Python3
Raspberrypi3
7セグメントLED

7セグメントLEDで時計を作る(Raspberrypi3 / python3)

使用ハード

Raspberry Pi3 model B

確かこれを買いました。
Amazonでベストセラー1位って書いてたから。。
こんな箱に入って届きました。
IMG_20180106_082852.jpg

電子工作パーツ

取りあえずブレッドボード、ジャンパワイヤ、LEDが欲しかったので、他にもよく分からんパーツも入ってるけどこれを買いました。
このセットにたまたま含まれてた7セグメントLEDを使って時計を作ります。
IMG_20180107_093613.jpg

使用するソフト

今回の悩みどころはソフト面では無かったのでサラッと。
- OS: Raspbian 9
- Script: python 3

第一の難関 ~これ何て名前よ~

まず、この部品。たまたまセットに入ってたので何て名前かが分からない!
型番っぽいのが書いてるからこれで検索してもドンピシャ同じのはヒットしないし。。
IMG_20180107_093613.jpg

どうやら彼の名は「7セグメントLED」もう少し詳しく言うと「7セグメント12ピンLED」という事が分かった。

7セグメントって何のことさ・・
IMG_20180107_095631.jpg
要するに数字1桁を表すのに光るとこが7つあるって事らしい。

12ピンって何のことさ・・
これは部品から出てるピンが12個あることを指すようです。
写真だと片方の6ピンしか見えてないけど上下に6ピンずつあるので12ピンLED。
ピンの数が違う部品もあるみたいだけど今は無視します!

第二の難関 ~ピン12個で4桁の数字??~

ここまでで1桁の数字を出し分けるのに7つLEDがあるというのは分かった。
(ドットも別LEDなのでそれを含めると8つのLEDとなる!)

ん?どうやってこれで数字出すのさ??
8LED * 4桁 = 32ピン いるんじゃね?
この仕組み知るのにひどく時間が掛かりました。これが一番お伝えしたい!

12ピンそれぞれの役割

まず、部品についている12個のピンそれぞれにはピン番号が振られています。
モノにより違う場合もあるっぽいですが、大体は左下から1,2,3という順になっていて上に上がって右上から7,8,9・・・12という順のようです。
IMG_20180107_095631 (1).jpg

ある桁の数字に対して点灯させるLED位置を示すピン

数字を表すLEDのどの位置を点灯するかを担っているピンと対応するLED位置が赤いピンです。
なんで順番じゃなくて歯抜けなのよ!覚えづらいな!
IMG_20180107_095631 (2).jpg  IMG_20180107_0956311.jpg

どの桁の数字を点灯させるかを示すピン

残りの4つの青いピンが4桁ある表示エリアのどこを光らせるかを担います。
対応する桁は8の字の上に書いてある番号になります。
IMG_20180107_095631 (3).jpg

以上を整理すると12個あるピンの用途はこのようになります。

ピン 種類    用途          
1 数字LED 数字の左下
2 数字LED 数字の底
3 数字LED ドット
4 数字LED 数字の右下
5 数字LED 数字の真ん中
6 桁指定 右から1つ目の数字
7 数字LED 数字の右上
8 桁指定 右から2つ目の数字
9 桁指定 右から3つ目の数字
10 数字LED 数字の左上
11 数字LED 数字の天井
12 桁指定 右から4つ目の数字

最後の難関 ~4桁それぞれに数字を出す~

これで実際に数字を表示させてみるところまで来たと思いきや・・ちゃんと落とし穴がございました。

取りあえず数字の「1」を表示させてみよう

  1. ピン4,7を点灯させる(1の表示)
  2. ピン12を指定して右から4つ目に表示する

結果は、「1」と正常に表示! よしよしやっと楽しくなってきた。
IMG_20180108_001907.jpg

次の桁には「2」と表示させて「12」とさせてみよう

  1. ピン4,7を点灯させる(1の表示)
  2. ピン12を指定して右から4つ目に表示する
  3. ピン1,2,5,7,11を点灯させる(2の表示)
  4. ピン9を指定して右から3つ目に表示する

結果は、「22」と表示されちゃいました!(1つ目の2で真ん中のLEDが光ってませんが)
IMG_20180108_002038.jpg
なんでさ??
これはまさに仕組みも理屈も分からずに挑んだからこそのミスなのでした。

ダイナミック点灯

原因は4桁の数字それぞれに違う値を表示させるための「ダイナミック点灯」制御が考慮されていないからでした。

ダイナミック点灯をざっくりというと・・

  • 4桁同時にそれぞれ表示させたい数字を指定するのはムリ!
  • だから1桁ずつ数字を表示して順番に数字を表示させよう
  • その処理をループさせて人が気付かないくらい高速に切り替えればバレないべ

ということでした。
なんてこった!今まで世のデジタル時計に誤魔化されてきてたのか!!

「1234」を表示するためには・・
IMG_20180108_003137.jpg
IMG_20180108_003140.jpg
IMG_20180108_003143.jpg
IMG_20180108_003146.jpg
をループで高速処理して・・

IMG_20180108_004005.jpg
で、でけた・・

時刻を表示させるためのスクリプト

あちこちから切り貼りしてpythonスクリプトを作りました。

ラズパイと7セグメントLEDとの接続

よそのサイトにあるようなイカした接続図を載せたいとこですが、初心者ゆえ分からず!
取りあえず先ほどの表に情報を追加してこんな一覧でご容赦ください。

ピン 種類    用途           ラズパイのGPIO
1 数字LED 数字の左下 7
2 数字LED 数字の底 8
3 数字LED ドット 25
4 数字LED 数字の右下 23
5 数字LED 数字の真ん中 18
6 桁指定 右から1つ目の数字 24
7 数字LED 数字の右上 4
8 桁指定 右から2つ目の数字 17
9 桁指定 右から3つ目の数字 27
10 数字LED 数字の左上 10
11 数字LED 数字の天井 11
12 桁指定 右から4つ目の数字 22

pythonスクリプト

ちなみに時刻を表示するにあたって、部品にひとつ問題が。
一番左のLED、真ん中が光りません。こういうものなのか、壊れたのか、謎です。
そのため上の例であった「2」のように真ん中が光って欲しい数字が表示できません。
仕方ないので7セグメントLEDと別にAMとPMを識別するためのLED部品を別で付けました。
なのでsetAmPmメソッドはそのための処理です。

led.py
import sys
import RPi.GPIO as GPIO
import time

INTERVAL = 0.001

#--------------------------------------------
# get now time
#--------------------------------------------
def getTime():
    # now time
    n = time.strftime('%I') + time.strftime('%M')
    timeList = list(n)
#    print("timeList: " + str(timeList))
    return timeList

#--------------------------------------------
# set AM/PM LED
#--------------------------------------------
def setAmPm():
    # get AM/PM
    ap = time.strftime('%p')
    # print(str(ap))
    if ap == "AM":
        turnLight(20,1)
        turnLight(21,0)
    else:
        turnLight(20,0)
        turnLight(21,1)

#--------------------------------------------
# switch 7seg LED light
#--------------------------------------------
def switchLight(gpio, number):
    GPIO.setup(gpio, GPIO.OUT)
    if number == 0:
        GPIO.output(gpio, GPIO.HIGH)
    else:
        GPIO.output(gpio, GPIO.LOW)

#--------------------------------------------
# set lighting LED number
#--------------------------------------------
def lightNumber(number, cnt):
    # GPIO ports for the 7seg pins
    segments =  (11,4,23,8,7,10,18,25)

    # Number light pattern
    num = {' ':(0,0,0,0,0,0,0),
        '0':(1,1,1,1,1,1,0),
        '1':(0,1,1,0,0,0,0),
        '2':(1,1,0,1,1,0,1),
        '3':(1,1,1,1,0,0,1),
        '4':(0,1,1,0,0,1,1),
        '5':(1,0,1,1,0,1,1),
        '6':(1,0,1,1,1,1,1),
        '7':(1,1,1,0,0,0,0),
        '8':(1,1,1,1,1,1,1),
        '9':(1,1,1,1,0,1,1)}

    # GPIO ports for the digit 0-3 pins
    digits = (22,27,17,24)

    for i in range(0,7):
#        print(str(segments[i]) + "," + str(num[number][i]))
        switchLight(segments[i],num[number][i])

    switchLight(digits[cnt-1],1)
    switchLight(digits[cnt],0)

#--------------------------------------------
# main
#--------------------------------------------
GPIO.setmode(GPIO.BCM)
try:
    # display to time number
    while True:
        # now time
        lst = getTime()

        # set AM/PM
        setAmPm()

        # counter reset
        count = 0

        # set display numbers
        for nm in lst:
            lightNumber(nm, count)
            count+=1
            time.sleep(INTERVAL)
finally:
    GPIO.cleanup()

最後にちょっと見た目を

レゴでケースを作ってる例がたくさんあったので、ここはベタに乗っかっておこうと。
センスと部品に問題を抱えたため概念渦巻いております。
タイトル「警察の金を盗んで木の根元に隠そうとしたらバレた」
1515225351213.jpg
青いLEDがPMを示します。AMになると隣の黄色LEDが点灯します。