今回はBMP180を使って、node.jsで値を取得する。
Raspberry pi と BMP180を物理的に接続する
この方のブログがすごいよかった。
以下のように接続する
RasPi BMP180
3.3V <==> VIN
GND <==> GND
SCL <==> SCL
SDA <==> SDA
Raspberry pi でI2Cを使えるようにする
ラズパイで下記のコマンドを打つ
sudo nano /etc/modules
以下の2文を追記する
i2c-bcm2708
i2c-dev
ブラックリストからI2Cを除く
sudo nano /etc/modprobe.d/raspi-blacklist.conf
以下の文に#をつけてコメントアウトを行う
(なければスルーでいいと思います)
blacklist i2c-bcm2708
それに加えて以下のコマンドを実行し、config.txtの編集を行う
sudo vim /boot/config.txt
以下を追記する
#以下を追記
device_tree=bcm2708-rpi-b.dtb
device_tree_param=i2c1=on
device_tree_param=spi=on
必要なソフトウェアのインストール
sudo apt-get install i2c-tools
リブートを行った
sudo shutdown -r now
最後に本当に接続できているかの確認を行う
sudo i2cdetect -y 1
以下の表示が出ればおっけー
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- 77
BMP180のデータを取得する
一応、BMP180と互換性があるBMP085のライブラリが使えるらしくbmp085やbmp085-sensorを試したが、動かなかった。
原因はbmp085、bmp085-sensorのnodeライブラリで使われているi2cライブラリがnodeのv0.12系で動かないためらしい、しかしrasp2cライブラリならI2Cの通信が行えるライブラリとして使えるので、Githubに上がっていたbmp085-sensorのコードでi2cを利用している部分をrasp2cに置き換えた。置き換えたコードが以下
var async = require('async');
var rasp2c = require('rasp2c');
module.exports = function BMP085(options) {
var sensor = function() {};
// var wire = new i2c(options.address);
var call = {};
var BMP085_CONTROL_REGISTER = 0xF4;
var BMP085_SELECT_TEMP = 0x2E;
var BMP085_SELECT_PRESSURE = 0x34;
var BMP085_CONVERSION_RESULT = 0xF6;
var BMP085_XLSB = 0xF7;
sensor.scan = function () {
rasp2c.detect(function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
};
function toS16(high, low) {
if (high > 127)
high -= 256;
return (high << 8) + low;
}
function toU16(high, low) {
return (high << 8) + low;
}
sensor.calibrate = function () {
rasp2c.dump(options.address, '0xAA-0xBF', function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
cal = {
ac1: toS16(result[0], result[1]),
ac2: toS16(result[2], result[3]),
ac3: toS16(result[4], result[5]),
ac4: toU16(result[6], result[7]),
ac5: toU16(result[8], result[9]),
ac6: toU16(result[10], result[11]),
b1: toS16(result[12], result[13]),
b2: toS16(result[14], result[15]),
mb: toS16(result[16], result[17]),
mc: toS16(result[18], result[19]),
md: toS16(result[20], result[21])
};
}
});
};
sensor.read = function (call) {
async.waterfall([
function (callback) {
// Write select pressure command to control register
rasp2c.set(options.address, BMP085_CONTROL_REGISTER, [BMP085_SELECT_PRESSURE + (options.mode << 6)], function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
setTimeout(function () {
callback(null); }, 28);
},
function (callback) {
// Read uncalibrated pressure.
rasp2c.dump(options.address, '0xF6-0xF8', function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
callback(null, ((result[0] << 16) + (result[1] << 8) + result[2]) >> (8 - options.mode));
}
});
},
function (pressure, callback) {
rasp2c.set(options.address, BMP085_CONTROL_REGISTER, [BMP085_SELECT_TEMP], function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
}
});
setTimeout(function () {
callback(null, pressure); }, 8);
},
function (pressure, callback) {
rasp2c.dump(options.address, '0xF6-0xF7', function(err, result) {
if (err) {
console.log(err);
} else {
console.log(result);
callback(null, [pressure, toU16(result[0], result[1])]);
}
});
}
], function (err, res) {
if (err)
call(err, {});
var uncal_pressure = res[0];
var uncal_temp = res[1];
// Get calibrated temp
var x1 = 0;
var x2 = 0;
var x3 = 0;
var b3 = 0;
var b4 = 0;
var b5 = 0;
var b6 = 0;
var b7 = 0;
var p = 0;
x1 = ((uncal_temp - cal.ac6) * cal.ac5) >> 15;
x2 = (cal.mc << 11) / (x1 + cal.md);
b5 = x1 + x2;
var corrected_temp = ((b5 + 8) >> 4) / 10.0;
if (options.units !== 'metric'){
corrected_temp = (9 * corrected_temp / 5) + 32;
}
// Get calibrated pressure
x1 = 0;
x2 = 0;
x3 = 0;
b3 = 0;
b4 = 0;
b5 = 0;
b6 = 0;
b7 = 0;
p = 0;
x1 = ((uncal_temp - cal.ac6) * cal.ac5) >> 15;
x2 = (cal.mc << 11) / (x1 + cal.md);
b5 = x1 + x2;
b6 = b5 - 4000;
x1 = (cal.b2 * (b6 * b6) >> 12) >> 11;
x2 = (cal.ac2 * b6) >> 11;
x3 = x1 + x2;
b3 = (((cal.ac1 * 4 + x3) << options.mode) + 2) / 4;
x1 = (cal.ac3 * b6) >> 13;
x2 = (cal.b1 * ((b6 * b6) >> 12)) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (cal.ac4 * (x3 + 32768)) >> 15;
b7 = (uncal_pressure - b3) * (50000 >> options.mode);
if (b7 < 0x80000000)
p = (b7 * 2) / b4;
else
p = (b7 / b4) * 2;
x1 = (p >> 8) * (p >> 8);
x1 = ((x1 * 3038) >> 16);
x2 = ((-7357 * p) >> 16);
p = p + ((x1 + x2 + 3791) >> 4);
if (options.units !== 'metric'){
p /= 3386.0;
}
call(err, {pressure: p,
temperature: corrected_temp});
});
};
sensor.calibrate();
return sensor;
};
そしてこれを下記のコードで呼ぶ
var BMP085 = require('./bmp180.js');
var sensor = BMP085({address: 0x77,
mode: 3,
units: 'metric'});
sensor.read(function (err, data) {
console.log("pressure:" +data.pressure);
console.log("temperature:" +data.temperature);
});
すると結果が以下のようになり、情報の取得をおこなえる
[ 27,
93,
251,
232,
199,
77,
129,
185,
99,
209,
70,
158,
25,
115,
0,
36,
128,
0,
209,
246,
9,
179 ]
[rasp2c] Raspberry PI revision 000d found
[rasp2c] Using I2C bus 1
[ 157, 164, 128 ]
[ 105, 141 ]
pressure:101143.22125314194
temperature:27.6
結構苦労だった・・・