Raspberry Pi 3に温湿度センサ「SHT21」と「SHT11」を接続し、温湿度データを入力して表示します。プログラム言語はPython3でライブラリ「pigpio」を使用します。Raspberry Pi 3の設定については「pigpioによるI2CとSPIインタフェースの実装」を参考にしてください。
温湿度センサ「SHT21」の接続
温湿度センサ「SHT21」は、I2CでRaspberry Pi 3と接続します。仕様を次に示します。
- 動作電圧:2.1V~3.6V
- 測定範囲:-40~+125℃,0~100%RH
- 精度:温度±0.3℃ 湿度±2%RH
- 変換時間:温度 85ms 湿度 30ms
温湿度センサ「SHT21」は、ebayから購入しました。
次のebayから購入したSOT23のDIP変換基板にSHT21をはんだ付けし、ブレッドボードで使用できるようにしました(裏面のGNDの部分にはんだ付けされないように、DIP変換基板のパターンをカットしています)。
Raspberry Pi 3と温湿度センサ「SHT21」間で、I2CのSDAとSCLのそれぞれに接続します。温湿度センサ「SHT21」のVCCにはRaspberry Piの3.3Vを入力します。接続した画像を次に示します。
温湿度センサ「SHT21」のピン配置を次に示します。
次のコマンドでRaspberry Pi 3との接続を確認します。
$ 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: -- -- -- -- -- -- -- --
- 温湿度センサ「SHT21」のアドレス - 0x40
温湿度センサ「SHT21」のPythonスクリプト
Python3でライブラリ「pigpio」を使用して、温湿度センサ「SHT21」のPythonスクリプト「mSHT21.py」を作成します。SHT21のデータシートを示します。
- 温湿度センサ「SHT21」から温度データを取得するには「Trigger T measurement(no hold master)」コマンド「0xF3」、湿度データを取得するには「Trigger RH measurement(no hold master)」コマンド「0xF5」を使用します。温湿度センサ「SHT21」のコマンド一覧を次に示します。
- 温湿度センサ「SHT21」からのセンサーデータにより、次の計算式に従って、温度/湿度を計算します。
- 温湿度センサ「SHT21」は、通信データの信頼性を確保するため8ビットのCRCが付与されています。
SHT21のCRC-8演算多項式: x8 + x5 + x4 +1
# -*- coding: utf-8 -*-
import pigpio
import time
import devtemperature
def _calculate_checksum(data, number_of_bytes):
"""5.7 CRC Checksum using the polynomial given in the datasheet"""
# CRC
POLYNOMIAL = 0x131 # //P(x)=x^8+x^5+x^4+1 = 100110001
crc = 0
# calculates 8-Bit checksum with given polynomial
for byteCtr in range(number_of_bytes):
crc ^= ((data[byteCtr]))
for bit in range(8, 0, -1):
if crc & 0x80:
crc = (crc << 1) ^ POLYNOMIAL
else:
crc = (crc << 1)
return crc
def _get_temperature_from_buffer(data):
"""This function reads the first two bytes of data and
returns the temperature in C by using the following function:
T = -46.85 + (175.72 * (ST/2^16))
where ST is the value from the sensor
"""
unadjusted = ((data[0]) << 8) + (data[1])
unadjusted &= Sht21._STATUS_BITS_MASK # zero the status bits
unadjusted *= 175.72
unadjusted /= 1 << 16 # divide by 2^16
unadjusted -= 46.85
return unadjusted
def _get_humidity_from_buffer(data):
"""This function reads the first two bytes of data and returns
the relative humidity in percent by using the following function:
RH = -6 + (125 * (SRH / 2 ^16))
where SRH is the value read from the sensor
"""
unadjusted = ((data[0]) << 8) + (data[1])
unadjusted &= Sht21._STATUS_BITS_MASK # zero the status bits
unadjusted *= 125.0
unadjusted /= 1 << 16 # divide by 2^16
unadjusted -= 6
return unadjusted
class Sht21(object):
# control constants
_SOFTRESET = 0xFE
DEFAULT_ADDRESS = 0x40
_TRIGGER_TEMPERATURE_NO_HOLD = 0xF3
_TRIGGER_HUMIDITY_NO_HOLD = 0xF5
_STATUS_BITS_MASK = 0xFFFC
# datasheet (v4), page 9, table 7, thanks to Martin Milata
# for suggesting the use of these better values
# code copied from https://github.com/mmilata/growd
_TEMPERATURE_WAIT_TIME = 0.086 # (datasheet: typ=66, max=85)
_HUMIDITY_WAIT_TIME = 0.030 # (datasheet: typ=22, max=29)
"""コンストラクタ"""
def __init__(self, pi):
self.pi = pi
self._device = pi.i2c_open(1, self.DEFAULT_ADDRESS)
reg_data = [self._SOFTRESET]
self.pi.i2c_write_device(self._device,reg_data)
time.sleep(0.050)
def read_temp(self):
reg_data = [self._TRIGGER_TEMPERATURE_NO_HOLD]
self.pi.i2c_write_device(self._device,reg_data)
time.sleep(self._TEMPERATURE_WAIT_TIME)
wc, data = self.pi.i2c_read_device(self._device, 3)
if _calculate_checksum(data, 2) == (data[2]):
return _get_temperature_from_buffer(data)
def read_humidity(self):
"""Reads the humidity from the sensor. Not that this call blocks
for ~30ms to allow the sensor to return the data"""
reg_data = [self._TRIGGER_HUMIDITY_NO_HOLD]
self.pi.i2c_write_device(self._device,reg_data)
time.sleep(self._HUMIDITY_WAIT_TIME)
wc, data = self.pi.i2c_read_device(self._device, 3)
if _calculate_checksum(data, 2) == (data[2]):
return _get_humidity_from_buffer(data)
def cancel(self):
"""
Cancels the sensor and releases resources.
"""
if self._device is not None:
self.pi.i2c_close(self._device)
self._device = None
if __name__ == "__main__":
pi = pigpio.pi()
if not pi.connected:
exit(0)
logger = 0
temp = devtemperature.Sht21(pi)
while True:
temperature = temp.read_temp()
humidity = temp.read_humidity()
print("temperature:{:.2f}℃ humidity:{:.2f}% ".format(temperature,humidity))
time.sleep(2.0)
温湿度センサ「SHT21」のPythonスクリプトの実行
作成したPythonスクリプトを次のコマンドで実行します。2秒ごとに温湿度センサ「SHT21」からの温湿度データを表示します。
$ python3 mSHT21.py temperature:20.91℃ humidity:52.24% temperature:20.91℃ humidity:52.24% temperature:20.91℃ humidity:52.24% temperature:20.91℃ humidity:52.27% temperature:20.91℃ humidity:52.24% temperature:20.91℃ humidity:52.24% temperature:20.92℃ humidity:52.27% temperature:20.92℃ humidity:52.27% temperature:20.92℃ humidity:52.27% temperature:20.93℃ humidity:52.30% temperature:20.93℃ humidity:52.30% temperature:20.93℃ humidity:52.30% temperature:20.93℃ humidity:52.30% temperature:20.93℃ humidity:52.30% temperature:20.94℃ humidity:52.33% temperature:20.94℃ humidity:52.36% temperature:20.95℃ humidity:52.36%
温湿度センサ「SHT11」の接続
温湿度センサ「SHT11」は、二本の信号線「DATA」「SCK」でRaspberry Pi 3と接続します。仕様を次に示します。
- 完全1チップの温度・湿度センサー
- A/Dコンバータ内蔵で完全デジタルで温度・湿度を出力
- 2線式でマイコンと接続
- 3~5V単一電源
- 調整不要で湿度±3.5%RH,温度±0.5℃の精度
- 分解能 湿度:0.03%RH,温度:0.01℃(
温湿度センサ「SHT11」のPythonスクリプト
Python3でライブラリ「pigpio」を使用して、温湿度センサ「SHT11」のPythonスクリプト「mSHT11.py」を作成します。SHT11のデータシートを示します。
- 最初にアドレス「000」を送信し、次に5ビットのコマンド「温度測定」「相対温度測定」を送信します。温湿度センサ「SHT11」のコマンド一覧を次に示します。
- 温度の計算は、温度の入力値(SOT)を温度値に変換するには次の式を用います(係数の値を次の表に示します)
- 相対湿度は、湿度指示値(SORH)に以下の公式と次に示される係数を適用して値を変換します。
# -*- coding: utf-8 -*-
import pigpio
import logging.config
import time
DATAPINT1 = 0x4
DATAPINTCW = 0x5
class SHT11(object):
# Conversion coefficients from SHT15 datasheet
D1 = -40.0 # for 14 Bit @ 5V
D2 = 0.01 # for 14 Bit DEGC
C1 = -2.0468 # for 12 Bit
C2 = 0.0367 # for 12 Bit
C3 = -0.0000015955 # for 12 Bit
T1 = 0.01 # for 14 Bit @ 5V
T2 = 0.00008 # for 14 Bit @ 5V
"""コンストラクタ"""
def __init__(self, pidata, loggerdata, datapin):
self.pi = pidata
self.logger = loggerdata
self.dataPin = datapin
self.sckPin = SCKPIN
# pigpio.setmode(GPIO_BOARD)
self.__lastinvocationtime = 0
def read_temperature_and_humidity(self):
temperature = humidity = 0
try:
temperature = self.read_temperature_c()
self.__wait()
humidity = self._read_humidity(temperature)
except SystemError:
self.logger.error("温湿度取得エラー")
finally:
return temperature, humidity
def __wait(self):
last_invocation_delta = time.time() - self.__lastinvocationtime
# if we queried the sensor less then a second ago, wait until a second is passed
if last_invocation_delta < 1:
time.sleep(1 - last_invocation_delta)
self.__lastinvocationtime = time.time()
def read_temperature_c(self):
temperature_command = 0b00000011
self.__sendcommand(temperature_command)
self.__waitforresult()
raw_temperature = self.__getdata16bit()
# self.logger.debug("raw_temperature:{:x}".format(raw_temperature))
self.__skipcrc()
# pigpio.cleanup()
return raw_temperature * SHT71.D2 + SHT71.D1
def _read_humidity(self, temperature):
humidity_command = 0b00000101
self.__sendcommand(humidity_command)
self.__waitforresult()
raw_humidity = self.__getdata16bit()
self.__skipcrc()
# GPIO_BOARD.cleanup()
# Apply linear conversion to raw value
linear_humidity = SHT71.C1 + SHT71.C2 * raw_humidity + SHT71.C3 * raw_humidity * raw_humidity
# Correct humidity value for current temperature
return (temperature - 25.0) * (SHT71.T1 + SHT71.T2 * raw_humidity) + linear_humidity
def __sendcommand(self, command):
# Transmission start
self.pi.set_mode(self.dataPin, pigpio.OUTPUT)
self.pi.set_mode(self.sckPin, pigpio.OUTPUT)
self.pi.write(self.dataPin, pigpio.HIGH)
self.__clocktick(pigpio.HIGH)
self.pi.write(self.dataPin, pigpio.LOW)
self.__clocktick(pigpio.LOW)
self.__clocktick(pigpio.HIGH)
self.pi.write(self.dataPin, pigpio.HIGH)
self.__clocktick(pigpio.LOW)
for i in range(8):
if (command & (1 << 7 - i)) != 0:
commanddata = 1
else:
commanddata = 0
self.pi.write(self.dataPin, commanddata)
self.__clocktick(pigpio.HIGH)
self.__clocktick(pigpio.LOW)
self.__clocktick(pigpio.HIGH)
self.pi.set_mode(self.dataPin, pigpio.INPUT)
ack = self.pi.read(self.dataPin)
# self.logger.debug("ack1: %s", ack)
if ack != pigpio.LOW:
self.logger.error("nack1")
self.__clocktick(pigpio.LOW)
ack = self.pi.read(self.dataPin)
# self.logger.debug("ack2: %s", ack)
if ack != pigpio.HIGH:
self.logger.error("nack2")
def __clocktick(self, value):
self.pi.write(self.sckPin, value)
# 100 nanoseconds
time.sleep(.0000001)
def __getdata16bit(self):
self.pi.set_mode(self.dataPin, pigpio.INPUT)
self.pi.set_mode(self.sckPin, pigpio.OUTPUT)
# Get the most significant bits
value = self.__shiftin(8)
value *= 256
# Send the required ack
self.pi.set_mode(self.dataPin, pigpio.OUTPUT)
self.pi.write(self.dataPin, pigpio.HIGH)
self.pi.write(self.dataPin, pigpio.LOW)
self.__clocktick(pigpio.HIGH)
self.__clocktick(pigpio.LOW)
# Get the least significant bits
self.pi.set_mode(self.dataPin, pigpio.INPUT)
value |= self.__shiftin(8)
return value
def __shiftin(self, bitnum):
value = 0
for i in range(bitnum):
self.__clocktick(pigpio.HIGH)
value = value * 2 + self.pi.read(self.dataPin)
self.__clocktick(pigpio.LOW)
return value
def __skipcrc(self):
# Skip acknowledge to end trans (no CRC)
self.pi.set_mode(self.dataPin, pigpio.OUTPUT)
self.pi.set_mode(self.sckPin, pigpio.OUTPUT)
self.pi.write(self.dataPin, pigpio.HIGH)
self.__clocktick(pigpio.HIGH)
self.__clocktick(pigpio.LOW)
def __waitforresult(self):
self.pi.set_mode(self.dataPin, pigpio.INPUT)
ack = pigpio.LOW
for i in range(100):
# 10 milliseconds
time.sleep(.01)
ack = self.pi.read(self.dataPin)
if ack == pigpio.LOW:
break
if ack == pigpio.HIGH:
raise SystemError
def cancel(self):
self.pi = 0
if __name__ == "__main__":
logging.config.fileConfig('logging.conf')
logger = logging.getLogger()
pi = pigpio.pi()
if not pi.connected:
exit(0)
temp = SHT11(pi, logger, DATAPINT4)
while True:
wtemperature, whumidity = temp.read_temperature_and_humidity()
print("temperature:{:.2f}℃ humidity:{:.2f}% ".format(wtemperature, whumidity))
time.sleep(2.0)








