初めてのRaspberry Pi BLEプログラミング (4) BME280①温度

 前回、CPUの温度を送るペリフェラルを作りました。ここからは、MEMSセンサのBME280をつないで実験を進めます。BME280の接続は、次の記事を参照してください。

 初めてのBLE (11) Raspberry Piでペリフェラル③BME280に対応

 次に、AdafruitのBME280のライブラリをインストールします。

sudo pip3 install adafruit-circuitpython-bme280

 プログラムを作ります。動作確認なので温度だけを読み出します。

import board
import busio
import adafruit_bme280
i2c = busio.I2C(board.SCL, board.SDA)
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, 0x76)
print("\nTemperature: %0.1f C" % bme280.temperature)

 実行結果です。問題なく動いているようです。

修正;BatteryLevelCharacteristic.py

 前回Characteristic(キャラ)を記述したBatteryLevelCharacteristic.pyでは、CPU温度を送るように記述しました。これを上記のBME280の温度に変更します。また、ファイル名をBME280Characteristic.pyに変更します。

from pybleno import *
import array
import board
import busio
import adafruit_bme280

class BME280Characteristic(Characteristic):
    def __init__(self):
        Characteristic.__init__(self, {
            'uuid': '12345678-1234-5678-1234-56789abcdef7',
            'properties': ['read'],
            'value': None
          })

    def onReadRequest(self, offset, callback):
            i2c = busio.I2C(board.SCL, board.SDA)
            bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, 0x76)
            callback(Characteristic.RESULT_SUCCESS, array.array('B', [int(bme280.temperature)]))

 UUIDは、独自の文字列です。

修正;BatteryService.py

 Serviceを記述したBatteryService.pyのファイル名をBME280Service.pyに変更し、内容は、上記のキャラを指定します。UUIDは、独自の文字列です。

from pybleno import *
from BME280Characteristic import *

class BME280Service(BlenoPrimaryService):
    def __init__(self):
        BlenoPrimaryService.__init__(self, {
          'uuid': '12345678-1234-5678-1234-56789abcdef0',
          'characteristics': [
              BME280Characteristic()
          ]})

修正;main.py

 14行目bleno.startAdvertising('BME280-t', で、Local Nameを変更しました。あと、呼び出すサービスの名前を修正しました。

from pybleno import *
import sys
import signal
from BME280Service import *

bleno = Bleno()

primaryService = BME280Service();

def onStateChange(state):
   print('on -> stateChange: ' + state);

   if (state == 'poweredOn'):
       bleno.startAdvertising('BME280-t', [primaryService.uuid]);
   else:
     bleno.stopAdvertising();
bleno.on('stateChange', onStateChange)

def onAdvertisingStart(error):
    print('on -> advertisingStart: ' + ('error ' + error if error else 'success'));

    if not error:
        def on_setServiceError(error):
            print('setServices: %s'  % ('error ' + error if error else 'success'))

        bleno.setServices([
            primaryService
        ], on_setServiceError)
bleno.on('advertisingStart', onAdvertisingStart)

bleno.start()

print ('Hit  to disconnect')

if (sys.version_info > (3, 0)):
    input()
else:
    raw_input()

bleno.stopAdvertising()
bleno.disconnect()

print ('terminated.')
sys.exit(1)

 実行します。温度(整数)が読み取れました。

 今度は実数で送ります。BME280Characteristic.pyの最後の行で、温度をint()で整数にしていたところをstruct.pack('>f'で、32ビットの固定小数点形式に変換します。0x41d03b9aのようなバイト列になっているので、list()で[0x41, 0xd0, 0x3b, 0x9a]のようにリスト形式にします。これは、arrayの配列と同じなので、1byteが四つになって送られます。

callback(Characteristic.RESULT_SUCCESS, array.array('B', list(struct.pack('>f', (bme280.temperature))) ))

 実行結果です。0x410xd00x3b0x9a=0x41d03b9aは、26.0291です。

  検証; Floating Point to Hex Converter