**S Collins April 2020**
The BH1750 is a cheap and easily used sensor that has a quoted range of 1-65532 Lux, has a great specification and a linear response. While this is used extensively, in a wide range of applications and the data sheet is readily available, most use of the sensor sketches and designs fail to take into account a number of issues in configuration or reading range.
The key issues are:
• The sensor itself returns a 16-bit unsigned integer. Therefore, the maximum value is limited in general. The standard conversion between the so called ‘counts’ to lux is 1/1.2 (this can be altered), that means you get a smaller value of lux to counts of the sensor. Usually you will get an integer value which represent the lux equivalent.
o Low Resolution Mode - (generic range: 0.0 up to 54612.5 lux)
o High Resolution Mode - (generic range: 0.0 up to 54612.5 lux)
o High Resolution Mode 2 - (generic range: 0.0 up to 27306.25 lux)
• There is a calibration factor of 1.2 used for measurement accuracy in the BH1750.h software. This figure can be changed in the range of 0.96 – 1.44, and alters the measurement accuracy of the readings. And can be calibrated if a calibrated light source is available, if not leave at 1.2.
• That the outdoor range of light range is from < 1- 120,000 lux so the sensor un-covered will fully saturate in full sun at 54612 lux if not adjusted or has a cover applied. This leads to inaccuracy in the reading if not compensated for in the software at higher light levels.
• That the direction of the sensor has to be pointed directly at the light source and has a beamwidth of +/- 30° at 80% of direct reading and 40% at +/-60°.
• That a covering over the sensor will reduce the level of light received at the sensor and needs to be compensated for in the software sketch with a calibration factor that will vary with the material and thickness used. For example, in the case of a white lens such as in this sensor “BH1750FVI Chip Light Intensity Light Module Light ball” the received light in the BH1750 is only around 52 % of the actual light level when directly overhead.
In the case of a Heltec CubeCell capsule clear cover then the light received is about 90% of the expected level. It should be noted that the light received by the sensor is altered due to the lens effect of the clear capsule’s different zones and different thicknesses. For a more consistent response it would be better to use a constant thickness white cover, as is used in most light detection meters.
• The sensitivity of the sensor can be adjusted by altering the Measurement Time (MT) that is configured for the sensor. This value is not normally exposed in the example Arduino sketches. It has in inbuilt default value of “69” decimal in the MTreg (dec) in the support library. In the datasheet it has a stated range of 31 (this does not work) to 254. This give a range scaling of the range in sensitivity scaling is 0.46 to 3.68. the formula for calculating the sensitivity, form the data sheet is:
o H-resolution mode: Illuminance per 1 count (lux / count) = 1 / 1.2 *(69 / X)
o H-resolution mode2: Illuminance per 1 count (lux / count) = 1 / 1.2 *(69 / X) / 2
o Where: 1.2 is the Measurement accuracy, 69 the Default value of MTreg (dec), X : MTreg value. 32 to 254.
How to use in Sketches
In the sketches used, such as in the Heltec LoRaWAN Sensor either for BH1750 or MultiSensor then some changes are needed.
First if you are using a 2-byte message for the lux value (the most airtime efficient way) then you can only transfer 65532 different bits of information so this needs to be scaled to cover the 120K lux range. It is recommended that you use the ONE_TIME_HIGH_RES_MODE. I use a scale factor of 2.5 so can cover 65532/1.2 * 2.5 giving a maximum of 136525 lux. This need to be divided in the sketch by 2.5 and then scales up by 2.5 in the payload decoder such as in TTN.
That you need to set the MTreg in the sketch to set the sensitivity value as I want to be able to detect the large range, I use MTreg of 32 (the lowest that can be used). And give a sensitivity of 32/69 * 1/1.2 = .386 lux per count. As the 1.2 calibration factor is taken account of the BH1750.h/.cpp Library.
We need to just use a calibration factor of 69/32 only I.e. 2.156. * Calibration factor for the item being use e.g. Light Ball 52% 0.522.156 = 1.12 or Heltec CubeCell Capsule Clear dome upwards 90% 0.9 2.156 = 1.95
That in the sketch you need to correct for the covering calibration factor for your sensor and lux range I have used the following in the MultiSenor Example items added or changed in bold:
float Temperature, Humidity, Pressure, SLpressure, lux, lux_cal, co2, tvoc;
Cal = 1.13 // bases on the sensitivity of sensor for MtReg = 32 compared to 69 the default and factor for cover e.g. for the light ball
if (BH_1750_e[pnr]) // 6
pinMode(GPIO0, OUTPUT); digitalWrite(GPIO0, HIGH);
#if (ModularNode == 1)
count = 0; lightMeter.setMTreg(32);// lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE); delay(100); lux = lightMeter.readLightLevel(); delay(100); lux = lightMeter.readLightLevel(); lightMeter.end(); Wire.end(); lux_cal = ((lux/Cal)/2.5); appData[appDataSize++] = pnr; appData[appDataSize++] = 6; appData[appDataSize++] = (uint8_t)((int)(lux_cal ) >> 8); appData[appDataSize++] = (uint8_t)((int)(lux_cal )); Serial.print(" BH1750: Light = "); Serial.print(lux_cal); Serial.print ("lx "); Serial.print(lux); Serial.println("lx ");
I hope the above helps, in getting sketches that report accurate lux reading (within sensors ability) and show that the sensor out of the box (or Cube!) need to be treated, to get the correct results.
I have also written a set of notes for the Bosch presure sensors and the calibration of example files to sea-level correct pressure readings see separate post.