2015年3月7日土曜日

8pinoでインフルエンザ感染リスク検知器をつくる②

今回は,I2C通信がうまくいっているのか確認する事にします.前回のエントリで「8pinoはシリアル通信できない」と書きましたが,正確にはシリアル通信できるみたいです.8pinoはUSBシリアル通信できないのですが「ソフトウェアシリアル」には対応しているので,8pinoの2本のpinをRX・TX通信路として使い,USBシリアル変換モジュールを使えばいいみたいです.

そこで秋月でUSBシリアル変換モジュールを購入し,8pinoの#0・#4 pinをそれぞれRX・TXに設定してみましたが,どうにもモニタできませんでした.オシロスコープで確認したところ,信号はきちんと出てるようなので,おそらくシリアル変換モジュールとPCの問題だと思います.ちなみに使用しているのはMacbook Airで,OSはYosemiteです.ドライバのインストールなどは問題無いと思います,認識もされているんですが・・・。なぜでしょうか.

仕方が無いので,Unoに8pinoのスケッチを書き込んで,シリアルモニタできちんと動いているか確認しました.まあ,Unoで動く事が確認できても8pinoで動いてるかわかんないんですが・・・.ちゃんと動きました.
TinyWireM.hをWire.hに変更しています
きちんと感染リスク(容積絶対湿度)が計算できている事が確認できました.修正したスケッチをのせておきます.変更点としては,HDC1000のRDY pinの機能を使う代わりにdelay()を使いました.これで8pinoの貴重なpin1本が節約できました.この節約できたpinにスイッチをつけたいと思います.
また,loop()のなかで温度と湿度を逐次計測するように変更しました.これできちんと動いているか,外気温度を変えたりすれば確認できます.

#include <TinyWireM.h>

//温湿度センサモジュール
#define HDC1000_ADDRESS 0x40 //温度センサモジュールのアドレス(固定)
#define HDC1000_TEMPERATURE_POINTER     0x00
#define HDC1000_CONFIGURATION_POINTER   0x02
#define HDC1000_CONFIGURE_MSB 0x10 //0x10=00010000
#define HDC1000_CONFIGURE_LSB 0x00 //0x00=00000000

int ledR = 1; //LEDの赤Anode
int ledB = 4; //LEDの青Anode
float ab_hum; //容積絶対湿度[g/m3]

void setup() { 
pinMode(ledR, OUTPUT); 
pinMode(ledB, OUTPUT);
TinyWireM.begin(); //initialize I2C bus
delay(15); //HDC1000は電源on後15msec程度の待ち時間が必要
configure(); //HDC1000の初期設定
delay(10);

getTempAndHumid(&ab_hum);
}

void loop() {
  if(ab_hum < 7){
    analogWrite(ledR, 100);
    delay(2000);
  }else if(7 <= ab_hum && ab_hum < 11){
    analogWrite(ledR, 100);
    analogWrite(ledB, 150);
    delay(2000);
  }else{
    analogWrite(ledB, 100);
    delay(2000);
  }
  digitalWrite(ledR, LOW);
  digitalWrite(ledB, LOW);
  delay(1000);
  getTempAndHumid(&ab_hum);
}

void configure(){ //Setup the HDC1000
  TinyWireM.beginTransmission(HDC1000_ADDRESS);
  TinyWireM.send(HDC1000_CONFIGURATION_POINTER); //pointerを指定した後
  TinyWireM.send(HDC1000_CONFIGURE_MSB);         //2byte(つまり8bit 8bit)のデータを送信している
  TinyWireM.send(HDC1000_CONFIGURE_LSB);         //この場合 00010000 00000000 従って12bit目が1にセットされた。
  TinyWireM.endTransmission();                   //12bit目が1だと温度湿度の順に32bitデータを送信するモードになる
}                                                //詳細はHDC1000のデータシートを参照

void getTempAndHumid(float *ab_hum){ //気温と相対湿度から容積絶対湿度を求める
  float tem, hum; //temparature[deg], humidity(相対湿度)[%]
  float sp_hum, p, wp, roh;
  int tempData, humidData;
  
  TinyWireM.beginTransmission(HDC1000_ADDRESS);
  TinyWireM.send(HDC1000_TEMPERATURE_POINTER);
  TinyWireM.endTransmission();
  delay(500);
  TinyWireM.requestFrom(HDC1000_ADDRESS, 4);
  while(TinyWireM.available() < 4){            //温度湿度それぞれ2byteのデータが送られてくる;
    ;
  }
  tempData = TinyWireM.receive() << 8;
  tempData |= TinyWireM.receive();
  humidData = TinyWireM.receive() << 8;
  humidData |= TinyWireM.receive();
  
  tem = tempData / 65536.0 * 165.0 - 40.0; //温度と湿度に変換
  hum = abs(humidData / 65536.0 * 100.0); //なぜか湿度が負になることがある
  
  //容積絶対湿度[g/m3]の計算
  p = 6.1078 * pow(10, (7.5 * tem) / (237.3 + tem)); //飽和水蒸気圧[hPa] Tetens equation
  wp = p * hum / 100; //水蒸気圧[hPa]
  sp_hum = 622 * wp / (1013.25 - wp); //重量絶対湿度[g/kg] 大気圧を1013.25hPaとした
  roh = 1.293 * 1 / (1 + tem / 273.15) * (1 - 0.378 * wp / 1013.25); //空気の密度[kg/m3]
  *ab_hum = sp_hum * roh; //容積絶対湿度[g/m3]
}


(右)リスクが低い,つまり温度や湿度が高いと青色に光ります
(左)逆にリスクが高くなると赤色っぽくなります
次回はスイッチを組み込みたいと思います.

Parts Lists

USBシリアル変換モジュール: http://akizukidenshi.com/catalog/g/gM-08461/

Reference


Note
なぜかHDC1000から送られてくる湿度が負を示す事があります.どうやらある値より大きな湿度の時にそうなるようです.絶対値は正しいようなので,とりあえずabs()で対応しています.なぜ負になるのか理由はまだわかりません.

0 件のコメント:

コメントを投稿