Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

BH1750 light sensor with Wemos D1 mini — dusk switch in lux

Wire a BH1750 (GY-302) to a Wemos D1 mini on D1/D2, read light in lux and switch the built-in LED on at dusk with hysteresis so it never flickers.

Arduino C++Verified — core esp8266 3.1.2, BH1750 1.3.0, 3 Nov 2026Compile-only

Community draft — report a mistake

The BH1750 measures light in lux over I2C, which makes it a far better dusk sensor than an LDR — and it doesn’t use the D1 mini’s single analog pin. Wire it to D1 (SCL) and D2 (SDA) at 3V3.

The sketch is a complete dusk-to-dawn switch with hysteresis, using the built-in LED as the “lamp” so you can test it on the desk. Replace the LED with a relay output for a balcony or gate light.

Wiring

Wemos D1 miniOnly the pins used are shown · 3.3 V logicBH1750 lux sensor (GY-302)3V3D1D2GNDVCCGNDSCLSDAADDR (not connected)
Every connection
Wemos D1 miniBH1750 lux sensor (GY-302)WireNotes
3V3VCCred
GNDGNDblack
D1SCLyellowD1 = GPIO5, default SCL.
D2SDAblueD2 = GPIO4, default SDA.

3–5 V (on-board regulator) part, 3.3 V board. The GY-302 has a 3.3 V regulator and accepts 3–5 V on VCC; its pull-ups suit both 3.3 V and 5 V boards.

Board quirks

  • ADDR is left open, which gives address 0x23. Tie ADDR to 3V3 for 0x5C if you want two BH1750s on the same D1/D2 bus.
  • Unlike an LDR on A0, the BH1750 gives real lux over I2C — and it leaves the D1 mini’s one analog input free for something else.
  • The switch uses two thresholds (on below 20 lx, off above 50 lx). With one threshold, a lamp switching on at dusk lights the sensor and turns itself off again, over and over.
  • The built-in LED is on D4 (GPIO2) and lights when the pin is LOW. Replace it with a relay on D5 or D6 for a real lamp — not on D4, which must be high at boot.
  • Mount the sensor facing the sky and away from the lamp it controls; under a monsoon cloud the sky can drop below 50 lx at midday, so pick thresholds by watching the serial output for a few days.

Code

bh1750-d1mini.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// BH1750 (GY-302) light sensor on a Wemos D1 mini (ESP8266): a dusk switch with hysteresis.
// VCC → 3V3, GND → GND, SCL → D1 (GPIO5), SDA → D2 (GPIO4); ADDR open (= 0x23).
// The built-in LED on D4 stands in for a light: on below DARK_LUX, off above BRIGHT_LUX.
#include <Wire.h>
#include <BH1750.h>

BH1750 lightMeter(0x23);
const float DARK_LUX = 20;     // switch on below this
const float BRIGHT_LUX = 50;   // switch off above this - the gap stops flicker at dusk
const uint8_t LED_PIN = LED_BUILTIN;  // D4 / GPIO2, lit when LOW
bool lampOn = false;

void setup() {
  Serial.begin(115200);
  Serial.println();
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);  // off
  Wire.begin();  // SDA = D2, SCL = D1
  if (!lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
    Serial.println("BH1750 not found at 0x23 - if ADDR is tied high, use 0x5C");
    while (true) delay(100);
  }
  Serial.println("BH1750 ready");
}

void loop() {
  float lux = lightMeter.readLightLevel();
  if (lux < 0) {
    Serial.println("BH1750 read error");
  } else {
    if (!lampOn && lux < DARK_LUX) lampOn = true;
    if (lampOn && lux > BRIGHT_LUX) lampOn = false;
    digitalWrite(LED_PIN, lampOn ? LOW : HIGH);
    Serial.printf("%.1f lx  lamp %s\n", lux, lampOn ? "ON" : "off");
  }
  delay(1000);
}

Library: BH1750 (Christopher Laws) — compiled with BH1750 1.3.0.

Expected serial output

Serial Monitor · 115200Output
BH1750 ready
312.5 lx  lamp off
48.3 lx  lamp off
17.9 lx  lamp ON
35.0 lx  lamp ON

Common errors

“BH1750 not found at 0x23”

Check SDA on D2 and SCL on D1. If ADDR is tied high, the address is 0x5C. I2C scanner.

Reads 54612 lx all the time

The sensor is saturated (direct sunlight) or the I2C read failed. Shade it and check the wiring.

↑↓ to move · Enter to open