2016年1月15日金曜日

RaspberryPi でダイナミック方式の 7 セグ LED を使ってみた

概要

RaspberryPi を起動した時に取得できた IP アドレスを 7 セグに表示したいなと思っていて、ずばりな記事を見つけたので試してみました
配線や Python スクリプトは、そのまま参考にさせていただきました

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 8.0 (Jessie)
  • Kernel Version 4.1.7+
  • Python 2.7.9
  • 7 セグ LED カソードコモン
  • ジャンパケーブル オスxメス 12 本
  • 抵抗 27オーム 4 個

配線

rpi_7_seg_led.jpg

参考サイトを元に実線してみましたが、各桁の表示 ON/OFF 用のジャンパで 4 本、7 セグの各セグメントを制御するためのジャンパが 8 本で、合計 12 本のジャンパと GPIO を使うのでかなりごちゃごちゃになってしまいました
もう少し GPIO に余裕のあるボードだともっと綺麗に配線できるかもしれません

抵抗は 27 オームの抵抗を使っていますが 47 オームの抵抗でも OK です

制御用の Python スクリプト

こちらも参考サイトのコードをそのまま使用させていただきました
今回は使っている GPIO も全く同じにしたのでそのまま動作します

  • mkdir -p ~/work/7_seg_led
  • cd ~/work/7_seg_led
  • vim turn_on_ip.py
!/usr/bin/env python
# -*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import threading
import time
import socket

ledport = (14, 15, 18, 23)
segport = (4, 17, 27, 22, 10, 9, 11, 7)
digit = ((1, 1, 1, 1, 1, 1, 0),     # 0
         (0, 1, 1, 0, 0, 0, 0),     # 1
         (1, 1, 0, 1, 1, 0, 1),     # 2
         (1, 1, 1, 1, 0, 0, 1),     # 3
         (0, 1, 1, 0, 0, 1, 1),     # 4
         (1, 0, 1, 1, 0, 1, 1),     # 5
         (1, 0, 1, 1, 1, 1, 1),     # 6
         (1, 1, 1, 0, 0, 0, 0),     # 7
         (1, 1, 1, 1, 1, 1, 1),     # 8
         (1, 1, 1, 1, 0, 1, 1),     # 9
         (0, 0, 0, 0, 0, 0, 0),     # Blank
         (0, 0, 0, 0, 0, 0, 1))     # Minus

class DynamicLed:
    def __init__(self):
        for n in range(8):
            GPIO.setup(segport[n], GPIO.OUT)
            GPIO.output(segport[n], False)
        for n in range(4):
            GPIO.setup(ledport[n], GPIO.OUT)
            GPIO.output(ledport[n], True)
    def set_digit(self, no, num):
        dot = num & 0x80
        num = num & 0x7F
        if(no == 0):
            GPIO.output(ledport[3], True)
        else:
            GPIO.output(ledport[no - 1], True)
        for n in range(7):
            GPIO.output(segport[n], digit[num][n])
        GPIO.output(segport[7], dot)
        GPIO.output(ledport[no], False)

rlock = threading.RLock()

class LedThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.ss = DynamicLed()
        self.dig = [0, 0, 0, 0]
        self.running = True
    def run(self):
        while self.running:
            rlock.acquire()
            for n in range(0, 4):
                self.ss.set_digit(n, self.dig[n])
                time.sleep(0.005)
            rlock.release()
    def stop(self):
        self.running = False
    def set(self, a, b, c, d):
        rlock.acquire()
        self.dig[0] = a
        self.dig[1] = b
        self.dig[2] = c
        self.dig[3] = d
        rlock.release()
    def set_num(self, num, width=0, dot=-1):
        str = '{0:>.{width}f}'.format(num, width=width)
        dp = 0;
        pos = 3;
        rlock.acquire()
        for n in range(len(str) - 1, -1, -1):
            if str[n] == '.':
                dp = 0x80
            elif str[n] == '-':
                self.dig[pos] = 11  # MINUS
                pos = pos - 1
            else:
                self.dig[pos] = int(str[n]) | dp
                dp = 0
                pos = pos - 1
            if pos < 0:
                break
        for n in range(0, pos + 1):
            self.dig[n] = 10    # BLANK
        if dot >= 0:
            self.dig[dot] = self.dig[dot] | 0x80
        rlock.release()

if __name__ == "__main__":
    GPIO.setmode(GPIO.BCM)
    GPIO.setwarnings(False)
    # get ip address
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.connect(('google.com', 0)) # dummy connect
    ip = sock.getsockname()[0]
    sock.close()
    array = ip.rsplit('.')
    # led thread start
    led = LedThread()
    led.start();
    try:
        while True:
            led.set_num(int(array[0]), dot=3)
            time.sleep(1)
            led.set_num(int(array[1]), dot=3)
            time.sleep(1)
            led.set_num(int(array[2]), dot=3)
            time.sleep(1)
            led.set_num(int(array[3]))
            time.sleep(1)
    except KeyboardInterrupt:
        print '\nbreak'
    led.stop()
    led.join()
    GPIO.cleanup()

実行

作成したスクリプトを実行してみましょう

  • cd ~/work/7_seg_led
  • python turn_on_ip.py

これでグローバル IP に接続するために割り振られた IP アドレスが 7 セグに順番に表示されると思います
使っている RPi が古めの低スペックなので、若干表示がチラつくときもありましたが、読み取れないレベルではなかったです

無限に表示し続けるので終了したい場合は Ctrl + c で終了させてください

cron に登録する

一箇所だけソースを修正します
cron にする場合に無限ループになっていると次回動作したときに GPIO を取り合いうまく表示されません
104 行目にある無限ループをコメントアウトしてあげましょう

103     try:
104         # while True:
105             led.set_num(int(array[0]), dot=3)
106             time.sleep(1)
107             led.set_num(int(array[1]), dot=3)
108             time.sleep(1)
109             led.set_num(int(array[2]), dot=3)
110             time.sleep(1)
111             led.set_num(int(array[3]))
112             time.sleep(1)

これで cron に以下のように設定します
とりあえず 1 分ごとに表示してくれます

*/1 * * * * python /home/pi/work/7_seg_led/turn_on_ip.py

最後に

IP アドレス情報を取得して順番に 7 セグ LED に表示してみました
cron に登録しておけば、配線さえしておけばいつでも IP を確認することができるようになりました

まぁでも、RPi を起動するたびにこの配線をするのは面倒なので、やっぱり fping とかで検知して接続したほうが簡単かもしれません

0 件のコメント:

コメントを投稿