Raspberry Pi 作品集
温度・湿度・気圧を
液晶キャラクタデバイスへの表示 と CSVファイルへの保存
温度・湿度・気圧を
液晶キャラクタデバイスへの表示 と CSVファイルへの保存
Raspberry Pi のLCDを見れば、温度・湿度・気圧が判る様にする。
液晶 16文字x2行 へ 月日・時刻・温度・湿度・気圧 を表示。
スポンサー リンク
目 次
1. Raspberry Pi モデル B+
使用中の「Raspberry Pi」は、初期のモデル「B+」でリビジョンは「0010」。
ハードウェアのモデルを確認する方法。
cat /proc/cpuinfo
Pythonによる 基盤のリビジョン番号を確認するコマンド。
sudo python
>>> import RPi.GPIO as GPIO
>>> GPIO.RPI_REVISION
・・・ Ctrl + D で終了
>>> import RPi.GPIO as GPIO
>>> GPIO.RPI_REVISION
・・・ Ctrl + D で終了
※:次のコマンドが使えない。
cat /proc/device-tree/model
→ cat: /proc/device-tree/model: No such file or directory
→ cat: /proc/device-tree/model: No such file or directory
初期のモデル「B+」を最新の「Raspberry Pi OS(32-bit)」で稼働させてみる → 立ち上がりに相当な時間を要するが、稼働OK!
このコマンドでは、「Rev 1.2」と表示される。
「cat /proc/device-tree/model」コマンドが使える。
Raspberry Pi Model B Plus Rev 1.2
このコマンドでは、「Rev 1.2」と表示される。
OSのバージョンを確認するコマンド。
cat /etc/os-release
カーネルのバージョンを確認するコマンド。
uname -a
Pythonのバージョンを確認するコマンド。
python --version
2. Raspberry Pi で I2Cデバイスを利用するための準備
1. raspi-config で I2C を有効化する。
sudo raspi-config
2. I2Cのカーネルモジュールを有効化する。
/etc/modules の編集。
/etc/modules の編集。
sudo nano /etc/modules
3. 読み込み拒否設定の変更。
sudo nano /etc/modprobe.d/raspi-blacklist.conf
4. I2Cの操作に利用するライブラリーやコマンドのインストール。
sudo apt-get install i2c-tools
5. 「ACM 1602NI」液晶キャラクタデバイス用に動作クロックを50Khzに設定。
sudo nano /etc/modprobe.d/i2c.conf
6. smbus(I2C制御用ライブラリーのpython版)のインストール。
sudo apt-get install python-smbus
7. 再起動。
sudo reboot
8. シリアル通信 baudrate 設定の確認。
dmesg | grep i2c
3. 使用した部品
①.湿度センサー:
HIH6130:スイッチサイエンス 3,743 円
②.気圧センサー:
MPL115A2:秋月電子通商 600 円
③.照度測定用CdSセル(光センサー):
GL5528 1MΩ:秋月電子通商 40 円
④.ADコンバーター:
ADS1015:スイッチサイエンス 1,393 円
ADS1015:スイッチサイエンス 1,393 円
⑤.液晶キャラクタデバイス:
ACM1602NI-FLW-FBW:秋月電子通商 800円。
ACM1602NI-FLW-FBW:秋月電子通商 800円。
・動作電圧:2.3~5.5V
・補正された湿度の範囲:10~90% RH
・補正された温度の範囲:5℃~50℃ ← 5℃以下が不可
・I2C通信による出力 → 4バイト出力
・補正された湿度の範囲:10~90% RH
・補正された温度の範囲:5℃~50℃ ← 5℃以下が不可
・I2C通信による出力 → 4バイト出力
④.ADS1015: 12 ビット、3.3kSPS、4 チャネル・デルタ・シグマ ADC。
CdSセル(光センサー)のアナログ情報を入力して、デジタル情報に変換するために購入。
ADS1015は、12 ビット(4096)のデータに変換するので約4000段階の値が取得できる。
CdSセル(光センサー)のアナログ情報を入力して、デジタル情報に変換するために購入。
ADS1015は、12 ビット(4096)のデータに変換するので約4000段階の値が取得できる。
PGA (プログラマブル・ゲイン・アンプ) と発振器と VREF とコンパレータと I2C 搭載。https://www.ti.com/product/ja-jp/ADS1015
⑤.液晶キャラクタデバイス:ACM1602NI-FLW-FBW。
※:この I2C デバイスは「 i2cdetect 」でアドレスが取得できない ‼。
Slaver address could only set to 1010000, no other slaver address could be set.
Slaver address could only set to 1010000, no other slaver address could be set.
液晶に表示される文字のコントラストは、3番端子にかける電圧で調整できる。この為に抵抗で電圧を変化させるが、どの程度の電圧にすれば適切なコントラストになるか分からないので、「可変抵抗」を利用する。但し、一度調整したら変えることは無いので「10kΩの半固定抵抗」を使用した。
4. 液晶キャラクタデバイスへの表示内容と表示位置
これらのセンサーから値を取得する回路と、取得した値をHDMI端子に接続しているディスプレイに表示するプログラムを作った。
しかしこれだと、ディスプレイがなければ役に立たないので、液晶キャラクタデバイスに表示し、 Raspberry Pi 単独で 『百葉箱』 になるようにした。
液晶キャラクタデバイスへの表示内容。
表示位置の指定。
Raspberry Pi のコマンドやプログラムで、16進数を表記する場合は数字の前に「0x」を付ける。
表示位置をヘキサデシマルのアドレスで指定するというのが、EBCDIC(エビシディック)の汎用機で育った世代には何とも懐かしい。
表示位置をヘキサデシマルのアドレスで指定するというのが、EBCDIC(エビシディック)の汎用機で育った世代には何とも懐かしい。
5. 気象情報取得回路図
Raspberry Pi に用意されているGPIOに電子回路を接続すると、電子デバイスの制御ができる。
又、PythonにはI2Cデバイス制御用のライブラリが提供されているので、簡単にデバイスを操作することが出来る。
又、PythonにはI2Cデバイス制御用のライブラリが提供されているので、簡単にデバイスを操作することが出来る。
I2C(Inter-Integrated Circuit)とは
フィリップス社(現NXP社)が提唱する通信インターフェースで, クロックに同期させてデータの通信を行う同期式シリアル通信のひとつです。I2Cでは,クロック(SCL),データ入出力(SDA)の2本の信号線を用いて通信します。
I2C デバイスには、出荷時に「 0x03 - 0x77 」の範囲でアドレスが割り当てられており、I2Cマスターはこのアドレスで、複数のスレーブの中から適切な対象を識別する。
I2Cデバイスを Raspberry Pi に接続するには、GPIOと同じ端子を利用する。
データの送受信を行う「SDA」は端子番号3番、クロックの「SCL」は端子番号5番となっている。このI2Cのチャンネル番号(I2Cバス番号)は「1」。
データの送受信を行う「SDA」は端子番号3番、クロックの「SCL」は端子番号5番となっている。このI2Cのチャンネル番号(I2Cバス番号)は「1」。
I2Cで接続されているデバイスを確認するコマンド。
sudo i2cdetect -y 1
← バス番号は(0 か 1)で、エラーが出ない方を使う
← バス番号は(0 か 1)で、エラーが出ない方を使う
6. LCD表示 Python プログラム
照度は取得するも、LCDのスペースが無く表示せず。
Python PGM List。
#! /usr/bin/env /usr/bin/python
# -*- coding: utf-8 -*-
import datetime
import time
from Adafruit_ADS1x15 import ADS1x15 # ADS1015関連の関数等の読み込み
import smbus # I2C 通信には smbus ライブラリを使う
import mpl1152a2 # 圧力取得関数のインポート
from acm1602 import acm1602 # acm1602関連の関数等の読み込み
# アナログ変換セットアップ
ADS1015 = 0x00 # ADS1015を指定する値を定義
gain = 4096 # 3.3Vを4096に分割
sps = 250 # サンプリング数の設定
adc = ADS1x15( ic=ADS1015 ) # ADS1015から値を取得
# LCDセットアップ
# LCDの初期設定
lcd = acm1602( 1, 0x50, 4 ) # チャンネル番号、スレーブアドレス、GPIO番号
lcd.move_home() # カーソル位置を左上に移動
lcd.set_cursol( 0 ) # カーソルを非表示にする
lcd.set_blink( 0 ) # カーソルの点滅を止める
# ループ
SLEEPTIME = 300 # 60秒 x 5分
while True: # 条件式「True」は永続的に繰り返しを続ける
# 日時取得
d1 = datetime.datetime.today()
d2 = datetime.datetime.strftime(d1,"%Y-%m-%d/%H:%M:%S")
# 照度取得
# チャンネル、ゲイン、サンプリング数を指定してアナログ入力の値を取得し
# 1000で割っておおよその電圧に変換
volts = adc.readADCSingleEnded( 0, gain, sps ) / 1000
# 湿度・気温・気圧取得
i2c_channel = 1 # I2Cのチャンネル(バス番号)を指定する
i2c = smbus.SMBus( i2c_channel ) # コネクションオブジェクトを取得
# スレーブアドレス「0x27」HIH-6130から4バイト分のデータを取得
dac = i2c.read_i2c_block_data( 0x27, 0, 4 )
# 1バイト目はdac[0]、2バイト目は dac[1] 、3バイト目はdac[2] 、4バイト目はdac[3]
h = ( ( dac[0] & 0x3f ) << 8 ) | dac[1] # 湿度データのクレンジング
humi = (float)(h) / 16383 * 100 # 湿度の計算
t = ( dac[2] << 6 ) | (dac[3] >> 2) # 温度データのクレンジング
temp = (float)(t) /16383 * 165 - 40 # 温度の計算
# 圧力取得関数 mpl1152a2 を使って気圧を取得
pres = mpl1152a2.getpressur( i2c_channel )
d1 = datetime.datetime.today()
d2 = datetime.datetime.strftime(d1,"%m%d")
print d1
print("Illuminance : " + str(volts) + " V" )
print "Temperature : %.2f C" % temp
print "Humidity : %.2f %%" % humi
print "Pressure : %.2f hPa" % pres
lcd.backlight(1) # LCDのバックライトを点灯する
# LCDの表示位置を指定しデータを書き込む
# 年月日
lcd.move( 0x00, 0x00 )
lcd.write( d2 )
# 時分
lcd.move( 0x05, 0x00 )
lcd.write( time.strftime("%H%M") )
# 温度
lcd.move( 0x0a, 0x00 )
lcd.write( "%.2fC" % temp )
# 湿度
lcd.move( 0x00, 0x01 )
lcd.write( "%.2f%%" % humi)
# 気圧
lcd.move( 0x07, 0x01 )
lcd.write("%.2fhP" % pres )
time.sleep( SLEEPTIME ) # SLEEPTIME の値まで待機する
HIH-6130 デジタル湿度センサの出力内容(4バイト)とクレンジング
湿度データの1バイト目の前2ビットを取り除く
①.dac[0] & 0x3f:湿度データの1バイト目の前2ビット(Status分)が不要なので「00111111=3f」でANDして「00」にする。
②. ( dac[0] & 0x3f ) << 8 :1バイト目を8桁分左にシフトする(動かして空いた桁には「0」が入る)。
③.( ( dac[0] & 0x3f ) << 8 ) | dac[1] :シフトした1バイト目と2バイト目をORでつなぐ。
→ 取り出したデータは前2ビットが「00」なので「14ビットが値」。
②. ( dac[0] & 0x3f ) << 8 :1バイト目を8桁分左にシフトする(動かして空いた桁には「0」が入る)。
③.( ( dac[0] & 0x3f ) << 8 ) | dac[1] :シフトした1バイト目と2バイト目をORでつなぐ。
→ 取り出したデータは前2ビットが「00」なので「14ビットが値」。
温度データの4バイト目の後ろ2ビットを取り除く
④.(dac[3] >> 2:温度データの4バイト目を右に2桁分シフトする(動かして空いた桁には「0」が入る)。
②.dac[2] << 6 ) :3バイト目を左に6桁分シフトする(動かして空いた桁には「0」が入る)。
③.( dac[2] << 6 ) | (dac[3] >> 2):変換した3バイト目と4バイト目をORでつなぐ。
→ 取り出したデータは8ビットに6ビットが結合されたので「14ビットが値」。
②.dac[2] << 6 ) :3バイト目を左に6桁分シフトする(動かして空いた桁には「0」が入る)。
③.( dac[2] << 6 ) | (dac[3] >> 2):変換した3バイト目と4バイト目をORでつなぐ。
→ 取り出したデータは8ビットに6ビットが結合されたので「14ビットが値」。
7. PythonからCSVファイルへの書き込み
液晶デバイスを見ていると、気象情報を時系列で保存し、変化をグラフで見たくなる。 そこで、取得したデータを「CSV」で保存し、このファイルをパソコンに取り込んで、 エクセルでグラフ表示にして見る。
手順。
①.PythonでCSVファイルを新規に作成する。
②.作成した csvファイル に時系列データを追記する。
③.パソコンにダウンロードしてエクセルでグラフにする。
②.作成した csvファイル に時系列データを追記する。
③.パソコンにダウンロードしてエクセルでグラフにする。
①.気象データを保存する csvファイル を作る
csvファイル を保存するディレクトリーを作る。
mkdir /home/pi/data
csvファイル を作るpythonプログラム。
sudo nano /home/pi/Python_PGM/makecsv_01.py
import csv
with open('data/weather-data_01.csv', 'w') as f:
writer = csv.writer(f)
writer.writerow(['日付','時刻','気温','湿度','気圧'])
writer.writerow(['2023-02-15','09:07:38',18.54,53.46,1068.60])
open()の第一引数には、新たなファイルへのパスを指定する。
csvファイルの名前を「weather-data_01.csv」とした。
第二引数は「mode」で、書き込みモードを'w'とすると上書きとなり、元の内容は削除される。
csvファイルの名前を「weather-data_01.csv」とした。
第二引数は「mode」で、書き込みモードを'w'とすると上書きとなり、元の内容は削除される。
writerow()メソッドで1行ずつ書き込む。引数はリスト。
②.作成した csvファイル に気象データを追記する
csvファイル に「30分」毎の時系列データを追記するpythonプログラム。
#! /usr/bin/env /usr/bin/python
# -*- coding: utf-8 -*-
import datetime
import time
import smbus
import mpl1152a2
from acm1602 import acm1602
import csv
# ループ
interval = 1800 # 60秒 x 30分
while True: # 条件式「True」は永続的に繰り返しを続ける
i2c_channel = 1
i2c = smbus.SMBus( i2c_channel )
dac = i2c.read_i2c_block_data( 0x27, 0, 4 )
h = ( ( dac[0] & 0x3f ) << 8 ) | dac[1]
humi = (float)(h) / 16383 * 100
t = ( dac[2] << 6 ) | (dac[3] >> 2)
temp = (float)(t) /16383 * 165 - 40
pres = mpl1152a2.getpressur( i2c_channel )
d1 = datetime.datetime.today()
date = d1.strftime('%Y-%m-%d') #日付の整形 yyyy-mm-dd
jkok = d1.strftime('%H:%M') #時間の整形 hh:mm
temp = "{:.2f}" . format(temp) #気温(小数点第2位まで)
humi = "{:.2f}" . format(humi) #湿度(小数点第2位まで)
pres = "{:.2f}" . format(pres) #湿度(小数点第2位まで)
print date
print jkok
print temp
print humi
print pres
# CSV書き出し
with open('/home/pi/data/weather-data_01.csv','a') as f:
writer = csv.writer(f)
writer.writerow([date,jkok,temp,humi,pres])
time.sleep(interval) # intervalの値まで待機する
既存のCSVファイルに追記したい場合は、 open()の追記モード‘a’ でファイルを開く。
書き込み自体は新規作成の場合と同じくwriterow()やwriterows()。
末尾に追記される。
書き込み自体は新規作成の場合と同じくwriterow()やwriterows()。
末尾に追記される。
※:sleepという関数「time.sleep(interval)」を使用しているため、 「time」と言う名前の変数は使用できない。
csvファイルの内容を見てみる。
sudo nano /home/pi/data/weather-data_01.csv
③.パソコンにダウンロードしてエクセルでグラフにする
csvファイルを「FileZilla」を使って、パソコンにダウンロードする。
参考:Raspberry Pi 気象情報をスマホにメールで送信する
参考:Raspberry Pi 監視カメラを構築し遠隔監視が出来るようにする
以上。
(2015.01.02)
スポンサー リンク