にせねこメモ

はてなダイアリーがUTF-8じゃないので移ってきました。

Raspberry Pi Zero Wで温度ロガーをつくる

Raspberry Pi Zero Wと温度センサを利用して、屋外の温度を記録する温度ロガーをつくった。記録した温度データをブラウザから閲覧する仕組みもつくった。

モチベーション

外気温を記録出来たら楽しいので。

注意

素人が適当に勘と見よう見まねでつくっているだけなので、不適切な部分があるかもしれません。参考にする場合は専門家に相談するようにしてください。責任取れませんので…。

システム構成

  • Raspberry Pi Zero Wを使う。
    • 家の外に設置して記録したデータを取り出すのに、家のWifiに繋がれば楽なので。というかSSHで繋げられるので管理が楽。
  • 16GBのmicro SDカード
  • 温度センサは防水プローブに入ったDS18B20を利用
  • あとプルアップ用に4.7 kΩの抵抗器が1つ必要。プルアップ用なので別にその辺りの抵抗値なら何でも良さそう。

環境

母艦パソコンのOSはWindows 10で、Cygwinsshを使っている。

Raspberry Pi Zero Wのセットアップ

Raspberry Pi OSのインストール

  • SDカードをパソコンに挿す
  • https://www.raspberrypi.org/software/ からDownload for WindowsをクリックしてRaspberry Pi Imagerをダウンロードして実行する。
    1. CHOOSE OS→Raspberry Pi OS (32-bit)
    2. CHOOSE STORAGE→SDカードを選択
    3. WRITEをクリック
    • 書き込みが終ったらCONTINUEを押して、ウィンドウを閉じる
  • 入れてみたらバージョンは Raspbian GNU/Linux 10 (buster) だった。

ssh, Wifiのセットアップ

  • パソコンにSDを挿しなおす
  • イメージを書き込んだSDカード(boot)を開く→sshという名前の空ファイルを作成(拡張子なし!)
  • SDカード(boot)の直下にwpa_supplicant.confというファイルを次の内容で作成する
ctrl_interface=/var/run/wpa_supplicant
network={
    ssid="xxxxxxxxxxxxxxxxxxxx"
    psk=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    key_mgmt=WPA-PSK
}

ssidは繋ぎたい無線LANSSIDを入力する(クォートで囲む)。
pskには次のサイトにSSIDパスフレーズを入力して計算した16進ハッシュ値を書く(クォートで囲まない)。

(改行コードはLFにしたけどCRLFでも動くんだろうか?)

電源につないで起動する。

Raspberry Piへの接続

起動すると自動的にWifiに接続される。IPアドレスRaspberry Pi Zero Wにディスプレイを繋げていればそこに表示されるが、わからなければAdvanced IP Scannerなどを利用して調べる。ローカルIPは限られてるので総当たりでも何とかなるはず。

以下、Raspberry Piのアドレスを192.168.11.10とする。
パソコンからRaspberry PiSSHで繋げる。

ssh pi@192.168.11.10
  • Are you sure you want to continue connecting (yes/no/[fingerprint])と聞かれたら yesと入力してEnter
  • 初期パスワードraspberryを入力してログイン

初期設定

パスワード変更
passwd

現行のパスワード(raspberry)1回、変更後の好きなパスワード2回を入力してパスワードを変更する。


adminのパスワードを変更するのは、

sudo passwd admin

とする。

ソフトウェアを最新に更新
sudo apt update
sudo apt upgrade -y
タイムゾーンを東京にする
sudo raspi-config

で設定を開き、

  • 5 Localisation OptionsTimezoneAsiaTokyoFinish

参考: Raspberry Piの設定【raspi-config/言語・タイムゾーン・キーボードの設定】 - Aldebaranな人のブログ

IPアドレスの固定
sudo nano /etc/dhcpcd.conf

次のような内容を書き加えるか、コメントアウトを外して変更する。アドレスは環境に合わせる。ここではルーターのアドレスを192.168.11.1としている。

interface wlan0
static ip_address=192.168.11.10/24    
static routers=192.168.11.1
static domain_name_servers=192.168.11.1 8.8.8.8

参考: TCP/IP networking - Raspberry Pi Documentation

SSHを公開鍵認証だけにする

cd ~
mkdir .ssh
nano .ssh/authorized_keys

(ここで接続元のコンピュータの公開鍵を書き込む)

chmod 600 .ssh/authorized_keys
chmod 700 .ssh
SSHD設定
sudo nano /etc/ssh/sshd_config

コメントアウトしたりして次のような設定に変更する。書いてない部分はそのまま。

Port 22 #外部公開しないのでデフォルトで良し

LoginGraceTime 30
PermitRootLogin no
StrictModes yes
MaxAuthTries 3
MaxSessions 5

PubkeyAuthentication yes

IgnoreRhosts yes

PasswordAuthentication no
PermitEmptyPasswords no

参考: sshd_configの設定項目の理解を目指す | Unskilled?

センサーのはんだ付け

接続

f:id:nixeneko:20210501175928p:plain
f:id:nixeneko:20210501175942p:plain
(画像はFritzingで作成)

写真

f:id:nixeneko:20210501171446p:plain
f:id:nixeneko:20210501171307p:plain
面倒なので直にはんだ付けした。構成を変更したくなったら面倒だけど…。

参考: 5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (16) ディジタル温度センサ1 1-Wire DS18B20 | 電子工作の環境向上

1-Wire有効化

sudo nano /boot/config.txt

/boot/config.txtを開き、

dtoverlay=w1-gpio

を追記、保存、再起動。

sudo reboot now

参考: 1-WIRE at Raspberry Pi GPIO Pinout

温度自動記録の設定

自動記録のコードを用意した。温度を読み取ってファイルに時刻と温度を書き込むだけのコード。
github.com

これを動かす。

cd ~
git clone https://github.com/nixeneko/record_temperature
git checkout v1.0
cp settings.py.template settings.py
ls /sys/bus/w1/devices/
nano settings.py 

/sys/bus/w1/devices/の中に温度センサのデバイスがあるので、使いたい温度センサ(たぶん28-で始まってるやつ)をメモして、settings.pyをそれに合わせて変更する。

自動実行の設定

cron.dに書く

sudo nano /etc/cron.d/record_temperature

で設定ファイルを開いて、

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

*/1 * * * * pi /home/pi/record_temperature/rec_temp.py

と書き込み、保存する。これは1分毎に記録する場合。*/1*/5にすれば5分ごとの記録になる。(*/1*と同じ。)

防水プラボックスの加工

f:id:nixeneko:20210501183207p:plain
屋外に設置するので防水プラボックス(今回使ったのはタカチ BCAP112107T)に入れる。大は小を兼ねるということで大きめにした、入らなかったら嫌なので。固定用の金具も購入。蓋が透明な奴にしたけど別に蓋が透明である必要なかったなと思った。

配線を通すために穴を開ける。

穴あけ

f:id:nixeneko:20210501183527p:plain
ドリルで穴を開け、穴をつなげてやする。

f:id:nixeneko:20210501183655p:plain

プラボックスにいれる

f:id:nixeneko:20210501184745p:plain
延長コード通す穴がでかすぎるので木材を切ってストッパーにする。動くと困るので接着剤で接着した。
f:id:nixeneko:20210501184118p:plain
f:id:nixeneko:20210501184201p:plain

シリコンシーラントで穴をふさぐ

f:id:nixeneko:20210501184830p:plain
これ本当にうまく行ってんのか謎。
ケーブルが上下に動くと普通にはがれるっぽいのでケーブルを固定してからやった方がいいっぽい。最終的に設置してからもう一回もりもりやった。

延長コードと遮断機付きのコードを繋ぎ、自己融着テープで絶縁・防雨対策

延長コードと遮断機付きのコードは適当に屋外でも使えそうなやつを通販で買った。室外機とかの屋外配線見る限りもっと簡易な作りのやつが使われてるような気がするんだけど…。

f:id:nixeneko:20210501185311p:plain

過電流遮断器なので短絡くらいしか検出できないけど、まあないよりマシかなあという感じ。漏電は配電盤の漏電遮断器が検出してくれると思う。

コード同士を接続し、自己融着テープで絶縁する。
f:id:nixeneko:20210501185422p:plain
自己融着テープは光に弱いらしく、ビニールテープでさらに巻いておくといいらしい。直射日光に当たらないのでそのままにしたが。

接地

2x4材を立てて、そこにタッピングネジでプラボックスを固定。
f:id:nixeneko:20210501190431p:plain
コードを屋外コンセントにつなぎ、電源を入れる。

インターネットからドメインでアクセスできるようにする

Dynamic DNS申込み

https://www.mydns.jp/ を使った。別にドメインが取れればなんでもいいと思う。

サービスに合わせて設定する。

IP更新

cd ~
nano update_ip.sh

を次の内容で作成する。

#!/bin/sh
wget https://ipv4.mydns.jp/login.html --http-user=ID --http-passwd=PASSWORD -O /dev/null

IDPASSWORDは自分のアカウントに合わせて変更し、保存する。

chmod +xしてcrontabで一日一回実行するように設定

chmod +x update_ip.sh
./update_ip.sh

IPの更新が動いているのを確かめる。

自動更新の設定

sudo nano /etc/cron.d/update_dynamic_dns

次の内容にして保存する。

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

12 5 * * * pi /home/pi/update_ip.sh

(環境変数の設定、とりあえず書いといたけど必要ないかも?)

これでドメインからIPが引けるようになるが、まだルータで止まってアクセスはできない。

参考: DDNSにBasic認証でIPアドレスを通知する - Qiita

ローカルからドメインでアクセスできるようにする

Raspberry PiDNSサーバーにする

Dnsmasqのインストール

sudo apt -y install dnsmasq 
sudo nano /etc/dnsmasq.conf

設定は、Raspberry PiのIPが192.168.11.10、ルータのIPが192.168.11.1ドメインexample.comの場合を書く。次の項目のコメントアウトを外し、serverはルータ(というかDNSサーバ)のIPに書き換える。

domain-needed
bogus-priv
no-resolv
address=/example.com/192.168.11.10
server=192.168.11.1

有効化する。

sudo systemctl restart dnsmasq
sudo systemctl enable dnsmasq

参考: ラズパイ(Raspberry Pi)とDnsmasqで作るDNSサーバ | Device Plus - デバプラ

ルータのDNSルーティング設定を行う

ルータの設定画面を開き、
詳細設定→DNSルーティング設定(ルータによって異なる)から

を追加。

これでローカルからもドメインでアクセスできるようになった。

気温のグラフを表示するWebサイト+CGIの設置

サイトのデータ置く用のユーザwwwを追加(この辺知識がないので何がベストプラクティスなのか分からない…)

sudo adduser --shell /bin/false www

適当に入力してユーザを作成。


サイトのデータを用意を次に用意したのでこれを使う。特定の日のデータをJSONで取得するCGIと、JSONで取得した温度データをChart.jsを使ってグラフにするHTMLファイルからなる。
github.com

用意。

sudo -Hu www /bin/bash
cd ~
git clone https://github.com/nixeneko/temperature_website
cd temperature_website/public/
cp settings.js.template settings.js
cp api/settings/settings.py.template api/settings/settings.py

Ctrl+D押してログアウト

HTTPサーバの設定

Apach2のインストールと設定

sudo apt -y install apache2
sudo nano /etc/apache2/sites-available/example.com.conf

設定を環境に合わせて次のようにする。

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    ServerName example.com
    DocumentRoot /home/www/temperature_website/public
    <Directory /home/www/temperature_website/public>
        Require all granted
    </Directory>
    <Directory /home/www/temperature_website/public/api>
        Options +ExecCGI
        SetHandler cgi-script
    </Directory>
    <Directory /home/www/temperature_website/public/api/settings>
        Require all denied
    </Directory>
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

サイトやモジュールの有効化

sudo a2enmod cgid
sudo a2ensite example.com.conf
sudo a2dissite 000-default.conf
sudo apache2ctl configtest
sudo systemctl restart apache2
sudo gpasswd -a www-data www

参考: Ubuntu 20.04にApache Webサーバーをインストールする方法 | DigitalOcean

ファイアフォールの設定(ufw)

sudo apt install ufw
sudo ufw default deny
sudo ufw allow 53
sudo ufw allow 80/tcp
sudo ufw limit 22/tcp
sudo ufw enable
sudo ufw status
sudo systemctl restart ufw

参考: ufwコマンドの使い方 - Qiita

ルータのポートフォワーディングの設定

80番ポートをRaspberry PiIPアドレスに!
→全世界に公開!


ドメインにアクセスすると次のような画面が表示される。
f:id:nixeneko:20210501222613p:plain

百葉箱の設置

センサー部分は百葉箱の中に突っ込む。どうせ家の蔭で日には当たらないので別にいらない気もするが。
もともとは防水プラボックスごと百葉箱のなかに突っ込むつもりだったが思ったよりでかかったので外に出すことにした。なのでもっと小さいやつで良かったかもしれない…

まともな百葉箱は高いのでレーザーカッターによるそれっぽいキットを使った。

この中型ウェザーシールド。

梱包はこんな感じで、側面の鎧戸(戸ではないが)だけ組み立てられた状態で来た。
f:id:nixeneko:20210501204048p:plain

仮組みしようとしたら手前の板の片方の穴が3mm下にずれていて嵌まらなかった。
f:id:nixeneko:20210501204154p:plain
…ので、ナイフで削って嵌まるようにした。

仮組。
f:id:nixeneko:20210501204608p:plain
手前の取り外せるようになっている窓が、扉みたいになっていないので、取り外しはやや面倒かもしれない。あまり頻繁に開け閉めしたい場合には向かないと思う。


2x4材に固定できるように背面板に穴を開け、接着し塗装した(塗装と接着を交互にやって上手い具合にやろうとした)。塗装は白の水性塗料を刷毛で2重~3重に塗り重ねた(塗料がなくなったのでやめた)。
f:id:nixeneko:20210501205340p:plain

防水プラボックスの上方、2x4材にネジとナットで固定し、底に開けた穴からセンサーを中に入れ、センサーを針金で固定した。
f:id:nixeneko:20210501210137p:plain

ついでにケーブルをナイロンクランプで固定している。
蓋をして完成。
f:id:nixeneko:20210501211020p:plain

材料費

合計17,600円程度。

他に送料、工具類、固定用のネジ類、2x4材等などは書いてないが5千円はかかってるかもしれない。
百葉箱除けば1万円しないと考えると、いい感じかもしれない。

感想

要素要素の技術は大したことない(というか、誰かがしっかり舗装してくれているのでそれを辿るだけでいい)が、組み合わさるとなんかすごいことやってる気がしてくる。

温度センサの誤差が±0.5℃なので結構大きめ。もっと高精度のやつが使えればいいんだけど、防水プローブに入ったやつが見つからなかったのでどうすればいいのかよくわからない。直接雨が当たらなければ別に良さそうな気もするが。

ラズパイはLinuxなので楽だが、Wifiと電源がないところでは使えないので、設置場所が限られる。バッテリーで数ヶ月動くデータロガーが作れればいいんだけど。