ニワとりの巣箱

面白いものが生まれたり生まれなかったり。

テラリウム管理装置を作る4

さあようやく完成に近づいてきました。

最後に取得した気温・湿度と画像をTwitterに流します。

 

まずはアカウントを作成します。

f:id:niwakxq:20171217190245p:plain

Pythonからつぶやくので、APIを利用するために

アプリケーションとアカウントを連携させなければなりません。

その際、電話番号認証が必須になるので

アカウント作成時に認証しておいた方がいいでしょう。

 

詳しい手順はこの辺を参考にしました。

www.statsbeginner.net

 

アプリケーションの認証用ページは

普通に検索してもなかなかたどり着けないので

メモ代わりにリンクを残しておきます。

apps.twitter.com

 

で、こちらで登録が完了すると、

コンシューマキーとアクセストークンというものが発行されます。

f:id:niwakxq:20171217203250p:plain

知られるとアカウント乗っ取られちゃうので消してありますが、

オレンジの辺りに表示されているランダムっぽい文字の羅列です。

Seacretと書いてある行と両方必要なので、それぞれコピーしておきます。

 

これが自分が作るアプリとTwitterの間の認証情報という奴になります。

アプリから渡されるこれらの値が正しければ、

このTwitterアカウントに対して操作ができるというわけです。

 

ここまで準備ができたらPythonでプログラミングです。

今回はTwythonというライブラリを使います。

ライブラリはあらかじめpipでインストールしておきましょう。

 

$ sudo pip install twython

 

とりあえずTwythonにさせたい処理は

画像とテキストを渡してツイートしてもらうことです。

ですがこれだけでも結構長くなるので、

簡単に呼び出せるようにライブラリ化しておきましょう。

#coding:utf-8

import os
import io
from twython import Twython
from PIL import Image

class TwitterAccess:

    CONSUMER_KEY = ''
    CONSUMER_SECRET = ''
    ACCESS_TOKEN = ''
    ACCESS_SECRET = ''

    def __init__(self):
        print('initialized')

    def tweet(self,text):
        apiInst = Twython(TwitterAccess.CONSUMER_KEY,TwitterAccess.CONSUMER_SECRET,TwitterAccess.ACCESS_TOKEN,TwitterAccess.ACCESS_SECRET)
        apiInst.update_status(status=text)

    def tweetImage(self,text,imgFileNm):
        apiInst = Twython(TwitterAccess.CONSUMER_KEY,TwitterAccess.CONSUMER_SECRET,TwitterAccess.ACCESS_TOKEN,TwitterAccess.ACCESS_SECRET)
        
        photo = Image.open(imgFileNm);
        image_io = io.BytesIO()
        photo.save(image_io, format='JPEG')
        image_io.seek(0)
        
        image_ids = apiInst.upload_media(media=image_io)
        apiInst.update_status(status=text, media_ids=[image_ids['media_id']])

最初にCONSUMER_KEY~ACCESS_SECRETまで4つの定数を定義していますが、

ここに先ほどTwitterのアプリ認証画面で発行された

コンシューマキーやアクセストークンを記入します。

 

あとはメインの処理からtweetImageを呼び出せば、

画像付きのツイートが送信できるはずです。

というわけで、テスト用にこんな感じの処理を書きました。

#coding:UTF-8

import RPi.GPIO as GPIO
import dht11
import time
import datetime
from twython import Twython

import TwitterAccess
import ImageCapture

# initialize GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.cleanup()

dht11Inst = dht11.DHT11(pin=4)

dateTimeFormat = "%Y/%m/%d %H:%M:%S"
filePath = '/usr/app/niwashi/img/capture.jpg'

twitter = TwitterAccess.TwitterAccess()
capt = ImageCapture.ImageCapture()

loopContinue = True

while loopContinue:
    sleepTime = 60
    
    current_time = datetime.datetime.now().strftime(dateTimeFormat)

    loopRead = True
    
    while loopRead:
        dht11Read = dht11Inst.read()
        
        if dht11Read.is_valid():
            textTweet = 'ゲンザイノ ニチジハ ' + current_time + ' キオン ' + str(dht11Read.temperature) + '℃ ' + 'シツド ' + str(dht11Read.humidity) + '% デス.'
            
            if capt.putImage(filePath):
                twitter.tweetImage(textTweet, filePath)
            else:
                twitter.tweet(textTweet)
            
            print('success tweeted.')
            
            loopRead = False
            
        else:
            print('dht11 error')
            time.sleep(1)

    time.sleep(sleepTime)

60秒間隔で気温・湿度を取得、画像を撮影し

Twitterに投稿するプログラムです。

 

気温・湿度の読み取りに失敗した場合は1秒待って再度読み取り

画像の取得に失敗した場合はテキストだけツイートします。

 

画像の取得もライブラリ化してますが、

やっていることは前々回の記事の通りです。

 

うまくいっていれば、このようにツイートできているはずです。

f:id:niwakxq:20171217212357p:plain

 

これはあくまでテストですが、

実際のプログラムはエラーが続いた場合に停止する処理や

1日に時間を決めて何回かだけツイートするようにしています。

(長いのでコードは後程GitHubにでも挙げるかもしれません)

 

なにはともあれひとまずこれで完成です!

Twitterアカウントは公開しているので、

興味のある人はフォローしてみてください。

twitter.com

テラリウム管理装置を作る3

大変です。

モタモタしている間に、

(管理装置の有無とか水やりに関係なく)

苔がどんどん茶色くなっていきます。

やはり寒いのか…

 

f:id:niwakxq:20171207002518j:plain

 

相変わらず完全に枯れているわけではなさそうですし、

よく見ると一部新芽らしきものもあるので

ダメと言い切るには早いのですが

いかんせん元気がなさそうです。

 

今のところ特にできることもなく、様子を見るしかありません。

誰か詳しい人がいたらどうすべきか教えていただきたい…

 

 

手段が目的になり若干本末転倒な気はしますが

作りかけの管理装置は完成させてしまいましょう。

 

今回は温度と湿度を計測できるようにしたいと思います。

調べてみると、この辺のセンサーを接続するのが定番のようです。

 

上の画像と基板が若干違いますが、センサー自体は同じものです。

抵抗付きなのでこのまま接続できて便利です。

f:id:niwakxq:20171206235040j:plain

結構メジャーな安価センサーらしく、秋月電子さんとかでも買えます。

 

この辺の記事を参考に、

qiita.com

GPIOとセンサーを接続します。

どのピンをどのピンに接続するかは、上の記事と基板を見ながら何となく判断しました。

 

ちなみに私が使ったものの場合、写真の3本のケーブルは

 赤が2番(5V)

 黒が6番(grand)

 緑が7番(GPIO4)

に接続するのが正解でした。

この辺は多少違っても試行錯誤でつなぎ変えているうちに正解にたどり着けます。

センサーは初期不良があったり、うっかり壊すこともあるので

安ければ2~3個買っておいてもいいでしょう。

 

センサーの値は、Pythonから取得します。

ありがたいことに、そのためのライブラリが公開されているので

遠慮なく使わせてもらいます。

https://github.com/szazo/DHT11_Python

 

いくつかファイルがありますが、必要なのはdht11.pyという奴です。

この中に書いてある処理を、自分のソースコードから呼び出せばいいわけです。

dht11_example.pyが呼び出し方のサンプルになっているので、

それを参考にこんな感じで取得処理を書きます。

#coding:UTF-8

import RPi.GPIO as GPIO
import dht11
import time
import datetime

# initialize GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.cleanup()

dht11Inst = dht11.DHT11(pin=4)

dateTimeFormat = "%Y/%m/%d %H:%M:%S"
current_time = datetime.datetime.now().strftime(dateTimeFormat)

sleepTime = 30

loopRead = True
        
while loopRead:
    dht11Read = dht11Inst.read()
 
    if dht11Read.is_valid():
        textTweet = 'ゲンザイノ ニチジハ ' + current_time + ' キオン ' + str(dht11Read.temperature) + '℃ ' + 'シツド ' + str(dht11Read.humidity) + '% デス.'
        print(textTweet)
    else:
        print('dht11 error')
        loopRead = False
               
    time.sleep(sleepTime)

 

dht11というのがライブラリの呼び出しで、

readして成功したら気温と湿度を出力する

readが失敗したら終了

です。

実際に動かしてる奴から抜粋してきたので

どこか間違ってたらごめんなさい。

 

30秒間隔で読み取ってみましたが、

結構頻繁にエラーになります。

失敗しても何度かリトライするようにした方がよさげ。

 

うまくいけば、実行画面に

ゲンザイノ ニチジハ 2017/11/14 17:16:25 キオン 19℃ シツド 95% デス.

のように表示されます。

 

さあこれで残るはTwitterとの連携ですね。

続く

テラリウム管理装置を作る2

テラリウムの映像を取得するカメラをラズベリーパイに実装します。

※不慮の事故によりOSの再インストールを行ったので、

以降の記事はOSがWeezyではなくJessieになってます。

 

ラズベリーパイには専用のカメラモジュールもありますが、

結構いいお値段しますしその割に性能が限られるので

気軽に取り替えられる市販のWEBカメラを接続して使いたいと思います。

 

アマゾンで安いのを探しました。

<iframe style="width:120px;height:240px;" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" src="https://rcm-fe.amazon-adsystem.com/e/cm?ref=qf_sp_asin_til&t=niwatomarigi-22&m=amazon&o=9&p=8&l=as1&IS1=1&detail=1&asins=B0087UMLJI&linkId=568e9a41b9737596615bc51b64c66808&bc1=FFFFFF<1=_top&fc1=333333&lc1=0066C0&bg1=FFFFFF&f=ifr">
</iframe>

 

これをラズベリーパイに接続します。

USBなので特に何も考えず、とりあえず挿せばよし。 

f:id:niwakxq:20171114000744j:plain

 

カメラが認識されているか確認

$ lsusb

Bus 001 Device 005: ID 056e:7016 Elecom Co., Ltd
Bus 001 Device 004: ID 2019:ab2a PLANEX GW-USNano2 802.11n Wireless Adapter [Realtek RTL8188CUS]
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

 

1行目にELECOMって出てるので多分これでしょう。

 

カメラとして機能しているか確認するため、

簡単なビューワーをインストールします

$ sudo apt-get install guvcview

 

起動

 

$ guvcview

f:id:niwakxq:20171123204105j:plain

 

いい感じに映りました。

(OSがWeezyだとこれがうまく映らず、真黒な画面が表示されますが

以降の手順には影響ないので気にせず続行してください)

 

あとお気づきかと思いますが、苔の一部というか大部分が

茶色くなってしまっています。

原因は不明ですが、こういうこともあるみたいです。

最近急に寒くなったことが関係あるのかもしれませんし、

この苔とテラリウムの環境が合わなかった可能性もあります。

(今のところ水やりは怠ってませんよ!)

一応枯れているわけではなさそうなので

部屋を温めたり日に当てたりして復活を期待したいと思います。

 

 

実際の撮影はPythonで行います。

Python自体は元々RaspberryPiに入っています。

バージョンを確認するとこんな感じ。

$ python --version

Python 2.7.13

 

ここに画像を扱う定番のOpenCVというライブラリを入れます。

$ sudo apt-get install libopencv-dev
$ sudo apt-get install python-opencv

ここからプログラミングです。

と言っても画像を取得して保存するだけなので簡単。

これだけです。

 

#!/usr/bin/env python
# coding:utf-8

import cv2
import time

c = cv2.VideoCapture(0)

ret, img = c.read()

if ret==True:
    cv2.imwrite('/usr/app/niwashi/img/capture.jpg', img)

c.release()

 

細かい解説はよそのサイトに譲ることにして、

/usr/app/niwashi/img/capture.jpg

というファイルに撮影した画像を保存しているだけです。

これをデスクトップで確認してみると、

f:id:niwakxq:20171125021031j:plain

映りましたが、真っ暗です。

撮影できていないわけではないので、

明るさの調整の問題と思われます。

 

 

どうもカメラには自動補正機能があるらしいです。

こちらのページを参考に、複数回撮影してから本撮影するようにしました。

ラズパイでUSBカメラを使うときに知っておきたいこと | hiro345

 

…省略…

c = cv2.VideoCapture(0)

for i in xrange(30):for i in xrange(30):

    ret, sample = c.read()

ret, img = c.read()

…省略…

 

f:id:niwakxq:20171125021816j:plain

映りました。

ちょっと暗いのは撮影したとき部屋が暗かったからです。

照明があったほうがいいかもしれませんが、

基本的にはこれでよさげです。

解像度が低いですが、そこはカメラの性能。

もうちょっと高いのを買えばよかったかもしれませんが、

苔の状態はなんとなくわかりそうなのでよしとしましょう。

 

次回に続きます。

ラズベリーパイをついばむ Wi-Fiに接続する

テラリウムの方も進めてはいますが、

実は無線でのインターネット接続もできるようにしていたので

その覚書です。

 

本当はだいぶ前からできるようになってたんですが、

先日ちょっとアクシデントにより

OSの再インストールからやり直す羽目になりまして。

Wi-Fiの接続方法を書き残していなかったためにだいぶハマりました。

反省。

 

RaspberriPi3だとWi-Fiモジュールを内蔵してたりしますが、

私が使っているのは2Bなので

USB接続の子機を使用しています。

 

なおOSの再インストールでバージョンが

WeezyからJessieに上がっています。

 

f:id:niwakxq:20171120220757j:plain

 

とりあえず差し込んで認識されているか確認

$ lsusb
Bus 001 Device 004: ID 2019:ab2a PLANEX GW-USNano2 802.11n Wireless Adapter [Realtek RTL8188CUS]
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. SMC9514 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

 

1行目のように機器名が表示されていればOK

 

次に接続パスワードを暗号化

$ wpa_passphrase ルーターSSID 接続パスワード
network={
    ssid=ルーターSSID
    #psk=接続パスワード
    psk=暗号化された接続パスワード
}

これをコピーして

 

下記の設定ファイルを開き

$ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

末尾に貼り付ける(暗号化前の接続パスワード行は消す)

country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid=ルーターSSID
    psk=暗号化された接続パスワード
}

 

今度は以下の設定ファイルを開いて、

$ sudo nano /etc/network/interfaces

下記の内容を追加(固定IPを割り当てる書き方)

auto lo
iface lo inet loopback

allow-hotplug eth0
iface eth0 inet dhcp

auto wlan0
allow-hotplug wlan0
iface wlan0 inet static
address 割り当てる固定IP
netmask サブネットマスク
gateway ルーターのIP
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

 

これで再起動して、うまくいってるか確認

$ ifconfig

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 割り当てた固定IP netmask サブネットマスク broadcast ルーターのブロードキャストアドレス
ether MACアドレス txqueuelen 1000 (イーサネット)
RX packets 1333 bytes 191702 (187.2 KiB)
RX errors 0 dropped 7 overruns 0 frame 0
TX packets 607 bytes 105485 (103.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

 

inetに続いて割り当てた固定IPが表示されていればOK

ブラウザでネットにつながってるか確認する

 

必要なのはこれだけなんですけどねー

書き間違えたり余計なこと書いたりでなかなか動かず苦労しました…

テラリウム管理装置を作る1

f:id:niwakxq:20171112155712j:plain


テラリウムの苔を枯らさないために

管理装置を作っていきます。

 

まずはどんな装置にするか決めます。

第1段階は遠隔監視ができることが目標です。

 

監視項目は、

・映像(苔は動かないので静止画)

・気温

・湿度

の3つにしたいと思います。

 

苔は基本的に根から水分等を吸収しないので、

土壌の水分ではなく空気中の水分が多いことが重要です。

また気温が高すぎても低すぎてもいけません。

といっても具体的に何度・何%なら大丈夫という数値があるわけではないので、

まずは様子を見ながらデータが取れればいいかと思います。

 

実際の異常・変化の有無は見た目で判断するしかありません。

数値だけでは見た目も地味でモチベーションが上がりませんし。

画像は必須です。

 

一度に色々やりすぎるとなかなか完成しませんから、

機能はとりあえずこのくらいで十分でしょう。

 

そしてこれらの監視項目をどうやって見るかですが、

私も日常生活で消費する情報は大体ツイッターから摂取する

ツイッターランドの住人ですから、

タイムラインに流れるようにしたいと思います。

 

ここまでやることが決まれば、機器構成も大体決まりますね。

セットアップしていたRaspberryPiがついに活躍する時がきました。

これにカメラと温度・湿度センサを追加します。

制御にはRaspberryPiと相性の良いPythonを使うのがよさそうです。

ラズベリーパイのパイはパイソンのパイ)

Twitterとの連携も問題なくできるようです。

 

あとは名前を付けておきましょう。

テラリウム管理システム『NumaNoNiwashi』通称『N3』

(沼は私の自宅の通称&最終的には庭師の仕事をしてくれる予定)

 

それでは次回から開発スタートです。

ガンダムテラリウム改

はい、というわけでなんとかしました。

と言っても苔を植え替えただけですが。

 

f:id:niwakxq:20171105225524j:plain

f:id:niwakxq:20171105225532j:plain

f:id:niwakxq:20171105225538j:plain

 

前回はシノブゴケという苔でしたが、今回はスギゴケです。

多少樹木のミニチュアっぽい?ですかね。

損傷して森林地帯に放棄された兵器的な雰囲気が出るといいんですが。

(こういう妄想がモチベーションになるので重要) 

 

 

しかし問題はここからです。

苔は水さえ与えれば生きるという比較的手間のかからない植物ですが、

前回はそこに甘えて「多少ほったらかしても大丈夫じゃろ」と思っているうちに

うっかり存在を忘れて残念なことになってしまいました。

シノブゴケの犠牲を無駄にしてはいけません。

 

そこで今回は、

 ①存在を忘れないための遠隔監視

 ②多少ほったらかしても枯らさないための水やりの自動化

という二重の対策を施したいと思います。

 

つづく

おひさしぶりです

 うっかり放置したまま2年も経ってしまいました。

すみません。

 

ちょっと提督業にハマったり

薄い本を買い漁ったり

イカになってインクばら撒いたり

ポケモンを探して歩き回ったり

孤独のグルメをエンドレスリピートしたり

にわとりのフレンズになったり

結婚したりしているうちにね…

 

別にやっていることは相変わらずなので

何事もなかったかのように続きます。

 

しかし2年も経つと色々ありまして

このブログの最初に作ったガンダムテラリウムを

すっかり枯らしてしまいました。

 

f:id:niwakxq:20170926204058j:plain

f:id:niwakxq:20170926204114j:plain

 

元々毎日世話をするのが苦手なんですよねー…

苔は比較的放置しても大丈夫なんですけど、限度はあります。

まずはこれをなんとかしたいと思います。