« CVTとかインパネとか | トップページ | さよならトンちゃん »

2010年12月22日 (水)

Melexis MLX90614

仕事の中で趣味の電子工作をしました(^^;。

P1

Strawberry Linux 社で売っていた Melexis 社の赤外温度計(放射温度計) MLX90614 BAA を買いまして、Arduino Duemilanove 君で温度データを収集し、PC にシリアル転送してあげようという計画を立てました。

 http://strawberry-linux.com/catalog/items?code=18120

P2

用意した基板は10年ぐらい前に秋月電子で買った紙フェノール基板。ランドだけでスルーホール無し。カッターで切れ目を入れてバキッって割ってサイズを揃えます。

P3

配線完了。嘘です。ここに至るまで四苦八苦してます。キモは SDA と SCL に付けたプルアップ抵抗(47kΩ)。Arduino のコアである Atmega328 の内蔵プルアップが上手く動作していないような感じ。後でよく調べましょう(でも多分忘れるな(^^;)。

それにしても変なパターンの配線になってしまいましたが、実は…

Fig1_2

…という測定風景を「スケッチ」した絵だったりして… 趣味だからこのぐらいは遊ばないとね! う、半分は仕事だっけ(^^;。

P4

横から見るとこんな感じ。

P5

USBケーブルでPCにつなぎ、自作のアプリでシリアル(仮想シリアル)からの計測データを拾ってラベルに表示します(最初の写真参照)。

さてその Arduino のプログラム。MLX 90614 は I2C ライクな SMBus という仕様のインターフェイスを採用しています。I2C なら Arduino の Wire ライブラリで簡単にハンドリングできる筈なのですが… どうやってもダメ。ネットで i2cmaster ライブラリなんてのも探したけどダメ。結局、別のプロジェクトで使った自作の I2C ライブラリを移植して、シンクロスコープ横目にチョコチョコ修正して、ようやく動くようになりました。

でも悪いところはプルアップの処理だけだったのかも… Wire ライブラリでも動くのかも… これ以上追求する元気は無し(^^;。

因みに、自分の手のひらや顔は 32℃位、口の中が 35~36℃位、部屋の中が 25℃位、ノートPCに付け替えて外に出たら、駐車場が 8~10℃位、壁が 11℃位、晴天 45℃方向が 5℃、直上(真上)が-5.5℃でした。オモロー! Arduino Duemilanove じゃなくて Arduino Fio で組んでみるかなぁ。MLX90614 を白い猿の人形(の目?)に組み込んで、体温計にすると尾も白いですね。お猿の名前はアメデオでキマリ!(^O^

以下、一応動作するコード。

//=================================================//
//  MLX90614 IR Data Readout Program               //
//  V1 Coded by Pawpaw  2010-12-22                 //
//=================================================//

#define  TRUE      !0
#define  FALSE     0
#define  SDA       2
#define  SCL       3
#define  SADR      0
#define  TEMPADR   0x07
#define  WRITE     0
#define  READ      1
#define  ACK       TRUE
#define  NAK       FALSE

//==================//
//  初期化          //
//==================//

void setup()
{
  InitMLX90614();
  Serial.begin(9600);

  /*
  // 以下のコメント内の Default: 以降の数値は、実際にコードを実行させて得られた値です。
 
  delay(1000);
  SendHex(ReadDevice(SADR, 0x20));    // Default: 0x9993 = 39315 = 12000 = 120.00℃
  SendHex(ReadDevice(SADR, 0x21));    // Default: 0x62E3 = 25315 = -2000 = -20.00℃
  SendHex(ReadDevice(SADR, 0x22));    // Default: 0x0201
  SendHex(ReadDevice(SADR, 0x23));    // Default: 0xF71C
  SendHex(ReadDevice(SADR, 0x24));    // Default: 0xFFFF
  SendHex(ReadDevice(SADR, 0x25));    // Default: 0x9FB0
  SendHex(ReadDevice(SADR, 0x2e));    // Default: 0xBC5A
  */
}

//==========================//
//  メイン処理              //
//==========================//

void loop()
{
  float  t;

  t = (float) ReadTemp() * 0.02 - 273.15;
  Serial.println(t);
  delay(250);
}

//==========================//
//  Hex 送信              //
//==========================//

void SendHex(unsigned long d)
{
  char  s[10];
 
  sprintf(s, "%04X", d);
  Serial.println(s);
}

//==========================//
//  データ取得              //
//==========================//

unsigned long ReadTemp()
{
  return ReadDevice(SADR, TEMPADR);
}

//======================================================//
//  XLM90614 の RAM または EEPROM 上の1ワードを取得    //
//======================================================//

unsigned long ReadDevice(int sadr, int adr)
{
  int           a;
  unsigned int  h = 0;
  unsigned int  l = 0;
  unsigned int  p = 0;

  a = (sadr << 1) | WRITE;
  SendStart();
  WriteData(a);
  WriteData(adr);

  a = (sadr << 1) | READ;
  SendStart();
  WriteData(a);
  l = ReadData(NAK);
  h = ReadData(NAK);
  p = ReadData(ACK);
  SendStop();

  return (((unsigned long) h) << 8) | ((unsigned long) l);
}

//==============================//
// Init MLX90614  //
//==============================//

void InitMLX90614()
{
  pinMode(SDA, OUTPUT);
  pinMode(SCL, OUTPUT);
  SCLon();
  SDAon();
}

//==============================//
// I2C Send start  //
//==============================//

void SendStart()
{
  SCLon();                // Readの際にはSCL=0になっているため
  SDAon();                //  この2行の処理が必要
  SDAoff();
  SCLoff();
  delayMicroseconds(10);  // シンクロで見やすいように入れた
                          // 無くても動作
}

//==============================//
// I2C Send stop  //
//==============================//

void SendStop()
{
  SCLon();
  SDAon();
}

//==============================//
// I2C Write data  //
//==============================//

void WriteData(unsigned int c)
{
  int  i;

  for (i=0; i<8; i++) {
    if (c & 0x80) {
      SDAon();
    }
    else {
      SDAoff();
    }
    SCLon();
    SCLoff();
    c <<= 1;
  }
  SDAon();
  SetSDAin();
  SCLon();
  SCLoff();     // Receive ACK
  SetSDAout();
}

//==============================//
// I2C Read data  //
//==============================//

unsigned int ReadData(int f)
{
  unsigned int   c;
  int            i;

  c = 0;
  SetSDAin();
  for (i=0; i<8; i++) {
    SCLon();
    if (digitalRead(SDA)) {
      c |= 0x01;
    }
    else {
      c &= 0xfe;
    }
    SCLoff();
    if (i != 7) {    // 最後はシフトしない
      c <<= 1;
    }
  }
  SetSDAout();
  if (f) {
    SDAon();         // ACK = 1
  }
  else {
    SDAoff();        // ACK = 0
  }
  SCLon();
  SCLoff();

  return c;
}

//==============================//
// I2C SCL & SDA control //
//==============================//

void SetSDAout() { pinMode(SDA, OUTPUT);    } // SDA を出力に設定
void SetSDAin()  { pinMode(SDA, INPUT);     } // SDA を入力に設定
void SCLon()     { digitalWrite(SCL, HIGH); }
void SCLoff()    { digitalWrite(SCL, LOW);  }
void SDAon()     { digitalWrite(SDA, HIGH); }
void SDAoff()    { digitalWrite(SDA, LOW);  }

|

« CVTとかインパネとか | トップページ | さよならトンちゃん »

コメント

コメントを書く



(ウェブ上には掲載しません)




« CVTとかインパネとか | トップページ | さよならトンちゃん »