Python
RaspberryPi
GoogleSpreadSheet
GoogleHome

(ラズパイで温度・湿度・気圧をグーグルシートに保存してグーグルホームにしゃべらせたのやつ)に近づいたらバックライトが付くようになった

 今回、前回の成果物にさらに距離センサーを加え、人が近づいたら液晶ディスプレイのバックライトが点くようになりました。I2Cも4連。これで視野性がアップです!
201807fin.jpg

この前の記事

ラズパイで温度・湿度・気圧をグーグルシートに保存してグーグルホームにしゃべらせた

出来たこと

・I2Cで接続した距離センサーで、人が近づいているのを検知し、液晶ディスプレイのバックライトを点灯(今回の追加)

・室内の温度・湿度・気圧および6時間前との気圧変化イメージをリアルタイムに計測し、液晶ディスプレイに表示(前回機能)
・毎時の温度・湿度・気圧をGoogle スプレッドシートに自動保存(前回機能)
・タクトスイッチを押すと、現在の温度・湿度・気圧と6時間前の気圧変化をGoogle Home Miniが話してくれます(前回機能)

接続構成図

kousei.gif

図にありますようにI2Cで4つのデバイスをパラレルに繋げています。なので非常にシンプルです。
ブレッドボード上に各デバイスを配置していますが、接続コードもVDD,GND,SDA,SCLで色をきっちり分ければ、接続ミスも減りますね。

$ i2cdetect -y 1

でアドレスを確認。4つのデバイスともアドレスはダブっていません。
i2cdetect201807.gif

測距モジュールGP2Y0E03について

とても小さなモジュールです。(横1cm!)
1番:VDD 2番:- 3番:GND 4番:VDD* 5番:VDD 6番:SCL 7番:SDA
アドレスは0x40です。

常時、センサーから前に立つ障害物の距離を測定して、設定以下に近づいたら、GPIO(この場合は4番)をHIGHにして、液晶ディスプレイのバックライトを制御します。

距離を測定してGPIOを制御するコードは以下のとおり(全体コードは一番下に表示してあります)
30cmより近づくとGIIO4がHIGHに、それ以外だとLOWになります。
コメントアウトしてますが、distanceに距離が入っていますのでprint文で測定値が確認できます。

address_gpy2=0x40
register_gpyu=0x5E
register_gpys=0x5F

def read_gpy2():  #GP2Y0E03
    data=0
    #11-4bit data
    ue=i2c.read_word_data(address_gpy2,register_gpyu)
    #3-0bit data
    shita=i2c.read_word_data(address_gpy2,register_gpys)

    ue=ue & 0xff
    shita=shita & 0xff

    distance =((ue*16+shita)/16)/4
    #print(distance)

    if (distance<30):
        GPIO.output(4,GPIO.HIGH)
    else:
        GPIO.output(4,GPIO.LOW)


液晶ディスプレイLCD2320(AQM0802A)について

前回はバックライト無しを買ってしまったので、今回はバックライト有りに差し替えています(汗)。
秋月電子の説明書には、GPIOにてバックライトオンオフ制御が可能とあったので試してみたところ、どうもバックライトが点きません。で、お店に聞きに行ったら下記の部分もハンダ付けしなければいけないとのこと。(丁寧に教えていただきました)
確かに説明書には、「バックライト有りの液晶はバックライト端子をハンダ付けします」と書いてありました。(わかりづらいといればわかりづらいが・・)

display_back.jpg

左1番ピンから
1番:RST 2番:GND 3番:LED 4番:SCL 5番:SDA 6番:VDD
ですので、3番をラズパイのGPIO4に接続して、バックライトオンオフを制御しています。

で、距離測定のタイミング

常時、温湿度および気圧、表示していますので、それにあわせて距離を測定しています。
実際には、温湿度表示+ウエイト2秒+表示切替+気圧表示+ウエイト2秒で表示を切り替えますので、

# データ受取(湿度・温度)
        s = "Hm:"+str(hum)+"%Tp:"+str(tmp)+"C"
        write_string(s)
####
        read_gpy2() # 距離取得
####
        time.sleep(2) #2秒表示

# データ受取(気圧)
        s = " "+prs+"hPa"+disp
        write_string(s)
####
        read_gpy2() # 距離取得
####
        time.sleep(2) #2秒表示

コード

# -*- coding: utf-8 -*-
# AM2320-BMP085-LCD2320(AQM0802A)-Google sheet-Google Home

import smbus
import sys
import time
import requests
import os
import Adafruit_BMP.BMP085 as BMP085
import RPi.GPIO as GPIO
from datetime import datetime

i2c = smbus.SMBus(1) #2320
address = 0x5c #2320
sensor = BMP085.BMP085()

#GP2Y0E03
address_gpy2=0x40
register_gpyu=0x5E
register_gpys=0x5F

#Maker Webhooks
EVENT="LivingRoom Humidity-Temperature"
KEY="**********************"

#GPIOの初期化命令(トグルスイッチはラズパイのGPIO24に接続)
GPIO.setmode(GPIO.BCM)
GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(4,GPIO.OUT)
GPIO.output(4,GPIO.LOW)

#液晶ディスプレイセッティング
address_aqm0802a = 0x3e
register_setting = 0x00
register_display = 0x40

chars_per_line = 8  #8x2行ディスプレイを使用
display_lines = 2
display_chars = chars_per_line*display_lines

position = 0
line = 0
disp="L******H"

#その他初期化
comment=""
hist=[1013,1013,1013,1013,1013,1013]
old_time = 99

def read_gpy2():  #GP2Y0E03
    data=0
    #11-4bit data
    ue=i2c.read_word_data(address_gpy2,register_gpyu)
    #3-0bit data
    shita=i2c.read_word_data(address_gpy2,register_gpys)

    ue=ue & 0xff
    shita=shita & 0xff

    distance =((ue*16+shita)/16)/4
    #print(distance)

    if (distance<31):
        GPIO.output(4,GPIO.HIGH)
    else:
        GPIO.output(4,GPIO.LOW)


#液晶ディスプレイ
def setup_aqm0802a(): 
    trials = 5
    for i in range(trials):
        try:
            i2c.write_i2c_block_data(address_aqm0802a, register_setting, [0x38, 0x39, 0x14, 0x70, 0x56, 0x6c])
            time.sleep(0.2)
            i2c.write_i2c_block_data(address_aqm0802a, register_setting, [0x38, 0x0d, 0x01])
            time.sleep(0.001)
            break
        except IOError:
            if i==trials-1:
                sys.exit()

def clear():
    global position
    global line
    position = 0
    line = 0
    i2c.write_byte_data(address_aqm0802a, register_setting, 0x01)
    time.sleep(0.001)

def newline():
    global position
    global line
    if line == display_lines-1:
        clear()
    else:
        line += 1
        position = chars_per_line*line
        i2c.write_byte_data(address_aqm0802a, register_setting, 0xc0)
        time.sleep(0.001)

def write_string(s):
    for c in list(s):
        write_char(ord(c))

def write_char(c):
    global position
    byte_data = check_writable(c)
    if position == display_chars:
        clear()
    elif position == chars_per_line*(line+1):
        newline()
    i2c.write_byte_data(address_aqm0802a, register_display, byte_data)
    position += 1

def check_writable(c):
    if c >= 0x20 and c <= 0x7d :
        return c
    else:
        return 0x20 # 空白文字

#Google Spread Sheetに書込み
def google_post(hum,tmp,prs):
    url = "https://maker.ifttt.com/trigger/" + EVENT + "/with/key/" + KEY
    data = { "value1": hum, "value2": tmp, "value3": prs }
    requests.post(url=url, data=data)

#Google Home miniに送信
def my_callback(channel):
    if channel == 24:
         os.system("node word0.js "+"現在の部屋の湿度は"+str(hum)+"%、温度は"+str(tmp)+"度、気圧は"+str(prs)+ "ヘクトパスカルです。"+comment)

def prs_check(hist5,hist0):
    global comment
    global disp

    if hist5 > hist0+9:
        comment="6時間で大きく気圧が上がっています"
        disp="L     >H"
    elif hist5 > hist0+4:
        comment="6時間でやや気圧が上がっています"
        disp="L    > H"
    elif hist5 > hist0+2:
        comment="6時間で少し気圧が上がっています"
        disp="L   >  H"
    elif hist5 < hist0-9:
        comment="6時間で大きく気圧が下がっています"
        disp="L<     H"
    elif hist5 < hist0-4:
        comment="6時間でやや気圧が下がっています"
        disp="L <    H"
    elif hist5 < hist0-2:
        comment="6時間で少し気圧が下がっています"
        disp="L  <   H"
    else:
        comment="気圧はほぼ安定しています"
        disp="L  ==  H"

#割り込み
GPIO.add_event_detect(24, GPIO.RISING, callback=my_callback, bouncetime=2000)

#液晶ディスプレイセッティング
setup_aqm0802a()


try:
    while True:
        try:
            i2c.write_i2c_block_data(address,0x00,[])
        except:
            pass
# 読み取り命令
        time.sleep(0.003)
        i2c.write_i2c_block_data(address,0x03,[0x00,0x04])

# データ受取(湿度・温度)
        time.sleep(0.015)
        block = i2c.read_i2c_block_data(address,0,6)
        hum = float(block[2] << 8 | block[3])/10
        tmp = float(block[4] << 8 | block[5])/10

        clear()
        s = "Hm:"+str(hum)+"%Tp:"+str(tmp)+"C"
        write_string(s)
####
        read_gpy2()
####
        time.sleep(2) #2秒表示

# データ受取(気圧)
        prs = "{0:4s}".format(str(sensor.read_pressure()/100))
        s = " "+prs+"hPa"+disp
        write_string(s)
####
        read_gpy2()
####
        time.sleep(2) #2秒表示

        now_time = datetime.now().strftime("%H") #今の「時」を取得
        if str(now_time) != str(old_time): #「時」が変わっていれば・・
            google_post(hum,tmp,prs) # Google Spreaed Sheetに書込み
            for i in range(0,5): #過去6時間分のデータを更新
                hist[i]=hist[i+1]
            hist[5]=int(prs)
            old_time = now_time
            prs_check(hist[5],hist[0]) #6時間前の気圧変化をチェック

except KeyboardInterrupt:
    pass

GPIO.cleanup()

所感

I2Cにデバイスを常時4つ繋げて、たまにバックライト点けたり、GoogleSpreadSheetを書き込んだり、はたまたGoogleHomeにしゃべらせたりしても、元気にRaspberry Pi Zeroは動いてくれます。
ただ、小さめのブレッドボードを使っているので、もうこれ以上はデバイスは載らない感じかな。