空間的な温度を測定する

MEMS非接触温度センサ D6T

静止人物も検出できる
高感度な人感センサを実現
ここでは「形D6T-44L-06」を用います。
これは4×4の空間の16点の温度を測定できるセンサーです。


信号は下図のようになります。

D6T.h
#include "mbed.h"
// MEMS非接触温度センサテスト

class D6T : public I2C
{
private:
  unsigned char addr;
  char buffer[36];
  int *dataBuffer;
  int length;
public:
  D6T();
  D6T(PinName data, PinName clock, int* databuff);
  void read();
};
 1 
 2 
 3 
 4 I2Cクラスから派生させる
 5 
 6 
 7 I2Cアドレス
 8 内部バッファ
 9 応答バッファアドレス
10 バッファの長さ
11 
12 コンストラクタ
13 引数付きコンストラクタ
14 データ読み込み
15 


D6T.cpp
#include "D6T.h"
// MEMS非接触温度センサテストテスト

D6T::D6T():I2C(p9,p10)
{
  addr = 0x14;
}

D6T::D6T(PinName data, PinName clock,int *databuff):I2C(data, clock)
{
  addr = 0x14;
  length = 35;
  buffer[length]=0;
  dataBuffer = databuff;
}

void D6T::read()
{
  start();
  ((I2C*)this)->write(addr);  //write
  ((I2C*)this)->write(0x4c);
  ((I2C*)this)->read(addr|1, buffer, length );  // read
  stop();
  for(int i=0; i<16; i++) {
    dataBuffer[i] = buffer[(i+1)*2] + buffer[(i+1)*2+1]*256;
  }
}
 1 
 2 
 3 
 4 デフォールトコンストラクタ
 5 
 6 
 7 
 8 
 9 引数付きコンストラクタ
10 
11 
12 
13 最終データを0とする
14 データアドレスの先頭
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 なまデータを整数型の数字に変換
25 
26 
27


main.cpp
#include "mbed.h"
#include "D6T.h"
#include "NokiaLCD.h"
// mosi, sclk, cs, rst, type
NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::PCF8833);

int main()
{
  int data[16];
  //         sda, scl
  D6T sensor(p28, p27, data);
  lcd.background(0x000000);
  lcd.cls();
  float dt;
  float p3=M_PI/3.0;
  while(true)
  {
    sensor.read();
    for(int i=0; i<4; i++) {
      for(int j=0; j<4; j++) {
        dt = (data[i*4+j]-256)*3.0;
        float t=dt/256*M_PI;
        int B=127*(cos(t)+1);
        int G=256*((int)(127*(cos(t-M_PI/2)+1)));
        int R=256*256*((int)(127*(cos(t+M_PI)+1)));
        int m = R+G+B;
        lcd.fill(j*32, i*32, 32, 32, m);
      }
    }
    wait_ms(1);
  }
}
 1 
 2 
 3 
 4 
 5 カラーLCD
 6 
 7 
 8 
 9 
10 
11 p28にsda、p27にsclを繋ぐ
12 
13 
14 
15 
16 
17 
18 計測する
19 カラーで表示させる計算
20 
21 
22 
23 
24 
25 
26 
27 表示
28 
29
30 1ミリ秒wait
31
32

同じアドレスの2つのセンサーから計測
同じアドレスの2つのセンサーから計測してみます。常識的にI2Cでは同じアドレスの装置をアクセスすることはできません。ここではdataラインをアナログスイッチを用いて切り替えてそれを可能にしてみます。sw1とsw2はTC74HC139(4-Line Decoder)に接続し、アナログスイッチ(TC74HC4066)をコントロールする信号です。が、TC74HC4066のコントロール入力はアクティブハイで、TC74HC139はアクティブロウなので、TC74HC04AF(インバーター)を用いて接続する必要があります。

ピン配置
アナログスイッチTC74HC4066AF TC74HC139 TC74HC04

2つのセンサーの場合の例は以下のようになります。4つにするには139,04,4066の残りを同じように用いればできます。



139はさらに半分しか使っていないので、うまくやるとセンサーは8個まで使えるかもしれません。
以下のプログラムはセンサーが4つの場合です。

4つのD6Tで計測する main.cpp
#include "mbed.h"
#include "D6T.h"
#include "NokiaLCD.h"
Serial pc(USBTX, USBRX); // tx, rx
NokiaLCD lcd(p5, p7, p8, p9, NokiaLCD::PCF8833); // mosi, sclk, cs, rst, type
DigitalOut sw1(p29);
DigitalOut sw2(p30);

int main()
{
  int data[16];
  int sw=0;
  //         sda, scl
  D6T sensor(p28, p27, data);
  lcd.background(0x000000);
  lcd.cls();
  float dt;
  float p3=M_PI/3.0;
  while(true)
  {
    sensor.read();
    for(int i=0; i<4; i++) {
      for(int j=0; j<4; j++) {
        dt = (data[i*4+j]-256)*3.0;
        float t=dt/256*M_PI;
        int B=127*(cos(t)+1);
        int G=256*((int)(127*(cos(t-M_PI/2)+1)));
        int R=256*256*((int)(127*(cos(t+M_PI)+1)));
        int m = R+G+B;
        switch(sw)
        {
          case 0: lcd.fill(j*16, i*16, 16, 16, m);
                  break;
          case 1: lcd.fill(j*16, i*16+64, 16, 16, m);
                  break;
          case 2: lcd.fill(j*16+64, i*16, 16, 16, m);
                  break;
          case 3: lcd.fill(j*16+64, i*16+64, 16, 16, m);
                  break;
        }
      }
    }
    if(sw++ == 3) sw=0;
    switch(sw)
    {
      case 0: sw1=0;sw2=0;break;
      case 1: sw1=1;sw2=0;break;
      case 2: sw1=0;sw2=1;break;
      case 3: sw1=1;sw2=1;break;
    }
    wait_us(100);
  }
}
 1 
 2 
 3 
 4 
 5 
 6 センサー選択
 7 センサー選択
 8 
 9 
10 
11 
12 ゼロ番センサーからスタート
13 
14 sdaはp28、sclはp27に接続
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 センサーにより表示位置を変更
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 先頭に戻る
44 次のセンサーを選択する
45 
46 
47 
48 
49 
50 
51 
52 
53 


4つのセンサーからの温度の表示例


2つの場合