Help us understand the problem. What is going on with this article?

nemの灯~Raspberrypi,Pythonで作るクリスマスイルミネーション~

はじめに

クリスマスも近いので、
nemのトランザクション量に合わせて明るくなるイルミネーションを作りました。

明るさは、
 ・2秒ごとに暗く(デューティ比-1%)
 ・nemブロック生成時のトランザクション量分明るく(デューティ比+x%)
なります。

nemのトランザクション量に左右される光なので、「nemの灯」と名前を付けました。

IMG_5828.jpg

本記事を最後まで実施頂くことで、下記2つが身につくことでしょう。
・電子工作界の「Hello world」ことLチカの技術
・nem界の「Hello world」ことトランザクション確認の技術

必要な物(値段は一例)

・Rasberry Pi Zero WH(他のラズパイでも可です)
  1848円(スイッチサイエンス)
  https://www.switch-science.com/catalog/3646/
・ジャンパワイヤ(メス~ワニ口)※100均のワニ口加工したら100円
  955円(スイッチサイエンス)
  https://www.switch-science.com/catalog/5534/
・マイクロSDカード 16GB
  820円(amazon)
・ラズパイにssh接続するためのPC(Windows,Mac,Linux等)
・イルミネーションと箱
  100円×2(ダイソー)
 ※お手持ちのイルミネーション機器(単三2本ほどで動くもの)でも可

0.ラズパイを準備しよう!

Raspberrypi(ラズパイ)とは、英ラズベリーパイ財団が開発した超小型のシングルボードコンピューターです。
ラズパイの種類は多々ありますが、今回はより小さく安いRaspberrypi zeroWHという種類を
使って解説していきます。

まずはラズパイを持っていない方は買いましょう。
amazonなどでは、結構定価より高くなっていることが多いので、
スイッチサイエンスさん等で買うことをお勧めします。

ラズパイの準備については、色々記事記事があると思うので、こちらでは割愛します。
https://qiita.com/RyoheiTomiyama/items/4c25f146264521cf6446

1.ラズパイでLチカしてみよう!

まずは、プログラミングでいうところの『Hello World!』である
Lチカ(LEDを点灯させる)をやってみましょう。

GPIO用のライブラリをインストールする

$ sudo apt install python3-rpi.gpio

Lチカプログラムの作成

gpio.py
#!/usr/bin/python3

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
try:
        while True:
                GPIO.output(18, True)
                time.sleep(0.1)
                GPIO.output(18, False)
                time.sleep(0.1)

except KeyboardInterrupt:
        pass

GPIO.cleanup()

ラズパイの配線

ラズパイのGPIO18ピンとお手持ちのイルミネーションを繋げましょう。
Untitled Sketch_ブレッドボード.jpg IMG_5838.jpg

Lチカプログラムの実行

$ python3 gpio.py

0.1秒に1回ずつ、LEDのオンとオフを繰り返すはずです。
プログラムはCtrl + C で停止させます。

2.ラズパイでPWM制御してみよう!

PWMとはPulse Width Modulationの略でパルス幅変調を用いた制御のことです。
ラズパイはデジタルな制御(1か0か、今回の場合3.3Vか0Vか)しか出力出来ません。

そこで、非常に短い間隔でオンオフを繰り替えし、オンの時間とオフの時間の比(デューティ比)を
調整することで、LEDの光度やモーターの速さを調整することが出来ます。
例えば、1秒間にオンオフを数百回繰り返した場合、人が見た場合50%のオンの光として認識されます。

下記ファイルを作成し、実行してみましょう。

pwm.py
#!/usr/bin/python3

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT) #18ピンを利用

Duty = 100

try:
        while True:
                pwm = GPIO.PWM(18, 100000) #PWM出力(18ピン,1000Hz)
                pwm.start(0)

                # LED点灯
                for i in range(Duty):
                        pwm.ChangeDutyCycle(i)
                        time.sleep(0.1)

                # LED消灯
                for i in range(Duty):
                        pwm.ChangeDutyCycle(Duty - i)
                        time.sleep(0.1)
                pwm.stop()

except KeyboardInterrupt:
        pass

GPIO.cleanup()


PWM制御は、上記の通りGPIOライブラリでも使えるみたいですが、ソフトウェアで制御するためか
他の処理の影響を受けてしまい、安定しません。

そこでハードウェア側でPWM制御可能なwiringpiを使って同じことをしたいと思います。

wiringpi用のライブラリをインストールする

$ sudo pip3 install wiringpi

プログラムの作成

wiringpi_pwm.py
#!/usr/bin/env python3
# coding: utf-8

import wiringpi
import time

pwm_pin = 18
interval = 1

range2 = 1024
hz = 1 / ( interval * 0.001 )
clock = int( 18750 / hz )

# 初期設定
wiringpi.wiringPiSetupGpio()
wiringpi.pinMode( pwm_pin, wiringpi.GPIO.PWM_OUTPUT )
wiringpi.pwmSetMode( wiringpi.GPIO.PWM_MODE_MS )
wiringpi.pwmSetClock( clock )

# LED点灯
for i in range(101):
    duty = int(i / 100 * range2)
    print("i = ", i, "clock = ", clock, " duty=", duty )
    wiringpi.pwmWrite( pwm_pin, duty )
    time.sleep(0.05)

# LED消灯
for i in range(101):
    duty = int((100 - i) / 100 * range2)
    print("i = ", i, "clock = ", clock, " duty=", duty )
    wiringpi.pwmWrite( pwm_pin, duty )
    time.sleep(0.05)

PWMプログラムの実行

$ python3 wiringpi_pwm.py

wiringpiを用いた方がかなりキレイにLEDが光ったと思います。

3.NEMトランザクションを検知してみよう!

では、お待ちかね?のNEMトランザクションの検知をしてみましょう。

指定したNEMアドレスに着金があった場合にLEDが光るようにします。
なお、上記で作成した「wiringpi_pwm.py」を呼び出しているので、
「wiringpi_pwm.py」と同じ階層に配置頂く必要があります

プログラムの作成

address_transaction.py
import requests
import json
from time import sleep
import random
import os

node  = random.choice(("http://alice2.nem.ninja:7890","http://alice3.nem.ninja:7890",\
    "http://alice4.nem.ninja:7890","http://alice5.nem.ninja:7890",\
    "http://alice6.nem.ninja:7890","http://alice7.nem.ninja:7890"))
print(node)

api = '/account/unconfirmedTransactions'
parameter = 'address=NB3KO7I5RVBON2MNAO5K4STBCQROG5LUJHQB3EZM' 
# 一例としてnemlogのアドレスを記載しています。各自監視したいアドレスに変更下さい。

url = str(node + api + '?' + parameter)

nemTimeStamp = 0

while True:

    try:
        r = requests.get(url, timeout=(6.0, 7.5)).json()
    except:
        print("node is: ", node)
        node  = random.choice(("http://alice2.nem.ninja:7890","http://alice3.nem.ninja:7890",\
            "http://alice4.nem.ninja:7890","http://alice5.nem.ninja:7890",\
            "http://alice6.nem.ninja:7890","http://alice7.nem.ninja:7890"))
        print("node change: ", node)
        continue

    sleep(5)
    try:
        if not r['data']:
            print('none')
            continue
        elif nemTimeStamp != r['data'][0]['transaction']['timeStamp']:
            os.system('python3 ./wiringpi_pwm.py')
            print('トランザクションが' + str(len(r['data'])) + '個もあるって素敵やん')
            nemTimeStamp = r['data'][0]['transaction']['timeStamp']

    except:
        print('トランザクションが0個は泣けるやん')
        sleep(5)
        continue

着金確認プログラムの実行

$ python3 address_transaction.py

4.灯せ!nemの灯!

最後に、nemの灯のプログラムを紹介します。
最初は100%の明るさで光っており、
 ・2秒に1%ずつ暗くなっていく
 ・nemで生成されたブロックごとにトランザクション量を測り、その%分だけ明るくなる
というものです。

この灯を見ることで、今のnemの元気さ(トランザクション量の多さ)が直感的に分かるようになっています。

プログラムの作成

nemFire.py
import requests
import json
from time import sleep
import random
import wiringpi

### 初期設定 ###
# wiringpi
pwm_pin = 18
interval = 1

range2 = 1024
hz = 1 / ( interval * 0.001 )
clock = int( 18750 / hz )
wiringpi.wiringPiSetupGpio()
wiringpi.pinMode( pwm_pin, wiringpi.GPIO.PWM_OUTPUT )
wiringpi.pwmSetMode( wiringpi.GPIO.PWM_MODE_MS )
wiringpi.pwmSetClock( clock )
Duty = 100

# nem
node  = random.choice(("http://alice2.nem.ninja:7890","http://alice3.nem.ninja:7890",\
    "http://alice4.nem.ninja:7890","http://alice5.nem.ninja:7890",\
    "http://alice6.nem.ninja:7890","http://alice7.nem.ninja:7890"))
print("node first select: ", node)

api = '/chain/last-block'
url = str(node + api)

nemTimeStamp = 0
nemTimeStamp2 = 0

sleep_distance = 3

def up_pwm(duty, upcount):
    for i in range(upcount):
        wiringpi.pwmWrite( pwm_pin, int((duty + i) / 100 * range2) )
        print("up_pwm: ", (duty + i))
        sleep(sleep_distance / 10)

def down_pwm(duty, downcount=1):
    if duty <= 0:
#        wiringpi.pwmWrite( pwm_pin, 0 )
        sleep(sleep_distance)
        return

    for i in range(downcount * 10):
        wiringpi.pwmWrite( pwm_pin, int((duty - i / 10) / 100 * range2) )
        print("down_pwm: ", (duty - i / 10),"duty_turm: ", int((duty - i / 10) / 100 * range2))
        sleep(sleep_distance / 10)


try:
    while True:
        try:
            r = requests.get(url, timeout=(6.0, 7.5)).json()
        except:
            print("node is: ", node)
            node  = random.choice(("http://alice2.nem.ninja:7890","http://alice3.nem.ninja:7890",\
                "http://alice4.nem.ninja:7890","http://alice5.nem.ninja:7890",\
                "http://alice6.nem.ninja:7890","http://alice7.nem.ninja:7890"))
            print("node change: ", node)
            continue

        try:
            nemTimeStamp2 = r['transactions'][0]['timeStamp']

            if nemTimeStamp != nemTimeStamp2:
                print('トランザクションが' + str(len(r['transactions'])) + '個もあるって素敵やん')
                nemTimeStamp = nemTimeStamp2
                up_pwm(Duty,len(r['transactions']))
                Duty = Duty + len(r['transactions'])
                continue

        except:
            print('トランザクションが0個は泣けるやん')

        down_pwm(Duty)
        Duty = Duty - 1

        if Duty > 100:
                Duty = 100
        elif Duty < 0:
                Duty = 0

        print(Duty) 

except KeyboardInterrupt:
    pass

nemの灯の実行

$ python3 nemFire.py

所感

NEM好きの方はトランザクションが生まれる?ことに喜びを覚えている方が多い印象なので、
トランザクションを肌で感じれるようになればと思い、記事を書きました。
非エンジニアの方や電子工作未経験者の中から一人でも多くラズパイやプログラムに興味を持って頂けたら
マジガチ幸いです。

後半から解説とかが雑になりましたが、また機会があれば記事を出すようにします。
初めてのQiita記事で多々お見苦しい点もあったかと思いますが、大目に見てやってください。

アウトプットをすると自分の中でも整理出来て良いですね。

iotlt
IoT縛りの勉強会です。 毎月イベントを実施しているので是非遊びに来てください! 登壇者を中心にQiitaでも情報発信していきます。 https://iotlt.connpass.com
https://iotlt.connpass.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away