- リンクを取得
- ×
- メール
- 他のアプリ
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
今頃気が付きましたが、getShort と getUShort 関数が同じになってますね・・・あと、BH1750FVI の値を取得するのを忘れてました。とはいえ、この状態で実行すると、
- 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();
と、値が取得できました。
- $ npx ts-node src/bb.ts
- 25.8 1088.2437277298607 49.58872975883544
コメント
コメントを投稿