(2019.10.20 作成)
このセンサですが、型番により若干仕様が異なりますので購入時には注意してください。管理人が購入したのはMLX90614ESF-BAAというものですが、このBAAのところが仕様を表しており、この場合は電圧3V-標準パッケージになっています。5VバージョンだとAAAになります。
さてこのモジュールですが、以下のような特徴があります。
となっています。また使用に際してはパッケージが均一な温度になっていることが前提となっているので近くに発熱するようなICを置かないように注意してください。
このモジュールはGY-906やHW-691と呼ばれるようですが、両者の違いはよく分かりません。回路図等もネットでは見つからないので、管理人が購入したモジュールの回路図を作成してみました。
このモジュールですが、入力部にTOREXの3.3V固定出力LDO (XC6206)が搭載されています。このLDOの最大定格は7VなのでVCCピンには5Vを入力しても良いと思われます。ただしSCL/SDAのピンの最大定格は不明なので5V系のマイコン(Arduino UNOなど)を使用する場合はレベル変換をして使用するのが良いかと思います。
MLX90614ですが、内部にEEPROMとRAMの2系統のメモリが搭載されています。EEPROMには放射率やノイズフィルタのなど設定値が書き込まれており、一方のRAMは読み取り専用で主に計測データが格納されます。この両者はメモリの番地で分かれており、EEPROMへアクセスする際は0x20を足してアクセスすることになります。
また通信はI2CをベースとしたSMBusということになっていますが、I2Cとの実際の違いは以下の2点ぐらいです。
"ぐらい"と簡単に書きましたが2のPECバイト追加をまじめに対処すると結構面倒です。
設定値をデフォルトのまま変更せず、単に放射率を1.0で固定しソフトで放射率の変更に対応し、かつノイズフィルタの設定を変更しないのであれば測定結果を読むだけなのでPECバイトを無視してしまえば済みます。多くの場合はこれで問題ないと思います。
放射率の補正を行う場合はざっくりは以下の式でいい気がします。
Tr = (To-Ta)/ε + Ta
ここでTr:変更後温度、To:変更前温度、Ta:環境温度、ε:放射率です。
ただしもう少しまじめにやるならこちらを参考にするのが良いのではないかと思います。さらにもっとまじめにやるなら輻射のスペクトルから考えないとダメな気がします。
一方設定値を変更する場合はPECを何とかして計算する必要があります。方法としては
などがあると思います。管理人は一番最後のマイコン(STM32)の機能を使うことで一応設定値の変更ができることを確認しました。
STM32F103基板を使用してMLX90164を使用してみました。放射率の変更しか試していませんが、EEPROMへの書き込みにも成功しています。
上記のグラフは青線が室温で、黒線が非接触温度計の温度です。少し時間だけ手をかざしたのですが、問題なく測れているように見えます。グラフ化についてはSTMstudioを使用しています。
MLX90164を操作するプログラムは以下からダウンロードできます。
<<Download>>
ただし、このプログラムだけでは動作できず、こちらでダウンロードする共通ライブラリと併せて使用することを前提としています。書き込み動作を行う際にはI2CについてはI2CwithPECクラスを使用してください。
しかしあまりわかりやすい書き方はしていないので、きっと誰も使い方はわからないでしょうね。。。もし興味があって頑張ってみた結果わからなければ下のフォームで連絡ください。時間があれば対応させていただきたいと思います。
使用したサンプルコードを下に示します。
#include "DKS_Common_F103xB.h" #include "DKS_F103C8T6.h" #include "DKS_I2C_F103xB.h" #include "DKS_MLX90614.h" DKS::STM32F103C8T6 board(DKS::BluePill); DKS::I2C::I2CwithPEC i2c; DKS::Thermometer::MLX90614 mlx; float tobj, ta; int main(void) { DKS::InitSystem(); board.Init(); i2c.Init(I2C1, 0, 0); // SCL:PB6, SDA:PB7 mlx.Init(&i2c); // load eeprom settings const float emissivity = mlx.GetEmissivity(); uint8_t fir, iir; mlx.GetFilter(fir,iir); // write eeprom const float emiNew = 0.9f; mlx.SetEmissivity(emiNew); uint16_t tObj, tA; for (;;) { mlx.Get(tObj, tA); tobj = mlx.Convert2Temperature(tObj); ta = mlx.Convert2Temperature(tA); }; }