LoginSignup
11
13

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-09-21

今回は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

結構苦労だった・・・

11
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13