BH1750。 I2Cバスを備えた環境光センサー。
BH1750 は、適度に高い解像度と感度を備えた環境光センサーです。 可視光に対しては人間の目の場合と同様に動作し、赤外線の影響を受けず、照明の種類の色温度にも依存しません。つまり、自然光や照明の色温度に依存しません。さまざまな種類の人工照明。 マイクロコントローラーとデジタル通信します。 I2Cバス, そのため、それを読み取る回路から一定の距離を置いて配置すると干渉に耐性があります。 応答時間は非常に短く、最も不利な状況でも 200 ミリ秒未満です。
電子的な観点から見ると、その実装は非常に簡単です。 電源 (2,4 V ~ 3,6 V) と I2Cバス。 オプションで、バス アドレスを変更して 0 つのデバイス (ADDR が低レベルの場合は 0100011B0 または 23x0、ADDR が高レベルの場合は 1011100B0 または 5xXNUMXC) を接続するように変更でき、VDI ラインをリセット機能に使用できます。マイクロコントローラー。
BH1750を接続するには Arduinoの、3,3 V 出力で動作することに加えて、最も正しいことは、XNUMX V 出力に加えてレベルコンバータを使用することです。 プルアップ抵抗 のために I2Cバス。 このコンポーネントはバスへの直接接続をサポートしますが、 I2Cバス レベル変換を考慮せずに回路のサイズを決定することはお勧めできません。
精度の割に非常に安価なことから人気があり、冒頭の写真にある有名なGY-30など、いくつかのモジュールが存在します。 マイクロコントローラーでプロトタイプを作成するときにより快適に接続するために、通常、マイクロコントローラー用のレベルコンバーターが含まれています。 I2Cバス および電圧レギュレータを使用して、5V 出力の代わりにより高い電圧 (最大 3,3V) で電力を供給します。 Arduinoの.
BH1750 には、連続と個別の 1750 つの読み取りモードがあり、アクティブと低電力またはスリープの 180 つの状態に対応します。 連続読み取りモードが使用されている場合、BH16 はサンプリング後もアクティブなままですが、個別の測定を実行した後、自動的にスリープおよび低電力モードに入ります。 連続モードでの最初の読み取りには最大 120 ミリ秒かかり、その後の読み取りには解像度に応じて XNUMX ミリ秒から XNUMX ミリ秒かかります。
センサーは4ルクス、1ルクス、0,5ルクスの間隔(分解能)で測定できます。 BH1750 はデータシートで 1 ルクスの分解能を使用することを推奨しています。これにより、10 ルクス未満の照度 (夕暮れの光に相当します) を区別できるようになり、測定に影響を与える可能性のあるノイズの影響を受けにくくなります。
1 ルクスと 4 ルクスの分解能は、整数部分を表すために 16 ビットのデータを使用するため、最大 65535 ルクスの測定値を達成できます (直射光のない晴れた日)。 0,5 ルクス モードでは、小数部分の最下位ビット (0,5 ルクスから 0,5 ルクスまで測定) が使用されるため、残りの 15 ビットで最大値 32767 ルクス (直射光のない屋外) を表すことができます。
通常、周囲光の測定に使用される光学窓は可視スペクトル全体に対応しており、その目的は人間の感度分布に匹敵する感度分布を達成することです。 光学窓が小さくなった場合(光がより低い波長範囲で測定される場合)、時間読み取り値を増やすことによって光学窓の影響の調整をキャンセルするモードにより、BH1750 の感度を高めることができます(最大 0,11 ルクス)。比例して。 この特別な(特大)モードでは個別の読み取りが行われるため、特に測定条件を変更することなく状況がこれを許可する必要があります(たとえば、センサーは非常に安定した状態を維持する必要があり、照明条件が異なる領域に移動してはなりません)。
BH1750 オペレーションコード
Estado
5>
-
0B00000000
(0x00
) 低電力モードまたはアイドル モード。 -
0B00000001
(0x01
) スイッチオン。 -
0B00000111
(0x07
) リセットします。 BH1750のデータログをクリアします。
分解能
5>
-
0B00010011
(0x13
) 4 ルクス分解能での連続測定 (16 ミリ秒から読み取り時間の間) -
0B00010000
(0x10
) 1ルクス分解能での連続測定(読み取り時間120ms) -
0B00010001
(0x11
) 0,5ルクス分解能での連続測定(読み取り時間120ms) -
0B00100011
(0x23
) 4 ルクスの分解能での測定 (16 ミリ秒の読み取り時間) -
0B00100000
(0x20
) 1 ルクスの分解能での測定 (120 ミリ秒の読み取り時間) -
0B00100001
(0x21
) 0,5 ルクスの分解能での測定 (120 ミリ秒の読み取り時間)
光学窓の変更調整
5>
-
0B011MT
[0,1,2,3,4] MTREG (Measurement Time REGister) レジスタの下位ビット。 -
0B01000MT
[5,6,7] MTREG レジスタの上位ビット。
ArduinoからBH1750を読み取る
BH1750 を使用して周囲の照明を測定するには Arduinoの 図書館が使われている ワイヤー との通信を管理する I2Cバス。 このプロセスは、このタイプの通信では通常のもので、最初に (プログラム内で) 次のようにアクティブ化されます。 Wire.begin()
、BH1750との通信が始まります。 Wire.beginTransmission()
そしてあなたの住所 I2C (ADDR がハイかローかに応じてそれぞれ 0x5C または 0x23)、対応するコードを次のように送信することで設定されます。 Wire.write()
そしてバスは解放されます Wire.endTransmission()
15
|
Wire.begin();
|
17
18
19
|
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.write(MEDIDA_CONTINUA_UN_LUX_BH1750);
Wire.endTransmission();
|
連続読み取りモードのいずれかが使用されている場合は、Wire.beginTransmission() を使用してアドレス付きのデータを取得します。 I2C BH1750 へのアクセスに対応し、16 バイトが要求されます (解像度は XNUMX ビット)。 Wire.requestFrom()
を使用して読み取られる Wire.read()
、最初のバイトを 8 ビットずつ回転させて、符号なし整数にロードされます。 その後、バスは次のように解放されます。 Wire.endTransmission()
。 最終結果は、戻り値を精度係数 (光学ウィンドウが変更されない場合は 1,2) で割ることによって得られます。
28
29
|
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.requestFrom(DIRECCION_BH1750_0,2);
|
37
38
|
lectura_BH1750=Wire.read()<<8; // Leer el primer byte y rotarlo 8 bits
lectura_BH1750|=Wire.read(); // Leer el segundo byte y «juntarlo» con el anterior on OR
|
40
|
iluminacion=long(100.0*(float)lectura_BH1750/DIVISOR_PRECISION)/100; // Resultado corregido y sin decimales
|
個別読み取りモードが使用されている場合、BH1750 はスリープ モードに入りますが、アクティブ モードに戻るには、設定 (同じ読み取りモードまたは新しい読み取りモード) またはパワーオン コード (0x01) を送信できます。 シャットダウン コード (1750x0) を使用して、BH00 を強制的にスリープ モードにできます。
センサーの読み取り時間を尊重することが重要です。これは解像度によって異なります。 待機時間が重要でない場合は、すべてのケースで、読み取りが確実に完了するように、予想される最大値よりわずかに大きい値に統一できます。
BH1750 のコードをより快適に作成するには Arduinoの、最も関連するオペレーション コードは、次のヘッダー ドキュメントにあります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#define REPOSAR_BH1750 0x00 // Modo de reposo o bajo consumo
#define ENCENDER_BH1750 0x01
#define RESETEAR_BH1750 0x07
#define MEDIDA_CONTINUA_CUATRO_LUX_BH1750 0x13
#define MEDIDA_CONTINUA_UN_LUX_BH1750 0x10
#define MEDIDA_CONTINUA_MEDIO_LUX_BH1750 0x11
#define MEDIDA_SIMPLE_CUATRO_LUX_BH1750 0x23
#define MEDIDA_SIMPLE_UN_LUX_BH1750 0x20
#define MEDIDA_SIMPLE_MEDIO_LUX_BH1750 0x21
#define ESPERA_BH1750_0 250 // 250 milisegundos de espera de lectura del BH1750 (mayor que la máxima)
#define TIMEOUT_I2C 10 // 10 milisegundos de espera antes de renunciar a leer el bus I2C
#define DIVISOR_PRECISION 1.2 // valor por el que dividir la lectura para calcular la luminosidad 1.2 si no hay cambios en la ventana óptica
#define DIRECCION_BH1750_0 0x23
#define DIRECCION_BH1750_1 0x5C
|
次のコード例は、光センサーの最も一般的な読み取りモードを示しています。 I2C BH1750。 解像度は 1 ルクスで、読み取りモードは連続です。 この例では、シリアル コンソールを使用して、 Arduinoの、測定値から得られた各結果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
|
#include “BH1750.h” // Cargar los códigos de operación del BH1750
#include <Wire.h>
unsigned int lectura_BH1750;
unsigned int iluminacion;
//float iluminacion; // Mostrar el valor con decimales
long cronometro_lecturas=0;
long tiempo_transcurrido;
long cronometro_timeout_i2c;
void setup()
{
Serial.begin(9600);
Wire.begin();
delay(ESPERA_BH1750_0); // Espera inicial para estabilizar el BH1750
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.write(MEDIDA_CONTINUA_UN_LUX_BH1750);
Wire.endTransmission();
}
void loop()
{
tiempo_transcurrido=millis()–cronometro_lecturas;
if(tiempo_transcurrido>ESPERA_BH1750_0)
{
cronometro_lecturas=millis();
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.requestFrom(DIRECCION_BH1750_0,2);
do
{
tiempo_transcurrido=millis()–cronometro_timeout_i2c;
}
while(Wire.available()<2&&tiempo_transcurrido<TIMEOUT_I2C);
if(Wire.available()>1)
{
lectura_BH1750=Wire.read()<<8; // Leer el primer byte y rotarlo 8 bits
lectura_BH1750|=Wire.read(); // Leer el segundo byte y «juntarlo» con el anterior on OR
//iluminacion=lectura_BH1750/DIVISOR_PRECISION; // Resultado corregido y con decimales (mínimamente más preciso pero menos legible)
iluminacion=long(100.0*(float)lectura_BH1750/DIVISOR_PRECISION)/100; // Resultado corregido y sin decimales
Serial.print(“La iluminación es de “);
Serial.print(iluminacion);
Serial.println(” lux”);
}
}
}
|
上で述べたように、1 ルクスと 4 ルクスの解像度モードは両方とも、16 ビットのデータを使用して測定値を整数として表します。 一方、0,5 ルクス モードでは、最後のビットは小数部分を表します。つまり、合計測定値に寄与する値が 1 のべき乗で右にシフトされます。 4 ルクスまたは XNUMX ルクス モードでは、最後のビット (LSB) は 2 の価値があります0、最後から2番目のXNUMX1、次の22…0,5ルクスモードでは最後のビット(LSB) は 2 の価値があります-1、最後から2番目のXNUMX0、次の21...
このデータ構造に従って、XNUMX 回の読み取りを実行する必要があることを考慮すると、 I2C 16 バイトの場合、8 ビット値を取得するには、バイトの最上位ビット、つまり最初に読み取られるビットをロードし、1 ルクス解像度モードと 4 ルクス解像度モードでそれらを左に 7 ビット回転する必要があります。 0,5ルクスではわずか0,5ビットです。 8 ルクス モードでの読み取り方法を統一するには、最上位バイトを符号なし整数にロードし、1 ビット左に回転し、最下位バイトをロードして、符号なし整数全体を XNUMX ビット左に回転します。を示す小数部の値 LSB (最下位ビット) 後で適用するため。
論理的に、1 ルクスまたは 4 ルクス モードの場合は、符号なし整数を使用する必要があります (unsigned int
) 何のために Arduinoの 予約しないでください MSB (最上位ビット) 符号を指定し、負の数ではなく測定値の真の値を直接操作できるようになります。 で Arduino の期限 整数は32ビットを使用するため必要ありませんが、同様に使用しても同じプログラムが動作します。 unsigned int
.
次のコードは、0,5 ルクス モードがどのように使用されるかを示しています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
|
#include “BH1750.h” // Cargar los códigos de operación del BH1750
#include <Wire.h>
unsigned int lectura_BH1750;
//unsigned int iluminacion;
float iluminacion; // Mostrar el valor con decimales
long cronometro_lecturas=0;
long tiempo_transcurrido;
long cronometro_timeout_i2c;
bool parte_decimal;
void setup()
{
Serial.begin(9600);
Wire.begin();
delay(ESPERA_BH1750_0); // Espera inicial para estabilizar el BH1750
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.write(MEDIDA_CONTINUA_MEDIO_LUX_BH1750);
Wire.endTransmission();
}
void loop()
{
tiempo_transcurrido=millis()–cronometro_lecturas;
if(tiempo_transcurrido>ESPERA_BH1750_0)
{
cronometro_lecturas=millis();
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.requestFrom(DIRECCION_BH1750_0,2);
do
{
tiempo_transcurrido=millis()–cronometro_timeout_i2c;
}
while(Wire.available()<2&&tiempo_transcurrido<TIMEOUT_I2C);
if(Wire.available()>1)
{
lectura_BH1750=Wire.read()<<8; // Leer el primer byte y rotarlo 8 bits
lectura_BH1750|=Wire.read(); // Leer el segundo byte y «juntarlo» con el anterior on OR
parte_decimal=(lectura_BH1750<<15)>0;
lectura_BH1750>>=1;
iluminacion=((float)lectura_BH1750+(parte_decimal?0.5:0.0))/DIVISOR_PRECISION;
Serial.print(“La iluminación es de “);
Serial.print(iluminacion);
Serial.println(” lux”);
}
}
}
|
BH1750センサーとArduinoを使用した周囲光の測定例のドキュメントをダウンロード.
コメントを投稿