概要
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 個
配線
参考サイトを元に実線してみましたが、各桁の表示 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 とかで検知して接続したほうが簡単かもしれません