ラズパイで最新の温湿度をファイル出力する

# はじめに
ラズパイで環境情報を取得するために、DHT11温湿度センサを使っています。
取得した最新の温湿度の情報を「2021/07/22 23:00:01 20 82」というような形でファイルに保存しているのでその方法をまとめておきます。

# センサーのつなげ方
DHT11センサにはピンが4本あるものと3本のものがありそうです。
私が持っているのは3本のもので、左からVCC,GRD,DATAとなっていました。

VCCは4番ポート(5V)、GRDは6番ポート(GRD)、DATAは8番ポート(GPIO14)に接続しました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1359985/db1a3e45-4fd4-9354-5fbc-60ac97f006bd.jpeg" width="300">

# 温湿度情報の処理
温湿度をファイルに出力する処理は以下です。OSOYOOのサンプルコードをベースにしているので細かいところはわかりませんが、処理を実行すると「/var/local/NowTemp.txt」に最新の日時と温湿度を出力します。

```python
import RPi.GPIO as GPIO
import time
import os
import datetime

#GPIOの番号
DHTPIN = 14

GPIO.setmode(GPIO.BCM)

MAX_UNCHANGE_COUNT = 100

STATE_INIT_PULL_DOWN = 1
STATE_INIT_PULL_UP = 2
STATE_DATA_FIRST_PULL_DOWN = 3
STATE_DATA_PULL_UP = 4
STATE_DATA_PULL_DOWN = 5

def read_dht11_dat():
    GPIO.setup(DHTPIN, GPIO.OUT)
    GPIO.output(DHTPIN, GPIO.HIGH)
    time.sleep(0.05)
    GPIO.output(DHTPIN, GPIO.LOW)
    time.sleep(0.02)
    GPIO.setup(DHTPIN, GPIO.IN, GPIO.PUD_UP)

    unchanged_count = 0
    last = -1
    data = []

    #センサーからデータを取得
    while True:
        current = GPIO.input(DHTPIN)
        data.append(current)
        if last != current:
            unchanged_count = 0
            last = current
        else:
            unchanged_count += 1
            if unchanged_count > MAX_UNCHANGE_COUNT:
                break

    state = STATE_INIT_PULL_DOWN
    lengths = []
    current_length = 0

    #温度と湿度が混ざった40個のリストを作成
    for current in data:
        current_length += 1

        if state == STATE_INIT_PULL_DOWN:
            if current == GPIO.LOW:
                state = STATE_INIT_PULL_UP
            else:
                continue
        if state == STATE_INIT_PULL_UP:
            if current == GPIO.HIGH:
                state = STATE_DATA_FIRST_PULL_DOWN
            else:
                continue
        if state == STATE_DATA_FIRST_PULL_DOWN:
            if current == GPIO.LOW:
                state = STATE_DATA_PULL_UP
            else:
                continue
        if state == STATE_DATA_PULL_UP:
            if current == GPIO.HIGH:
                current_length = 0
                state = STATE_DATA_PULL_DOWN
            else:
                continue
        if state == STATE_DATA_PULL_DOWN:
            if current == GPIO.LOW:
                lengths.append(current_length)
                state = STATE_DATA_PULL_UP
            else:
                continue
    
    if len(lengths) != 40:
        return False

    halfway = (max(lengths) + min(lengths)) / 2
    bits = []
    the_bytes = []
    byte = 0

    #中間より多いか少ないかで温度と湿度を判別している
    for length in lengths:
        #中間より小さければ温度
        bit = 0
        if length > halfway:
            #中間より大きければ湿度
            bit = 1
        bits.append(bit)

    #[湿度,XX,温度,XX,チェックサム]のリストの作成
    for i in range(0, len(bits)):
        byte = byte << 1
        if (bits[i]):
            byte = byte | 1
        else:
            byte = byte | 0
        if ((i + 1) % 8 == 0):
            the_bytes.append(byte)
            byte = 0

    #チェックサム比較
    checksum = (the_bytes[0] + the_bytes[1] + the_bytes[2] + the_bytes[3]) & 0xFF
    if the_bytes[4] != checksum:
        return False

    return the_bytes[0], the_bytes[2]

def main():

    #温湿度情報を取得
    while True:
        result = read_dht11_dat()
            
        #取得できるまで繰り返し
        if result != False:
            humidity, temperature = result
            break

    #日付情報を取得
    date = datetime.datetime.now()

    #温湿度情報をファイル出力
    output = date.strftime('%Y/%m/%d %H:%M:%S ' + str(temperature) + " " + str(humidity))
    com = "echo \"" + output + "\" > /var/local/NowTemp.txt"
    os.system(com)

def destroy():
    GPIO.cleanup()

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        destroy()
```
# 10分に1回温度情報を更新
常に最新の温度にしておきたいので、10分周期でコマンド実行するように/etc/crontabに記載して、「systemctl resatar cron」でcronを再起動します。
すると10分周期で最新情報に更新してくれます。

```linux
# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
*/10 *  * * *   root    python3 /home/pi/leo_test/temp_check2.py
```