Edited at

Raspberry pi に構築したnode.jsで温度センサを取得する

More than 3 years have passed since last update.

今回は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のライブラリが使えるらしくbmp085bmp085-sensorを試したが、動かなかった。

原因はbmp085、bmp085-sensorのnodeライブラリで使われているi2cライブラリがnodeのv0.12系で動かないためらしい、しかしrasp2cライブラリならI2Cの通信が行えるライブラリとして使えるので、Githubに上がっていたbmp085-sensorのコードでi2cを利用している部分をrasp2cに置き換えた。置き換えたコードが以下


bmp180.js


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;
};


そしてこれを下記のコードで呼ぶ


example.js

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

結構苦労だった・・・