TOP > 電子部品> 環境光センサ

環境光センサ(MAX44009)

 (2020.3.1 作成)

 このページではMAXIM社の環境光センサMAX44009について紹介したいと思います。ただ本記事執筆時点でMAXIM社のサイトを見ると新規購入不可なので生産が終了しているかもしれません。

 光量を観測するセンサはCdSやフォトダイオードなどいくつかあるのですが、環境光センサを使うメリットには以下のようなものがあると思います。

  • 工場で構成されており、照度の絶対値が出る。
  • 人の目の感度特性に合わせたフィルタが組み込まれているため、人の感じる明るさを表せる。
  • I2Cなどのインターフェースまで内蔵されているため小型、お手軽かつ低消費電力。
  • 自動感度調整が入っているので暗いところから明るいところまで計測できる(0.045lux〜188,000lux)

などなど。ということで周囲の明るさを知るだけであれば環境光センサを使うというのも一つの手だと思います。明るいか暗いかだけなら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で対応することができます。以下に使用したサンプルコードと結果を示します。

センサを使用するために使用したクラスは以下からダウンロードしていただけます。

Download

また、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で生産終了ということはもう少し使いやすいセンサになって後継品が出るのかな?と思いますが、どうでしょう?

コメント: 0