(2020.3.1 作成)
このページではMAXIM社の環境光センサMAX44009について紹介したいと思います。ただ本記事執筆時点でMAXIM社のサイトを見ると新規購入不可なので生産が終了しているかもしれません。
光量を観測するセンサはCdSやフォトダイオードなどいくつかあるのですが、環境光センサを使うメリットには以下のようなものがあると思います。
などなど。ということで周囲の明るさを知るだけであれば環境光センサを使うというのも一つの手だと思います。明るいか暗いかだけならCdSでもいいですけどね。
さてここで紹介していている写真のモジュールはGY-49というモジュールのようです。Aliexpressで150円強で購入することができます。
GY-49の回路図を探してみると
ここにArduinoで使用する場合の解説と併せて回路図の記載があります。ただ、少し怪しそうだったので頑張って自分で回路図を起こしてみました。クリックで拡大します。
センサ(MAX44009)の入力電圧は3.6Vまでですが、電源ICとしてTorexのXC6206が使用されているため最大6Vまで入力することができます。またI2CのラインにもFETを用いたレベルシフタが実装されているので、5V系マイコン、3.3V系マイコンのどちらも直接接続することができます。プルアップ抵抗もついていますので、I2Cラインに直接つなげることができます。
一つ面倒な点として、このセンサはA0ピンを使用することで2種類のI2Cアドレスを使用することができるのですが、これは基板上のはんだジャンパを使用してどちらかにつなげる必要があります。
ソフトは単にI2Cで計測データを読むだけ。と言いたいところですが、実際は少々面倒です。というのはこのセンサの出力は16bit=2Byteなのですが、この2バイトを読む間にI2Cのストップ条件を入れてはいけません。また自動でアドレスのインクリメントを行うことができません。
どういうことかと言うと通常I2Cでセンサのデータを読む際は2バイト連続して読み込む、または1バイトずつ読み込む、という動作を行うのですが前者の場合はインクリメントされないので不可、後者の場合は間にストップ条件が入るので不可となります。(Arduino用ライブラリではこのことが考慮されていないものもありそうです。)
このため測定データの読み込みは右図のような特殊なフローで読みだす必要があります。これはマイコンの種類によっては大変です。
例えばSTM32F103の場合、I2Cペリフェラルには2個のバッファがあるため1バイトだけ読もうとすると読み込みコマンドの前でストップ条件を設定しないといけません。しかしこのICの場合は1バイト読んだ後でスタート条件を生成しなければならないのでちょっと面倒です。頑張ればできるのかもしれませんが、、、、
STM32F1を使用した場合はペリフェラルを用いた通信は面倒ですが、ソフトウエアI2Cで対応することができます。以下に使用したサンプルコードと結果を示します。
センサを使用するために使用したクラスは以下からダウンロードしていただけます。
また、I2Cなどの汎用クラスはここからダウンロードしていただけます。
#define USE_SW_I2C #include "DKS_Common_F103xB.h" #include "DKS_F103C8T6.h" #include "DKS_I2C_F103xB.h" #include "DKS_MAX44009.h" #ifdef USE_SW_I2C #include "DKS_GPIO_F103xB.h" #include "DKS_Timer_F103xB.h" #endif DKS::STM32F103C8T6 board(DKS::BlackPill); #ifdef USE_SW_I2C DKS::I2C::SoftwareI2C i2c; DKS::DigitalOut scl, sda; DKS::Wait w; #else DKS::I2C::I2C i2c; #endif DKS::Illuminometer::MAX44009 max(0); float illuminance; int main(void) { DKS::InitSystem(); board.Init(); #ifdef USE_SW_I2C scl.Init(GPIOB, LL_GPIO_PIN_6); sda.Init(GPIOB, LL_GPIO_PIN_7); w.Init(TIM3); i2c.Init(&scl, &sda, &w); #else i2c.Init(I2C1, 0, 0); // SCL:PB6, SDA:PB7 #endif max.Init(&i2c); uint16_t ill; for (;;) { ill = max.Get(); illuminance = max.Convert2Illuminance(ill); }; }
以下は上記のコードを使用して動かした際の写真類です。一番左がテスト写真、中央がその際の通信のログ、右側が測定結果をSTMstudioでグラフ化したものです。ログを見ていただくと仕様書通りの動作を行っていることが分かります。
ちなみに右の画像がSTM32F1のI2Cペリフェラルを使用した場合です。受信が1バイトで止まらずに複数バイト読まれており期待した動作をしていません。
センサ自体は小さく、消費電力も小さいので良いとは思います。MAXIMで生産終了ということはもう少し使いやすいセンサになって後継品が出るのかな?と思いますが、どうでしょう?