So-net無料ブログ作成
検索選択

Intel XDK IoT Editionを使って温湿度センサを動かしてみる [edison]

前回,EdisonでArduino IDEから動かしてみた.
今回は,Intel XDK IoT Editionを使って温湿度センサを動かしてみる.

というわけで,まず,Intel XDK IoT Editionのインストール.
インストール手順とか,Intel XDK IoT Editionの使い方等は,詳しく書かれているサイトがいくつもあるので,そちらを参照下さいな.
たとえば...
Edisonを開封してからnode.jsでIOポート制御するまで - Qiita
Intel EdisonでIntel XDK for IoTを使う - Qiita
[Edison]Intel XDK IoT Edisonをつかってプログラムのビルドをしてみる | Developers.IO
あたりが参考になるかと.

で,温湿度センサを動かしてみる.温湿度センサは前回使った,AM2321だ.接続(回路図)等は前回から変わってない.

というわけで,早速コードを示そう.
適当なProjectを作って,package.jsonとmain.jsを以下のようにしてやる.

まず,package.json
{
  "name": "TemperatureHumiditySensor",
  "description": "",
  "version": "0.0.0",
  "main": "main.js",
  "engines": {
    "node": ">=0.10.0"
  },
  "dependencies": {
      "sleep": "*"
  }
}

次に,main.js
var mraa = require('mraa');
console.log('MRAA Version: ' + mraa.getVersion());

var sleep = require('sleep');

function crc16(buf, length)
{
    var crc = 0xFFFF;
    for (var j = 0; j < length; j++) {
        crc ^= buf[j];
        for (var i = 0; i < 8; i++) {
            if (crc & 0x01) {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

function Am2321(bus, address, bufsize) {
    this.x = new mraa.I2c(bus);
    this.x.address(address);
    this.buff = new Buffer(bufsize);
    
    this.wakeupSensor = function() {
        this.x.writeReg(0, 0);
    }
    
    this.sendCommand = function() {
        get_command = new Buffer([0x03, 0x00, 0x04]);
        this.x.write(get_command);
        sleep.usleep(1500);
    }
    
    this.receiveData = function() {
        this.buff = this.x.read(8);
    }
    
    this.checkCrc = function() {
        var crc = this.buff[6] + this.buff[7] * 256;
        return crc == crc16(this.buff, 6);
    }
    
    this.checkRecieveData = function() {
        return (this.buff[0] == 0x03) && (this.buff[1] == 0x04);
    }

    this.getHumidity = function() {
        var high = this.buff[2];
        var low  = this.buff[3];
        return (high * 256 + low) / 10;
    }

    this.getTemperature = function() {
        var temperature = 0;
        var high = this.buff[4];
        var low  = this.buff[5];

        if (high & 0x80) {
            temperature = -1 * (high & 0x7F) * 256 + low;
        }
        else {
            temperature = high * 256 + low;
        }
        return temperature / 10;
    }
}

var sensor = new Am2321(6, 0x5C, 8);
periodicActivity();

function periodicActivity()
{
    sensor.wakeupSensor();
    sensor.sendCommand();
    sensor.receiveData(); 

    if (sensor.checkCrc() == true) {
        if (sensor.checkRecieveData() == true) {
            var humidity = sensor.getHumidity();
            var temperature = sensor.getTemperature();
            console.log("%d %%, %d C", humidity, temperature);
        }
    }

    setTimeout(periodicActivity,5000);
}

そしたら,ビルドして,Edisonにアップロードして実行してやる.
そうすると,コンソールに温度と湿度が5秒おきに出力されるようになる.

AM2321はI2Cの通信シーケンスに癖があるのだが,とりあえず上記のコードで動作させることができるようだ.

MRAAライブラリがあるので,Arduinoで動かしたときと同じぐらい簡単.
お試しあれ.

タグ:XDK
nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感

Edisonに温湿度センサをつないでみる [edison]

Edisonに温湿度センサをつないでみた.
使用したのは,秋月電子で以前購入した,温湿度センサモジュールAM2321だ.
このセンサは,当初は中国語のデータシートしかなかったらしいが,今は英語のデータシートを確認することができる.
また,デジタル 温度・湿度センサー AM2321 を制御 - Neにマニュアルを日本語訳された方の情報があって,とても助かりました.

というわけで,センサの詳細は上記を参照してもらうとして...
このセンサ,買って手元に届いてから気がついたんだけど,ピン間隔が1.27mmになっていて,そのままではブレッドボードに挿せない.なので,ピンをやや曲げて間隔を広げつつ,ピンヘッダに半田付けしてやる.
半田付けがちょっと汚いが,こんな感じ.
AM2321-1.jpg
これでブレッドボードに挿せる.

さて,ではEdisonとの接続だ.
AM2321は通信モードとしてI2Cか1-Wireが選べるんだけど,今回はI2Cを使うことにした.EdisonはIntel Edison Breakout Boardを使っているので,IOは1.8Vだ.なので以前の照度センサをつないでみたときと同様に,秋月のI2Cバス用双方向電圧レベル変換モジュール(PCA9306)を経由して接続してやる.

回路図はこんな感じになる.I2Cのレベル変換モジュールはジャンパカットが必要なので注意.
当初はこんな感じで接続していたが,AE-PCA9306ではVref2側を高電圧側にするべきである.詳細は,ここのコメント欄を参照.
temperature_humidity_sensor_ng.png
なので,こちらの回路図のように接続すべきである.
temperature_humidity_sensor.png

で,接続するとこんな感じ.写真はAE-PCA9306のVref2側を低電圧側にしちゃったままのものだが,接続のイメージはつかめると思う.
AM2321-2.jpg

Arduinoで動作させてみる.スケッチは,いろんなサイトを参考にしつつ作成した.これでシリアルに温度と湿度が5秒おきに送られてくる.
#include <Wire.h>

#define I2C_AM2321_ADDRESS                0x5C
#define REGISTER_ADDRESS_HUMIDITY_HIGH    0x00
#define REGISTER_ADDRESS_HUMIDITY_LOW     0x01
#define REGISTER_ADDRESS_TEMPERATURE_HIGH 0x02
#define REGISTER_ADDRESS_TEMPERATURE_LOW  0x03
#define READ_REGISTER_LENGTH              0x04
#define FUNCTION_CODE_READ_REGISTER       0x03

enum BUFF_INDEX {
    INDEX_FUNCTION_CODE = 0,
    INDEX_RETURN_BYTE,
    INDEX_HUMIDITY_HIGH,
    INDEX_HUMIDITY_LOW,
    INDEX_TEMPERATURE_HIGH,
    INDEX_TEMPERATURE_LOW,
    INDEX_CRC_LOW,
    INDEX_CRC_HIGH,
    INDEX_MAX,
};
    
void wakeupSensor()
{
    Wire.beginTransmission(I2C_AM2321_ADDRESS);
    Wire.write(0x00);
    Wire.endTransmission();
}

void sendReadCommand()
{
    Wire.beginTransmission(I2C_AM2321_ADDRESS);
    Wire.write(FUNCTION_CODE_READ_REGISTER);
    Wire.write(REGISTER_ADDRESS_HUMIDITY_HIGH);
    Wire.write(READ_REGISTER_LENGTH);
    Wire.endTransmission();

    delayMicroseconds(1500);
}

void receiveData(byte (&buff)[INDEX_MAX])
{
    Wire.requestFrom(I2C_AM2321_ADDRESS, INDEX_MAX);
    int index = 0;
    while (Wire.available()) {
        buff[index++] = Wire.read();
    }
}

unsigned short crc16(unsigned char *ptr, int length)
{
    unsigned short crc = 0xFFFF;

    while (length--) {
        crc ^= *ptr++;
        for (int i = 0; i < 8; i++) {
            if (crc & 0x01) {
                crc >>= 1;
                crc ^= 0xA001;
            }
            else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

bool checkCrc(byte (&buff)[INDEX_MAX])
{
    unsigned short crc = 0;
    crc  = buff[INDEX_CRC_LOW];
    crc |= buff[INDEX_CRC_HIGH] << 8;

    return (crc == crc16(buff, 2 + READ_REGISTER_LENGTH));
}

bool checkReceiveData(byte (&buff)[INDEX_MAX])
{
    return ( (buff[INDEX_FUNCTION_CODE] == FUNCTION_CODE_READ_REGISTER)
          && (buff[INDEX_RETURN_BYTE]   == READ_REGISTER_LENGTH) );
}

bool readAm2321(byte (&buff)[INDEX_MAX])
{
    wakeupSensor();
    sendReadCommand();
    receiveData(buff);
    if (!checkCrc(buff)) {
        return false;
    }
    return checkReceiveData(buff);
}

signed int convertHumidity(byte high, byte low)
{
    return high * 256 + low;
}

signed int convertTemperature(byte high, byte low)
{
    signed int temperature = (high & 0x7F) * 256 + low;
    temperature *= (high & 0x80) ? -1 : 1;
    return temperature;
}

void displayHumidityAndTemperature(signed int humidity, signed int temperature)
{
    Serial.print(temperature / 10);
    Serial.print(".");
    Serial.print(temperature % 10);
    Serial.print("C");
    Serial.print(", ");

    Serial.print(humidity / 10);
    Serial.print(".");
    Serial.print(humidity % 10);
    Serial.print("%");
    Serial.println();
}

void setup()
{
    Serial.begin(9600);
    Wire.begin();
}

void loop()
{
    byte buff[INDEX_MAX] = {0};
    bool result = readAm2321(buff);

    if (result == true) {
        signed int humidity = convertHumidity(buff[INDEX_HUMIDITY_HIGH],
                                              buff[INDEX_HUMIDITY_LOW]);
        signed int temperature = convertTemperature(buff[INDEX_TEMPERATURE_HIGH],
                                                    buff[INDEX_TEMPERATURE_LOW]);

        displayHumidityAndTemperature(humidity, temperature);
    }

    delay(5000);
}


このセンサはI2Cの通信シーケンスに癖があって,WakeUpが必要だったり,アドレス送信後にWaitが必要だったりする.なお、上のスケッチでは,アドレス送信後のWaitはArduinoのWireライブラリではできない(できるかもしれないがやり方が分からない)ので対応してない.

あと,ときどき,受信データByte数が0で返ってくることがある.エラーは返ってこないしCRCチェックも正常なのだが.なので,Arduino側で4Byte受信したかどうかのエラーチェックもやっている.

それから,ときどき湿度値が3%ぐらい落ち込むことがある.

センサーの湿度の値が: さとうしゅうの 日々平安 2.37
で書かれてる現象と同じっぽい.I2C通信するとき,AM2321仕様にある通信シーケンス(Wait等)を守っていないからなのかなとも思ったが,

Arduino/みんな試作機/温湿度計 - 講義のページ - MyDNS.JP
に書かれてる「動作確認-2-」の測定例を見ても湿度値が落ち込んでいるところがある.こちらはI2Cではなく1-Wireで通信した結果のようなので,通信シーケンスに問題があるのではなさそうだ.

AM2321側が何か問題があるのではないかと思うのだが,詳細はよくわからない.
まぁあまり気にしないことにする.

というわけで若干動作が怪しいところがある気がするが,お手軽に使えるのでお試しあれ.

あーでも,秋月にHDC1000使用 温湿度センサーモジュールってのがあって,こっちも試してみたい.AM2321を購入したときにはなかったんだよなぁ.こっちはピン間隔が2.54mmピッチだし,TI製だし.機会があれば試してみたいが,そんなにいくつも温湿度センサっていらないよなぁ...
nice!(2)  コメント(0)  トラックバック(0) 
共通テーマ:日記・雑感