BH1750: ambient light in lux over I2C
The BH1750 is a ROHM light sensor that reports illuminance directly in lux, the unit light meters and building codes use, rather than the bare voltage an LDR gives. It sits on small GY-302 boards, talks I2C and covers 1 to 65535 lux, from a dim room to bright daylight. Christopher Laws鈥檚 BH1750 library is the usual driver.
Built in on Mokxi: #include <BH1750.h> and it builds, with nothing to install. Free, and no account needed.
What BH1750 does
The chip has measurement modes that trade speed for resolution. Continuous high resolution, the default, gives 1 lux steps every 120 ms; the high resolution 2 mode halves the step to 0.5 lux; the low resolution mode is 4 lux steps but only 16 ms. The one-time modes measure once and power down, which suits a battery sensor.
The ADDR pin picks the address: left floating or tied to ground it is 0x23, tied to VCC it is 0x5C. That gives you two sensors on one bus, for example one facing the sky and one facing a window.
| Library Manager name | BH1750 |
|---|---|
| Author | Christopher Laws |
| Include | #include <BH1750.h> |
| Boards | every board Mokxi compiles for but ATtiny85 |
| In the simulator | Simulated: it runs against the part the way it does on the bench. |
| Parts it drives | Light sensor, BH1750 |
Install it
It builds on every board Mokxi compiles for but ATtiny85.
In Mokxi it is built in: #include <BH1750.h> and the sketch compiles, with no download, no zip and no Library Manager.
On a real board, install "BH1750" by Christopher Laws from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add BH1750 to lib_deps in PlatformIO. Mokxi follows the calls of release 1.3.0, so a sketch written here builds there too.
ESP32-C3 路 Arduino Uno 路 Arduino Nano 路 Arduino Mega 2560 路 Arduino Leonardo 路 SparkFun Pro Micro 路 Arduino Micro 路 ESP32-C6 路 Raspberry Pi Pico 路 Raspberry Pi Pico W 路 Seeed XIAO SAMD21 路 STM32 路 STM32 Nucleo-F411RE 路 STM32 Blue Pill 路 micro:bit V2 路 Arduino Uno R4 路 ESP32 DevKit 路 ESP32-S3-DevKitC-1 路 ESP8266 NodeMCU 路 Arduino Pro Mini 3.3 V 路 Seeed XIAO ESP32-C3 路 ESP32-C3 SuperMini 路 Seeed XIAO ESP32-C6 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32 路 Arduino Nano RP2040 Connect 路 Seeed XIAO RP2040 路 Waveshare RP2040-Zero 路 Arduino Uno R4 WiFi
The calls you will use
In the order a sketch meets them.
BH1750 lightMeter
Creates the sensor at 0x23. BH1750 lightMeter(0x5C) for a board with ADDR high.
lightMeter.begin()
Configures the sensor in continuous high resolution mode. Returns false if it does not answer. Call Wire.begin() first.
Wire.begin();
if (!lightMeter.begin()) Serial.println(F("BH1750 not found"));lightMeter.begin(BH1750::ONE_TIME_HIGH_RES_MODE)
Starts in another mode: CONTINUOUS_HIGH_RES_MODE_2, CONTINUOUS_LOW_RES_MODE or one of the ONE_TIME modes.
float lux = lightMeter.readLightLevel()
The light level in lux, or a negative value on an error.
lightMeter.measurementReady()
True when a new measurement is available, so a loop can read without waiting.
lightMeter.configure(BH1750::ONE_TIME_HIGH_RES_MODE)
Switches mode, or in a one-time mode starts the next measurement.
lightMeter.setMTreg(69)
Sets the measurement time register (31 to 254) to stretch the range or the sensitivity. 69 is the default.
Example: Lux night lamp
On the Arduino Uno R3. It runs in the browser exactly as printed.
// Lux night lamp: a BH1750 light meter on I2C, and an LED that gets brighter
// as the room gets darker.
//
// A4, A5 SDA and SCL to the BH1750 (GY-302 module, address 0x23)
// pin 9 through 220 ohm to the LED's anode; its cathode to GND
// 5V/GND the module (it has its own 3.3 V regulator and pull-ups)
//
// An LDR in a divider gives a number that depends on the resistor and the
// cell. The BH1750 gives lux: its count is the light times 1.2, so the
// library's readLightLevel() is count / 1.2 and nothing else. A classroom is
// a few hundred lux, a cloudy day outdoors a few thousand, full sun past the
// 54612 the chip can count to.
//
// # The lamp
//
// Under 20 lux the lamp is full on; over 500 it is off; in between it fades,
// in whole numbers:
//
// brightness = 255 x (500 - lux) / 480
//
// readLightLevelCentis() gives the lux in hundredths, because this board has
// no floating point to do the sum with.
#include <Wire.h>
#include <BH1750.h>
const int LAMP = 9;
const long DARK = 20;
const long BRIGHT = 500;
BH1750 lightMeter;
void setup() {
Serial.begin(115200);
Serial.println("Mokxi Arduino Uno: BH1750 lux night lamp");
Wire.begin();
if (!lightMeter.begin()) {
Serial.println("no BH1750: check SDA, SCL and power");
}
pinMode(LAMP, OUTPUT);
}
void loop() {
if (lightMeter.measurementReady()) {
long lux = lightMeter.readLightLevelCentis() / 100;
int level;
if (lux <= DARK) {
level = 255;
} else if (lux >= BRIGHT) {
level = 0;
} else {
level = (int)(255 * (BRIGHT - lux) / (BRIGHT - DARK));
}
analogWrite(LAMP, level);
Serial.print("light ");
Serial.print(lux);
Serial.print(" lx lamp ");
Serial.println(level);
}
delay(200);
}Open it in the editor, wired and ready to run 路 Lux night lamp: the project page
Common errors and how to fix them
BH1750 not found
begin() got no answer. Check SDA and SCL, the address (0x23, or 0x5C with ADDR high), and that Wire.begin() runs before it. An I2C scanner should list the address.
readLightLevel() returns -1 or -2
Negative values are the library鈥檚 error codes: the sensor did not answer, or it was read before a measurement was ready. In a one-time mode call configure() again before each read.
The reading stays the same in a one-time mode
A one-time mode measures once and sleeps. Call configure(BH1750::ONE_TIME_HIGH_RES_MODE) before each readLightLevel(), or use a continuous mode.
Projects that use BH1750
Built-in projects that include it. Each page has the full sketch and opens in the editor, already wired.
Try BH1750 without installing anything
Open the example, change the sketch, and keep your version in a free account.