ゆっくり技術ノート!

いつかきっとできるだろうよ

Raspberry Pi で温度と湿度を知る

Raspberry Pi で温度と湿度を知る

はじめに

この記事はおうちハック Advent Calendar 2016の21日目の記事です。
前日:ajimitei labo.: HUIS でいらすとやリモコンを作ってみた
翌日:MQTTベースのおうち環境にMESHを追加する - Qiita

遅刻記事になってしまい本当にすいません。
RasPiの不調と、風邪をひいてしまったのと、能力不足で遅くなってしまいました。

環境と機器

  1. Raspberry Pi B 3 (Rasbian 2016-11-25)
  2. 温湿度計 HDC1000

手順

実際の試行錯誤はトラブルの項にまとめています

Step.1 Rasbianの初期設定を終わらせてからraspi-configでi2cを有効にします

sudo raspi-config
7 Advanced Options > I2C

Step.2 確認します

lsmod

Step.3 i2c-toolsをインストールする

sudo apt-get install i2c-tools

Step.4 HDC1000の接続を確認

sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Step.5 Wiring Piはデフォルトで入っているので再度入れる必要はないです

Step.6 HDC1000から温湿度を読む

gcc -Wall -o hdc1000_sample -lwiringPi hdc1000_sample.c
sudo ./hdc1000_sample

Raspberry Pi 2 Model B でI2C 温度+湿度センサーモジュール(HDC1000)を使う - Qiita
とうい記事の中のサンプルコードをほとんどそのまま使わせてもらいました
ありがとうございます

Step.7 継続的なログを見るためにcsvを作ります

これをcronで実行します

require "csv"
results = `sudo ./hdc1000_sample`
stamp  = Time.now.to_s + "," + results
File.open("/home/pi/outi_hack/tem_hyg.csv","a"){|f|f.puts(stamp)}

Step.8 ブライザで見るためにSinatraで表示させます

sudo apt-get install -y sinatra
sudo apt-get install -y sinatra-contrib

require "sinatra"
require "csv"
require 'sinatra/reloader' if development?
set :bind, '0.0.0.0'

get '/' do

    logs = CSV.read("tem_hyg.csv").reverse
    time = logs[0][0]
    tem = logs[0][1]
    hyg = logs[0][2]

    p "TEM: " + tem + " HYG: " + hyg + "   (#{time})"

end

できました!

f:id:Coro:20170129180030p:plain

トラブルと嵌ったところ

恥を忍んで公開します、笑ってやってください

配線を間違えてHDC1000を壊す

  • 暗がりでRasPiにジャンパー線を差し込んでいたら青と黒を見間違えて壊しました
  • 焦げ臭くなって基板上のセンサチップの半田が溶けて位置がずれた
  • RasPiが壊れなかったのは不幸中の幸い

i2c が有効にならない

  • 最初はRaspberry Pi B 1 Rev.2でRasbian(2016-11-25)を使っていたのですがraspi-configでもi2c や spi の項目ができこず/etc/modulesなどで手動で試みるも有効になりませんでした
  • 結局 Raspberry Pi B 3 を用意して再度やったら何の問題もなくraspi-config`から有効にできました
  • 今記事を書いてる時点で確認したら Raspberry Pi B 3 でもI2Cの項目が消えました f:id:Coro:20161228032233p:plain

RasPiが家の外に繋がらない

  • 家の中の他の PC には ping が通るのですがapt-getできなかったりwgetできなかったりしました
  • 原因がわからなかったので OS を再書き込みしました

sshができない

Sinatraが外から見えない

おわりに

  • i2cはArduinoで使ったことがあったので「温湿度表示とか簡単だろう」とたかをくくっていましたが、大変なことになってしまいました
  • 本当はESP-WROOM-02で温湿度やCO2を計測してマトリクスLEDなんかをつけることを妄想していたのでいつになるかわかりませんが、やりたい
  • 温度と湿度があっているのか調べるために家にあったアナログの温湿度を3つHDC1000の隣に置いていたのですが温度は3つのアナログ温度計もHDC1000も大体一致するのですが湿度に関してはすべて約15%の誤差があり湿度を正確に知るのは難しいことがわかりました f:id:Coro:20161228033953j:plain
  • ここまでお付き合いいただきありがとうございました

参考URL

  1. Raspberry Pi 2 Model B でI2C 温度+湿度センサーモジュール(HDC1000)を使う - Qiita
  2. 共有ライブラリへパスを通す | hajichan.net technical version
  3. Raspberry Pi 3でRaspbian Jessieをセットアップする方法 - karaage. [からあげ]
  4. RubyでWiringPiを使う | ぬわーーーーーーー!!!
  5. 「全裸で学ぶMVC事始め」をruby + Sinatraでやってみた - 飲む、寝る。
  6. Raspberry Pi の I2C を有効化する方法 (2015年版) – ymyzk’s blog

ありがとうございます

玄関をSuicaで開ける

玄関をSuicaで開ける

この記事は おうちハック Advent Calendar 2015 の23日目の記事です。

動機

私は普段、家の鍵を他の鍵と一緒にでまとめてをオシリポケットに入れているのですが、座ると鍵が当たって痛いので PASMOSuica で開けられるようにしたいと思います

私は iPhone なので FeliCa を搭載していないため iPhoneiPhoneケースの間に PASMO磁気干渉防止シートを挟んで使っています

では、作っていきましょう!

この記事を見れば作れるようにしたいので少しくどくなるかもしれませんが、ご了承ください
セキュリティはあまり考えていません。試す際は自分で対策してください
(でも多分、空き巣は NFC をハックするより窓を割って入ってくる方が簡単)

構成

今回、時間をかけず簡単に作るために機能を最低限の「NFC をかざしたら鍵を開ける(そして自動で閉める)」という機能に絞ることにします
NFC リーダ はこの手の工作では定番の RC-S380 を使います
サーボモータは鍵のサムターン(つまみ)を回すことを考えてトルクの大きなものを秋月電子で購入しました

https://gyazo.com/ef7c2750e751b7af3209cf18c9c2fe93:plain:w300

NFC からidmを取得する

Raspberry Pi の公式から Raspbian jessie を落としてSDカードにセットし IPアドレスの固定等の設定を行ったら(今回はRaspberry Pi Bを使います)
いよいよ PASMO から idm を取得します
idm とは PASMO/Suica 等の製造番号のことです

nfcpy

NFC を使うためのツールであるnfcpyを使います
これは公式サイトGetting started の通りやるとインストールできました
bzrというバージョン管理システムをinstallして、nfcpyをinstallしたい場所に移動、bzrでnfcpyをinstallします

sudo apt-get install bzr
cd <hoge>
bzr branch lp:nfcpy trunk

続いて Python で USB を使うたに python-usb をinstallします

sudo apt-get install python-usb

できたらサンプルコードを動かしてみましょう

sudo python examples/tagtool.py

PASMO等をタッチして、こんな感じにIDが表示されたら成功です https://gyazo.com/450bf973357d0df5bcfa0f59bc1cff4c

今回はこのサンプルコードをそのまま使わせてもらいます

サーボを動かす

ServoBlaster

サーボを動かすにはServoBlasterというCで書かれたツールを使います
git で公開されているのでgit clone してきて、Cのコードをmakeでコンパイルしinstallします

git clone git://github.com/richardghirst/PiBits.git
cd PiBits/ServoBlaster/user
make
sudo make install

サーボを動かしてみる

ServoBlasterは/dev/servoblasterに文字列[Servo_number]=[0-100]%を書き込むことでサーボを動かしてくれます

echo 4=100% > /dev/servoblaster

ServoBlasterで指定するServo_numberはgpioのピン番号とは違うので注意が必要です
https://gyazo.com/0c86c45477643e795ca7b5481fd835b8
https://gyazo.com/00d9e01f2b023184ecb46b7694edd4ae
ここではパーセンテージで指定するのでサーボを見ながら鍵を開けるのに良い角度を探ります
私のサーボの場合は91と40でした
このServoBlasterのいいところは使っていない時サーボに電圧をかけないところです
このため普通の鍵でも手で開閉錠できます

サーボが動いたら NFC をかざした時サーボを回してみましょう

サーボについて追加情報があります *1

登録したidmの時サーボを回す

Ruby から nfcpy と ServoBlaster を使うコードを書きます
ただコマンドを実行するだけなので簡単です
(ServoBlasterは Ruby の File.write ではダメな模様)

#ここは先ほど表示させた自分のidmに書き変える
USERS = {"Bob_Marley" => "xxxxxxxxxxxxxxxx",
        "Alice_Cartelet" => "xxxxxxxxxxxxxxxx"}
#ここも自分のサーボにあったものに書き換える
#s03t-2bbmg servo
UNLOCK_ANGLE = "91"
LOCK_ANGLE = "40"

AUTO_LOCK = 40

def nfc()
    #ここも自分の環境にあったものを指定
    `sudo python ~/Documents/nfc/trunk/examples/tagtool.py`
end

def idm(text)
    m = text.match(/ID=(.*?)\s/)
    idm =m[1]
    print("IDm = #{idm}\n")
    return idm
end

def unlock()
    print("Unlocking\n")
    `echo 4=#{UNLOCK_ANGLE}% > /dev/servoblaster`
end

def lock()
    print("Locking\n")
    `echo 4=#{LOCK_ANGLE}% > /dev/servoblaster`
end

loop do
    idm = idm(nfc)
    unlock_user = USERS.key(idm)

    unless unlock_user == nil
        print("Welcome back #{unlock_user}!\n")
        unlock

        print("Wait #{AUTO_LOCK}sec...")
        sleep(AUTO_LOCK)
        print("\n")

        lock
    else
        print("Illegal user\n")
    end

    print("Please wait reader restart...\n")
end

実行するとこんな感じに動くと思います https://gyazo.com/08b4d3d417724a3c00b491bfa92ea553 動画には写っていませんが40秒後に閉まります

土曜の進捗

A video posted by coro365 (@coro365) on

ハードウェア

鍵のサムターン(つまみ)にサーボを取り付けるための木材をノコギリとドリルで作成します
30mm*30mmの角材を30mmで切ってサイコロ状のものを作成、サムターンに合う穴を開けます
Image from Gyazo

続いてサーボを固定するためにダンボールでマウントを作成します
ダンボールを10枚積層、木工ボンドで合わせて完成です
ダンボールだととても簡単でよかったです(1時間ほどアニメ見ながら切りました)
Image from Gyazo

レーザ加工機が使う余裕があればアクリルで作ってもいいかもしれません
ただダンボールでも木工ボンドで補強するとかなり頑丈になります
ちなみに今回は溜まりに溜まったamazonの箱を使いました
https://gyazo.com/901a037740a05a6df9c20aec7ca3547a

取り付けて完成です

Image from Gyazo 動かすとこんな感じ(このNFCリーダは表からも裏からも使えました)

今後

  • 開閉錠ボタンと状況表示用のLEDを付けたい
  • 鍵が開いているか閉まっているかの状態を確認したい
  • リードスイッチ(磁気を感知するスイッチ)でドアの開閉を検知してオートロックの挙動に生かしたい
  • Sinatraとかでブラウザ上で開閉とログの確認をしたい
  • Supervosorを使ってRaspberry Piのデーモンにする

雑感

  • ServoBlasterとnfcpyが優秀ですぐにできてしまった
  • 一番時間がかかったのはマウントを作成するところ(ダンボールで作る前にアクリルをノコギリとドリルで加工して半日無駄にしている)
  • PASOM決済だけで生活できればiPhoneだけ持ち歩く生活にできるかも
  • 個人が少しのお金で、いろんなことが可能な環境は素晴らしいなと思いました(この方向で人間、進化してもらいたい)
  • 今後も隙を見ておうちを便利にしていきたいです

初めて Advent Calendar に参加しましたがイベントドリブンな感じで作ることができたので参加してよかったです(参加しなかったら作らなかったかも)
そんな おうちハック Advent Calendar 2015 の明日の記事は @YarmUIさん の スマートメータを自作した話 です
良いお年を!

購入したもの

Raspberry piは部屋に転がっていたものを使ったので出費は 4000円ほど

  1. Amazon.co.jp: Raspberry Pi Type B 512MB: パソコン・周辺機器
  2. Amazon.co.jp: SONY 非接触ICカードリーダー/ライター PaSoRi(パソリ) USB対応 RC-S380: パソコン・周辺機器
  3. GWSサーボ S03T/2BBMG/F(フタバ): サーボ 秋月電子通商 電子部品 ネット通販

ドアセンサ、開閉スイッチなどをつける時は必要です

  1. タクトスイッチ 12mm TVGP01-G73BB(黒): パーツ一般 秋月電子通商 電子部品 ネット通販
  2. ピンヘッダ 1×40 (40P): パーツ一般 秋月電子通商 電子部品 ネット通販
  3. ケース入りリードスイッチ(磁石付セット)MC-14AG: センサ一般 秋月電子通商 電子部品 ネット通販

参考ページ

  1. Raspberry PiにRaspbianをインストールする for Mac OSX
  2. Raspberry Pi 2 (Raspbian: jessie) でIPアドレスを固定する
  3. PWMでRaspberry PiのLEDの明るさ調整する
  4. FeliCa(フェリカ)IDmとは?|ステルス・ネットワークス
  5. Python module for near field communication — nfcpy trunk documentation
  6. Raspberry-PiにおけるGPIO関係ツールのインストール方法 | Раздан-3
  7. GPIO: Raspberry Pi Models A and B - Raspberry Pi Documentation
  8. nfcpyでお手軽NFC開発[1/2]

ありがとうございます

追記1 2017/08/09

サーボモータを回転させた際RasPiが再起動してしまう時は、別に電源を用意してください。
私の場合は、以下のように別電源にしました。(この方法が最適解かどうかはわかりません)

  1. USBケーブルを用意し皮膜をはがした後、プラスとマイナスの線をより分けます。
  2. プラスの線はサーボのプラスにつなぎ、マイナスの線 はサーボ と RasPi のGroundに繋ぎます。
  3. USBケーブル自体はApple USB 充電器 に繋ぎます

追記2 2017/08/09

多くの方にこの記事を読んで頂き大変嬉しく思っております。
また、この記事を見て同じものを作ろうとしている方の何人に連絡をいただきとても嬉しいです、記事にした甲斐がありました。
記事公開から1年以上経ち、その間にも iPhoneSuica 対応したり、電子マネー対応の店が増えてきたり、スマフォでATMからお金を引き出せたり、iPhone 1つで生活できる世の中に近づいている気がしてワクワクしています。

さて、この記事で作った物にLED,ドア開閉センサ,ボタンを追加した物がGithubに上がっているので、こちらもどうぞ。
github.com

追記おわり

*1:追記1 2017/08/09 をご覧ください

AppleScriptでiTunesのテレビ番組を連続再生する

iTunes のテレビ番組を連続再生するには再生したいテレビ番組をプレイリストに登録してリピート再生するという方法がある。
しかし、毎度毎度プレイリストを作るのは大変なので AppleScript を使って自動で次のエピソードに移動するようにしてみる

仕組み

  1. Scriptを起動したら TV Show が再生されていないか20秒毎にチェックする
  2. 再生されていたらそのEpisode の合計時間と現在の再生位置から残りの再生時間を3分ごとに調べる
  3. 残りの再生時間が3分以下になったら1分ごとにチェック、1分以下になったら1秒ごとにチェック
  4. 残りの再生時間が1秒以下になったら次のEpisode に移動する
  5. 2にもどる

今回使った命令いろいろ

次のEpisode に移動

  • これは他の種類のメディア(音楽とか)にも使えてキーボードについている送りキー[▶︎▶︎]と同じ機能を持つ
tell application "iTunes"
    next track
end tell

再生中のトラックの合計時間を調べる

  • 1:20:30(h:m:s) のように出力される
tell application "iTunes"
    set timeSize to time of current track as text
end tell

再生中のトラックの再生済みの時間を調べる

  • 秒で出力される
  • 再生されていない時は missing value となる
tell application "iTunes"
    set nowPositionSec to player position
end tell

コードは Gist にある

This applescript will automatically play the episode of the next iTunes TV show. · GitHub

  • 右にあるDownload ZIPからダウンロードする
  • Script Editor で開いて.app形式で保存する
  • Spotlight から起動したり、iTunes Scriptフォルダに入れて iTunes からも起動できる
  • iTunes Scriptフォルダは~/Library/iTunes/Scripts

参考ページ

  1. 鳶嶋工房 / AppleScript / Tips / スクリプトの中断
  2. iTunes for Mac まとめ - AppleScript
    • iTunes関連の命令について
  3. life log: AppleScript 最速基本文法マスター
  4. iTunes Scripts の使い方
    • iTunes Scriptフォルダの場所

ありがとうございます

Raspberry Pi で家電を操作する1

目次

今回は長くなるので複数回に分ける
  1. Raspberry Pi で家電を操作する1 (MacにWebサーバを設置して照明を操作する)
  2. Raspberry Pi で家電を操作する2 (Raspberry PiにWebサーバを設置して照明を操作する)[未投稿]

やりたいこと

  1. 今回はブラウザから部屋の照明のスイッチをサーボモータで動かしon/offさせたい
  2. 最初は Mac で作ってからRaspberry Pi に移す

構成と環境

Raspberry PiArduino の通信はシリアル通信を使用した
Raspberry Pi から直接サーボを操れるようだが、慣れているので Arduino を使用した。そのうち変更するかもしれない Gyazo

  1. OS X 10.10.2
  2. Arduino UNO
  3. ruby 2.0.0p598
  4. serialport (1.3.1)
  5. sinatra (1.4.5)

作業の軌跡

  1. Arduino でシリアルを受信してサーボを動かす
  2. Sinatra からシリアル信号を送る
    1. 時間差をつけてシリアル信号を送る
  3. Sinatra にタイマー機能をつける
  4. Raspberry Pi に移す
    1. IPを固定する
    2. ホスト名でリモート接続できるようにする
    3. 作成したSinatraアプリケーションをデーモンにする

Arduino でシリアルを受信してサーボを動かす

シリアル信号に応じてサーボを右もしくは左に少し回して照明などのスイッチをon/offする
スケッチは以下のような感じになった

  1. loop で常時シリアル信号を監視する
  2. 信号は数字になっていてそれぞれに対応したアクションを探す
  3. アクションが決定したら実行する
  4. サーボをデフォルトの位置に戻す

codeはgistにある
Arduino のコード

動作はこんな感じになった Gyazo

Sinatra からシリアル信号を送る

Sinatra でブラウザにon/offボタンを表示させ押せれたらシリアル信号を送るとようにしたい
Sinatra とは Ruby on Rails のような Ruby で Webサーバを立てるためのドメイン特化言語(DSL)です

Sinatra でシリアル通信を扱うためにはgemのserialportが必要なのでinstallする
gem install serialport

コードは以下のようになった

  1. 初期動作
    1. textで保存したシリアルポートの名前(環境によって異なる)を読み込む
    2. シリアルのインスタンスを作成
  2. /がリクエストされたらon/offボタンのあるhtmlを送る
  3. スタンドライトのonのボタン/standOnが押されたらシリアルを送信し/にリダイレクトする

見た目も良い感じになったと思う Gyazo

嵌ったところ1 逆引きDNS

localhost:4567でアクセルするとロードが100ms程度で終わるのに対しIPアドレスを直接指定すると1分以上かかってしまった
どうやらSinatra側がアクセスしてきたクライアントのIPアドレスをホスト名に変換するときに hosts が設定されていないとタイムアウトするまで時間がかかってしまうらしい (この解釈であってるかわからない)
DNS逆引きを止めるコードがネット上にあったので使わせてもらうことにした
sinatraでDNS逆引きを止める | TechRacho

嵌ったところ2 inline-block の隙間

今回 inline-block を使ったがリストタグ<ul>内に改行があると改行が半角スペースとなって表示されるらしい
その影響で各ボタンの間に隙間ができてしまって結果的にレイアウトが崩れてしまった

CSS で inline-block の文字間を 0em にして inline-block中 のulの文字間を xx-large とすることで解決した
一部を抜粋

ul{
    list-style:none;
    font-size: 0em;           /* inline-block 隙間対応*/
}

li p, .on, .off, .timer{
    padding: 30px 0px;
    margin: 0px;

    display: inline-block;
    font-size: xx-large;  /* inline-block 隙間対応*/

    color: #FFFFFF;

}

rerun

余談だが今回始めてrerunを使ってみた
rerun は関連するコードが更新されるとsinatraを再起動してくれる sinatra-contribだとイマイチ動こかないことがあったが rerun はいい感じに再起動してくれる
gem install rerunしてrerun 'ruby app.rb'する
Sinatra: Frequently Asked Questions

タイマー機能を作る

今回は簡単に指定時間 sleep させたあと任意のアクションのアドレス(例えばlocalhost:4567/standOn)にアクセスするようにする
コードはこんな感じになった

require "open-uri"

Hour = 3600

#Create mode
print("Select Mode\n1. Stand Light On\n2. Stand Light Off\n3. Room Light On\n4. Room Light Off\n--> ")
mode = gets.to_i

case mode
when 1 then mode = "standOn"
when 2 then mode = "standOff"
when 3 then mode = "roomOn"
when 4 then mode = "roomOff"
else
    print("Mode error\n")
    return 0
end
print("Select #{mode}\n\n")

#Create timelimit
print("Select Time(hour)\n--> ")
limit = gets.to_i
print("Select #{limit}hour\n\n")

#Wait
print("Waiting #{limit}hour...")
sleep(Hour * limit)
print("\n\n")

#Acsess
open("http://localhost:4567/#{mode}").read
print("Done\n")

Sinatra にタイマー機能をつける

上記のタイマだとターミナルからしか使えないのですこし面倒 しかもターミナルウインドウを閉じてしまうとプロセスも閉じてしまうので困ってしまう なので Sinatra と同じプロセスで動かして尚且つブラウザからも操作できるようにしてみる

コードはこんな感じになった

  1. '/'でタイマのボタンT(/timer/standOn)を押す
  2. 2つめのパスに記したアクション(例えばstandOn)を引数に/timerが開く
  3. /timer/standOnで時間を入力して時間とアクションをpostで送る
  4. app.rbがpostを受けて別スレッドでsleepさせておき本スレッドではすぐに/にリダイレクトする
  5. 別スレッドが時間になったら任意のアクションのアドレス(例えばlocalhost:4567/standOn) にアクセスする

このように直接時刻(6:30)を指定する方法と数時間後(4時間30分後)を指定する方法を用意した Gyazo

雑感

  1. タイマの時間指定をするフォームでinput type="tell"にするとiPhone等で数字入力するときにテンキーキーボードが出てくるのでカッコイイ
  2. 将来的にはタイマボタンT/timer/standOnに画面遷移するのではなくon/offボタンの長押しで画面遷移したい
  3. iosのブラウザでinput type="time"を表示するとinputの親要素ごと上下に数ピクセルずれてしまったのでなんとかしたい
  4. MaciPhone でアクセスできるとお布団から出なくても部屋の明かりをon,offできて寝る時に便利
  5. 照明のタイマー機能でやすやす起きれると思っていたら、布団に頭まで潜っているので意味がなかった(特に冬は)

コードはGithubとgistにある

  1. Sinatra のコード Coro365/home-control
  2. Arduino のコード It receives the serial signals to control the switches.

次回予告

次回は今回のコードを Raspberry Pi に移します
Raspberry Pi で家電を操作する2 (Raspberry PiにWebサーバを設置して照明を操作する)[未投稿]です

参考ページ

  1. Sinatraについての質問です Sinatraのサーバにlocalhost:4567で… - 人力検索はてな
    • ありがとうございました
  2. sinatraでDNS逆引きを止める | TechRacho
    • DNS逆引きキャンセル
  3. Ruby - rerunでSinatraのファイル変更時にリロード - Qiita
    • rerunについて
  4. inline-blockを並べた場合に発生する「隙間」を消去するCSS » INSPIRE TECH
    • inline-blockの隙間

ありがとうございます