- リンクを取得
- ×
- メール
- 他のアプリ
python を使ってセンサーの値を取得することができたので、次は node.js を使ってセンサーの値を取得します。物理的な接続はできていて、python での値の取得もできている、という前提です。
i2c デバイスファイルの権限変更
まず、root 権限でなくても i2c デバイスの読み書きができるようにします。スクリプトを sudo したりしなくてはならなくて不便なので、ユーザーに権限を付与します。
まず、デバイスファイルの権限を確認します。
$ ls -l /dev/i2c-* crw-rw---- 1 root i2c 89, 0 9月 15 23:17 /dev/i2c-0 crw-rw---- 1 root i2c 89, 1 9月 15 23:17 /dev/i2c-1
所有権はユーザーが "root"、グループは "i2c" になっています。なので、ユーザーを i2c グループに追加すればよさそうです。
$ sudo gpasswd -a **** i2c
****は実際のユーザー名に置き換えてください。これで再ログインすれば、前回のスクリプトも sudo を付けずに実行することが可能になります。
node.js インストール
armbian の場合、apt でも node.js をインストールできますが、npm のバージョンが古いのか、 python2.7 に依存しています。そのためだけに大量の関連パッケージをインストールするのももったいないので、nodebrew を使ってインストールすることにします。
まず nodebrew のダウンロード。
$ curl -L git.io/nodebrew | perl - setup % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0 0 0 0 0 0 0 0 0 --:--:-- 0:00:01 --:--:-- 0 100 24634 100 24634 0 0 13886 0 0:00:01 0:00:01 --:--:-- 13886 Fetching nodebrew... Installed nodebrew in $HOME/.nodebrew ======================================== Export a path to nodebrew: export PATH=$HOME/.nodebrew/current/bin:$PATH ========================================
コマンドの出力にあるとおり、.bashrc などに export で始まる行を追加して、nodebrew をダウンロードしたディレクトリをパスに追加します。
nodebrew を使って、最新版の node.js をインストールします。
$ nodebrew install-binary stable Fetching: https://nodejs.org/dist/v14.11.0/node-v14.11.0-linux-armv7l.tar.gz ################################################################################################################# 100.0% Installed successfully
nodebrew はインストール済みの node.js のバージョンを切り替えて使用することができます。そのため、インストールしたうえで、どのバージョンを使用するか指定する必要があります。インストールしただけだと、以下のように「v14.11.0」がインストールされていますが、「current: none」とあるように、使用するバージョンが指定されていない状態になります。
$ nodebrew list v14.11.0 current: none
なので、使用するバージョンを指定します。
$ nodebrew use v14.11.0 use v14.11.0
無事、current に使用するバージョンが表示されました。
$ nodebrew list v14.11.0 current: v14.11.0
ついでに、TypeScript を使うことにします。
$ mkdir builders_flash $ cd builders_flash $ npm init -y $ npm i -D typescript @types/node $ npx tsc --init
センサーの読み書きに使う i2c-bus ライブラリもインストールします。
$ npm i i2c-bus -s
コーディング
TypeScript は初めて使うので、いろいろと試行錯誤しましたが、結果的にはこんな感じのスクリプトになりました。途中の複雑な計算は、BME280 のデータシートに記載されている計算式ほぼそのまま (のつもり) です。
src/bme280.ts
const DEVICE_NUMBER = 0; //const TARGET_IC_ADDR = 0x23; const TARGET_IC_ADDR = 0x76; function getShort(data: any, index: number): number { return (data[index + 1] << 8) + data[index] } function getUShort(data: any, index: number): number { return (data[index + 1] << 8) + data[index] } function getChar(data: any, index: number): number { let result: number = data[index]; if(result > 127) { result = result - 256; } return result } function getUChar(data: any, index: number): number { let result: number = data[index] & 0xFE; return result; } function sleep(msec: number) { return new Promise(function(resolve) { setTimeout(function() {resolve()}, msec); }) } function readBME280(): void { const REG_DATA = 0xF7; const REG_CONTROL = 0xF4; const REG_CONFIG = 0xF5; const REG_CONTROL_HUM = 0xF2; const REG_HUM_MSB = 0xFD; const REG_HUM_LSB = 0xFE; const OVERSAMPLE_TEMP = 2; const OVERSAMPLE_PRES = 2; const MODE = 1; const OVERSAMPLE_HUM = 2; var i2c = require('i2c-bus'); var i2c1 = i2c.openSync(DEVICE_NUMBER); // write param i2c1.writeByteSync(TARGET_IC_ADDR, REG_CONTROL_HUM, OVERSAMPLE_HUM); const control = OVERSAMPLE_TEMP << 5 | OVERSAMPLE_PRES << 2 | MODE; i2c1.writeByteSync(TARGET_IC_ADDR, REG_CONTROL, control); var cal1 = Buffer.alloc(24); var cal2 = Buffer.alloc(1); var cal3 = Buffer.alloc(7); i2c1.readI2cBlockSync(TARGET_IC_ADDR, 0x88, cal1.length, cal1); i2c1.readI2cBlockSync(TARGET_IC_ADDR, 0xA1, cal2.length, cal2); i2c1.readI2cBlockSync(TARGET_IC_ADDR, 0xE1, cal3.length, cal3); const dig_T1 = getUShort(cal1, 0); const dig_T2 = getShort(cal1, 2); const dig_T3 = getShort(cal1, 4); const dig_P1 = getUShort(cal1, 6); const dig_P2 = getShort(cal1, 8); const dig_P3 = getShort(cal1, 10); const dig_P4 = getShort(cal1, 12); const dig_P5 = getShort(cal1, 14); const dig_P6 = getShort(cal1, 16); const dig_P7 = getShort(cal1, 18); const dig_P8 = getShort(cal1, 20); const dig_P9 = getShort(cal1, 22); const dig_H1 = getUChar(cal2, 0); const dig_H2 = getShort(cal3, 0); const dig_H3 = getUChar(cal3, 2); let dig_H4 = getUChar(cal3, 3); dig_H4 = (dig_H4 << 24) >> 20; dig_H4 = dig_H4 | (getChar(cal3, 4) & 0x0F) let dig_H5 = getChar(cal3, 5); dig_H5 = (dig_H5 << 24) >> 20; dig_H5 = dig_H5 | (getUChar(cal3, 4) >> 4 & 0x0F) const dig_H6 = getChar(cal3, 6) // Wait const wait_time = 1.25 + (2.3 * OVERSAMPLE_TEMP) + ((2.3 * OVERSAMPLE_PRES) + 0.575) + ((2.3 * OVERSAMPLE_HUM) + 0.575); sleep(wait_time / 1000); // Read temperature/pressure/humidity var data = Buffer.alloc(8); i2c1.readI2cBlockSync(TARGET_IC_ADDR, 0xF7, data.length, data); const pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4) const temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4) const hum_raw = (data[6] << 8) | data[7] // Refine tempreture let var1 = (((temp_raw >> 3) - (dig_T1 << 1)) * (dig_T2)) >> 11; let var2 = (((((temp_raw>>4) - (dig_T1)) * ((temp_raw>>4) - (dig_T1))) >> 12) * (dig_T3)) >> 14; let t_fine = var1+var2; let temperature = ((t_fine * 5) + 128) >> 8; // Refine pressure and adjust for temperature let pressure = 0; var1 = t_fine / 2.0 - 64000.0; var2 = var1 * var1 * dig_P6 / 32768.0; var2 = var2 + var1 * dig_P5 * 2.0; var2 = var2 / 4.0 + dig_P4 * 65536.0; var1 = (dig_P3 * var1 * var1 / 524288.0 + dig_P2 * var1) / 524288.0; var1 = (1.0 + var1 / 32768.0) * dig_P1; if(var1 == 0) { pressure = 0; } else { pressure = 1048576.0 - pres_raw; pressure = ((pressure - var2 / 4096.0) * 6250.0) / var1; var1 = dig_P9 * pressure * pressure / 2147483648.0; var2 = pressure * dig_P8 / 32768.0; pressure = pressure + (var1 + var2 + dig_P7) / 16.0; } // Refine humidity let humidity = t_fine - 76800.0; humidity = (hum_raw - (dig_H4 * 64.0 + dig_H5 / 16384.0 * humidity)) * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * humidity * (1.0 + dig_H3 / 67108864.0 * humidity))); humidity = humidity * (1.0 - dig_H1 * humidity / 524288.0); if(humidity > 100) { humidity = 100; } else if(humidity < 0) { humidity = 0; } console.log(temperature / 100.0, pressure / 100.0, humidity); } readBME280();今頃気が付きましたが、getShort と getUShort 関数が同じになってますね・・・あと、BH1750FVI の値を取得するのを忘れてました。とはいえ、この状態で実行すると、
$ npx ts-node src/bb.ts 25.8 1088.2437277298607 49.58872975883544と、値が取得できました。
コメント
コメントを投稿