Edisonに温湿度センサをつないでみる [edison]
Edisonに温湿度センサをつないでみた.
使用したのは,秋月電子で以前購入した,温湿度センサモジュールAM2321だ.
このセンサは,当初は中国語のデータシートしかなかったらしいが,今は英語のデータシートを確認することができる.
また,デジタル 温度・湿度センサー AM2321 を制御 - Neにマニュアルを日本語訳された方の情報があって,とても助かりました.
というわけで,センサの詳細は上記を参照してもらうとして...
このセンサ,買って手元に届いてから気がついたんだけど,ピン間隔が1.27mmになっていて,そのままではブレッドボードに挿せない.なので,ピンをやや曲げて間隔を広げつつ,ピンヘッダに半田付けしてやる.
半田付けがちょっと汚いが,こんな感じ.
これでブレッドボードに挿せる.
さて,ではEdisonとの接続だ.
AM2321は通信モードとしてI2Cか1-Wireが選べるんだけど,今回はI2Cを使うことにした.EdisonはIntel Edison Breakout Boardを使っているので,IOは1.8Vだ.なので以前の照度センサをつないでみたときと同様に,秋月のI2Cバス用双方向電圧レベル変換モジュール(PCA9306)を経由して接続してやる.
回路図はこんな感じになる.I2Cのレベル変換モジュールはジャンパカットが必要なので注意.
当初はこんな感じで接続していたが,AE-PCA9306ではVref2側を高電圧側にするべきである.詳細は,ここのコメント欄を参照.
なので,こちらの回路図のように接続すべきである.
で,接続するとこんな感じ.写真はAE-PCA9306のVref2側を低電圧側にしちゃったままのものだが,接続のイメージはつかめると思う.
Arduinoで動作させてみる.スケッチは,いろんなサイトを参考にしつつ作成した.これでシリアルに温度と湿度が5秒おきに送られてくる.
このセンサは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製だし.機会があれば試してみたいが,そんなにいくつも温湿度センサっていらないよなぁ...
使用したのは,秋月電子で以前購入した,温湿度センサモジュールAM2321だ.
このセンサは,当初は中国語のデータシートしかなかったらしいが,今は英語のデータシートを確認することができる.
また,デジタル 温度・湿度センサー AM2321 を制御 - Neにマニュアルを日本語訳された方の情報があって,とても助かりました.
というわけで,センサの詳細は上記を参照してもらうとして...
このセンサ,買って手元に届いてから気がついたんだけど,ピン間隔が1.27mmになっていて,そのままではブレッドボードに挿せない.なので,ピンをやや曲げて間隔を広げつつ,ピンヘッダに半田付けしてやる.
半田付けがちょっと汚いが,こんな感じ.
これでブレッドボードに挿せる.
さて,ではEdisonとの接続だ.
AM2321は通信モードとしてI2Cか1-Wireが選べるんだけど,今回はI2Cを使うことにした.EdisonはIntel Edison Breakout Boardを使っているので,IOは1.8Vだ.なので以前の照度センサをつないでみたときと同様に,秋月のI2Cバス用双方向電圧レベル変換モジュール(PCA9306)を経由して接続してやる.
回路図はこんな感じになる.I2Cのレベル変換モジュールはジャンパカットが必要なので注意.
当初はこんな感じで接続していたが,AE-PCA9306ではVref2側を高電圧側にするべきである.詳細は,ここのコメント欄を参照.
なので,こちらの回路図のように接続すべきである.
で,接続するとこんな感じ.写真はAE-PCA9306のVref2側を低電圧側にしちゃったままのものだが,接続のイメージはつかめると思う.
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製だし.機会があれば試してみたいが,そんなにいくつも温湿度センサっていらないよなぁ...
タグ:温湿度センサ