ラズパイその他工作

ラズパイとセンサで作る「快適空間自動生成装置」第2回

こんにちは、ヨシケンです!
自宅を快適に、在宅仕事を効率的にするデバイス作りの第2回です。前回は制作の概要と必要な部品を紹介しました。今回は実際にBluetoothセンサとラズパイをつないでいきます。ローム・センサメダルがあればとても簡単に、リモートでもセンサの値をラズパイに連携することができますよ!

1-3

 

今回の記事で必要な物一覧

Raspberry Pi 3 B+ または Raspberry Pi 4 Model B

3

Raspberry Pi 3 B+

4

Raspberry Pi 4 Model B

 

ローム・センサメダル(SensorMedal-EVK-002)

5

 

モバイルバッテリ

6

 

USB機器

100均などで買えるUSBミニライトや扇風機などを使用

7-2

 

今回の記事の流れ

  1. ローム・センサメダルとラズパイのBLE接続
  2. ラズパイUSBのコントロール
  3. センサ値を使ってハードウェアを動かすプログラム
  4. まとめ

 

1. ローム・センサメダルとラズパイのBLE接続

前回はローム・センサメダルをとりあえずスマホにつないで、その結果を表示してみました。ここではデータを受信する母艦としてラズパイを使いますので、ラズパイのBluetoothとセンサメダルを接続してみます。

まず、ラズパイのBluetooth接続のためのPythonプログラムbluepyをインストールします。

pi@raspberrypi:~ $ sudo pip3 install bluepy
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting bluepy
  Downloading https://www.piwheels.org/simple/bluepy/bluepy-1.3.0-cp37-cp37m-linux_armv7l.whl (560kB)
    100% |████████████████████████████████| 563kB 608kB/s 
Installing collected packages: bluepy
Successfully installed bluepy-1.3.0

 

次に、センサメダルとラズパイに電源を入れ、近くに置きます。

9_1

 

センサメダルをBluetooth経由でラズパイにつなぎます。センサメダルからの数値を表示する便利なプログラムがあるので、それをダウンロードします(こちらのGithubを使用させてもらっています)。

pi@raspberrypi:~ $  sudo mkdir Programs
pi@raspberrypi:~ $  cd Programs
pi@raspberrypi:~ $  sudo git clone http://github.com/bokunimowakaru/SensorMedal2

 

ダウンロードしたSensorMedal2フォルダに移り、以下のサンプルプログラムを実行します。こちらはPython3でsudo権限を付けて実行する必要があります。

pi@raspberrypi:~ $  cd SensorMedal2
pi@raspberrypi:~ $  sudo python3 ble_logger_SensorMedal2.py

 

いかがでしょうか?以下のように、とても簡単にセンサメダルからの計測数値をラズパイから見ることができたと思います。

14

 

センサメダルには全部で6個のセンサが内蔵されています。それぞれの意味はこのようになっており、様々な数値を計測、取得することができます。

  • Temperature: 温度(℃)
  • Humidity: 湿度(%)
  • Pressure: 気圧(hPa)
  • Illuminance: 明るさ(lx)
  • Accelerometer: 加速度(x軸、y軸、z軸)(g)
  • Geomagnetic: ジャイロセンサ値(x軸、y軸、z軸)(uT)
  • Magnetic: ホールセンサ値(もし磁石が近くを通ったら1、そうでない場合0)
  • Steps: 歩数(歩)
  • Battery Level: バッテリの残量

 

2. ラズパイUSBのコントロール

とても簡単にセンサの値を取得できたので、これを使ってラズパイにつないだハードウェアをコントロールしてみましょう。

前回記載した「このような機能があったらいいな」から以下を実装してみます。

番号 計測機能 計測後にあったらいい機能
1 部屋の温度を測る 室温に合わせて、扇風機などをコントロール
2 手元の明るさを測る 暗かったらライトを点ける

天気の変化や部屋の状況により、明るさが変化します。暗くなってもそのまま作業を続けると目が疲れるので、先ほどのセンサメダルの数値のうち、明るさのIlliminance (lx)を使います。明るさはルクスという単位で表示されます。昼間の部屋の明るさで200〜300ルクスくらいです。

明るさを測定後、手元が暗かったら電気を点けるように、USBで使えるミニライトを使います。このようにラズパイのUSB端子にミニライトを挿します。

10

明るさに応じてこのライトを点けたり消したりするように、USBをコントロールするライブラリをインストールします。以下のようにライブラリをダウンロード、インストールをおこないます。

 

pi@raspberrypi:~ $  wget https://www.gniibe.org/oitoite/ac-power-control-by-USB-hub/hub-ctrl.c
pi@raspberrypi:~ $  sudo apt-get install libusb-dev
pi@raspberrypi:~ $  gcc -o hub-ctrl hub-ctrl.c -lusb

 

さあ、これでコマンドからUSBに挿したデバイスのON、OFFができるようになりました。このhub-ctrlの使い方は、hub-ctrl -b [Bus Num] -d [Device Num] -P [Port Num] -p [On:1 / Off:0] のようになります。lsusb -tコマンドでデバイス接続情報を取得します。ここでは、Bus num: 1, Device num: 2, USBポートのPort numは2になります。

pi@raspberrypi:~ $  hub-ctrl
Hub #0 at 001:002
 INFO: individual power switching.
 WARN: Port indicators are NOT supported.
Hub #1 at 001:001
 INFO: ganged switching.
 WARN: Port indicators are NOT supported.

pi@raspberrypi:~ $  lsusb -t
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=dwc_otg/1p, 480M
    |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/5p, 480M
        |__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=smsc95xx, 480M

 

以下のように、-pに0を入れると電源オフ、1を入れると電源オンになります。

pi@raspberrypi:~ $  sudo hub-ctrl -b 1 -d 2 -P 2 -p 0
pi@raspberrypi:~ $  sudo hub-ctrl -b 1 -d 2 -P 2 -p 1

11

こちらは、-p 1を指定した状態。USBに接続したデバイスに電源が入りました。

 

3. センサ値からハードウェアを動かすプログラム

それではセンサメダルからの数値とUSBコントロールを紐付けたプログラムを作ります。
基本は先ほどダウンロードしたSensorMedal2プログラムを使います。

pi@raspberrypi:~ $  sudo cp ble_logger_SensorMedal2.py ble_illum.py

 

元々のプログラムに以下の9行目、78〜85行目の部分を追加します。明るさが300lxを下回ったらライト点灯。それ以上ならライトは消しておきます。

#!/usr/bin/env python3
# coding: utf-8

from __future__ import (division, absolute_import, print_function,
                                unicode_literals)
import fcntl
import socket
import struct
import os

def get_addr(ifname):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        return socket.inet_ntoa(
            fcntl.ioctl(
                s.fileno(),
                0x8915,  # SIOCGIFADDR
                struct.pack('256s', ifname[:15].encode('utf-8')))[20:24])
    except IOError:
        return 'Not Found!'

interval = 10 # 動作間隔

from bluepy import btle
from sys import argv
import getpass
from time import sleep

def payval(num, bytes=1, sign=False):
    global val
    a = 0
    for i in range(0, bytes):
        a += (256 ** i) * int(val[(num - 2 + i) * 2 : (num - 1 + i) * 2],16)
    if sign:
        if a >= 2 ** (bytes * 8 - 1):
            a -= 2 ** (bytes * 8)
    return a

scanner = btle.Scanner()
while True:    
    try:
        devices = scanner.scan(interval)
    except Exception as e:
        print("ERROR",e)
        if getpass.getuser() != 'root':
            print('使用方法: sudo', argv[0])
            exit()
        sleep(interval)
        continue

    for dev in devices:
        print("\nDevice %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi))
        isRohmMedal = False
        sensors = dict()
        for (adtype, desc, val) in dev.getScanData():
            print("  %s = %s" % (desc, val))
            if desc == 'Short Local Name' and val[0:10] == 'ROHMMedal2':
                isRohmMedal = True
            if isRohmMedal and desc == 'Manufacturer':

                # センサ値を辞書型変数sensorsへ代入
                sensors['ID'] = hex(payval(2,2))
                sensors['Illuminance'] = payval(25,2) / 1.2
                sensors['Battery Level'] = payval(30)
                sensors['RSSI'] = dev.rssi

                # 画面へ表示
                print('    ID            =',sensors['ID'])
                print('    Illuminance   =',round(sensors['Illuminance'],1),'lx')
                print('    Battery Level =',sensors['Battery Level'],'%')
                print('    RSSI          =',sensors['RSSI'],'dB')

                '''
                for key, value in sorted(sensors.items(), key=lambda x:x[0]):
                    print('    ',key,'=',value)
                '''

                illum = sensors['Illuminance']
                if illum < 300:
                    illum_msg = "Dark!"
                    os.system(“sudo hub-ctrl -b 1 -d 2 -P 2 -p 1”)
                else:
                    illum_msg = "Bright"
                    os.system(“sudo hub-ctrl -b 1 -d 2 -P 2 -p 0”)
                print(illum_msg)
                sleep(interval)

 

このプログラムをsudo python3 ble_illum.pyと流します。

15

 

センサの値を取得し、右側の写真のようにセンサメダルを覆って暗くなると、見事ライトが点きました。

12-2

 

4. まとめ

今回は、ローム・センサメダルとラズパイをBLE接続してみました。とても簡単に、離れたところから様々なセンサ値を取得できるのがご理解頂けたのではないかと思います。

6つのセンサにより、明るさだけでなく、温湿度や、気圧、加速度なども分かります。デスクや部屋の中の数値を色々測っても面白いかもしれませんね。

次回は、人感センサなども付けてさらに家でのリモートワークを快適にするような工夫をしていきたいと思います。

お楽しみに!

Tello+Scratch+SQ11でプチ動画を撮る!
ヨシケン(吉田 顕一)

普通の会社に勤めるサラリーマンですが、モノ作りが好きな週末メイカーで、電子書籍MESHBOOKを出したり、ブログを書いたりしています!

http://blog.ktrips.net