MicroPython: BH1750 Ambient Light Sensor with ESP32/ESP8266

The BH1750 is a 16-bit ambient light sensor. In this tutorial, you’ll learn how to use the BH1750 ambient light sensor with the ESP32 and ESP8266 boards programmed with MicroPython firmware. You’ll learn how to wire the sensor to the ESP boards, install the required libraries, and get ambient light measurements in Lux (the standard unit for illuminance).

MicroPython BH1750 Ambient Light Sensor with ESP32 ESP8266 NodeMCU

Using Arduino IDE? Follow the next tutorials instead:

Table of Contents:

This tutorial covers the following topics:

Prerequisites

To follow this tutorial you need MicroPython firmware installed in your ESP32 or ESP8266 boards. You also need an IDE to write and upload the code to your board. We suggest using Thonny IDE or uPyCraft IDE:

Learn more about MicroPython: MicroPython Programming with ESP32 and ESP8266

Parts Required

To follow this tutorial you need the following part:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Introducing BH1750 Ambient Light Sensor

The BH1750 is a 16-bit ambient light sensor that communicates via I2C protocol. It outputs luminosity measurements in lux (SI-derived unit of illuminance). It can measure a minimum of 1 lux and a maximum of 65535 lux.

The sensor may come in different breakout board formats. See the pictures below. Both images represent a BH1750 sensor.

BH1750 Ambient Light Sensor Breakout Boards

BH1750 Features

Here’s a list of the BH1750 sensor features. For more information consult the BH1750 sensor datasheet.

  • I2C bus Interface
  • Spectral responsibility is approximately human eye response
  • Illuminance to digital converter
  • Range: 1 – 65535 lux
  • Low current by power down function
  • 50Hz / 60Hz Light noise reject-function
  • It is possible to select 2 different I2 C slave addresses
  • Small measurement variation (+/- 20%)
  • The influence of infrared is very small
  • Supports continuous measurement mode
  • Supports one-time measurement mode

Measurement Modes

The sensor supports two different measurement modes: continuous measurement mode, and one-time measurement mode. Each mode supports three different resolution modes.

Low Resolution Mode4 lux precision16 ms measurement time
High Resolution Mode1 lux precision120 ms measurement time
High Resolution Mode 20.5 lux precision 120 ms measurement time

In continuous measurement mode, the sensor continuously measures ambient light values. In one-time measurement mode, the sensor measures the ambient light value once, and then it goes to power down mode.

Applications

BH1750 Ambient Light Sensor

The BH1750 is an ambient light sensor so it can be used in a wide variety of projects. For example:

  • to detect if it is day or night;
  • to adjust or turn on/off LED’s brightness accordingly to ambient light;
  • to adjust LCDs and screen’s brightness;
  • to detect if an LED is lit;

BH1750 Pinout

BH1750 Ambient Light Sensor Pinout

Here’s the BH1750 Pinout:

VCCPowers the sensor (3.3V or 5V)
GNDCommon GND
SCLSCL pin for I2C communication
SDA (Data)SDA pin for I2C communication
ADD*Selects address

The ADD pin is used to set the I2C sensor address. If the voltage on that pin is less than 0.7VCC (pin is left floating or connected to GND), the I2C address is 0x23. But, if the voltage is higher than 0.7xVCC (pin is connected to VCC), the address is 0x5C. In summary:

  • ADD pin floating or connected to GND → address: 0x23
  • ADD pin connected to VCC → address: 0x5C

Wiring the BH1750 to the ESP32 or ESP8266

The BH1750 ambient light sensor supports I2C interface. You can connect the BH1750 sensor to the ESP32/ESP8266 using the default’s I2C pins:

BH1750ESP32ESP8266
VCC3.3V3.3V
GNDGNDGND
SCLGPIO 22GPIO 5 (D1)
SDA (Data)GPIO 21GPIO 4 (D2)
ADD*Don’t connectDon’t connect
By not connecting the ADD pin, we’re selecting 0x23 I2C address. Connect it to 3.3V to select 0x5C address instead.

You can also use the following schematic diagrams as a reference.

Schematic – ESP32 with BH1750

ESP32 BH1750 Wiring Diagram Circuit

Schematic – ESP8266 NodeMCU with BH1750

ESP8266 NodeMCU BH1750 Wiring Diagram

BH1750 MicroPython Library

To read from the BH1750 sensor, we’ll use an external library that isn’t part of the standard MicroPython library by default.

Open the following link and copy the library code to Thonny IDE:

Follow the next steps to upload the library to your ESP32 or ESP8266 board:

1) Copy the library code to a new file. The bh1750.py library code can be found here.

# forked from: https://github.com/PinkInk/upylib/tree/master/bh1750
"""
Micropython BH1750 ambient light sensor driver.
"""

from utime import sleep_ms


class BH1750():
    """Micropython BH1750 ambient light sensor driver."""

    PWR_OFF = 0x00
    PWR_ON = 0x01
    RESET = 0x07

    # modes
    CONT_LOWRES = 0x13
    CONT_HIRES_1 = 0x10
    CONT_HIRES_2 = 0x11
    ONCE_HIRES_1 = 0x20
    ONCE_HIRES_2 = 0x21
    ONCE_LOWRES = 0x23

    # default addr=0x23 if addr pin floating or pulled to ground
    # addr=0x5c if addr pin pulled high
    def __init__(self, bus, addr=0x23):
        self.bus = bus
        self.addr = addr
        self.off()
        self.reset()

    def off(self):
        """Turn sensor off."""
        self.set_mode(self.PWR_OFF)

    def on(self):
        """Turn sensor on."""
        self.set_mode(self.PWR_ON)

    def reset(self):
        """Reset sensor, turn on first if required."""
        self.on()
        self.set_mode(self.RESET)

    def set_mode(self, mode):
        """Set sensor mode."""
        self.mode = mode
        self.bus.writeto(self.addr, bytes([self.mode]))

    def luminance(self, mode):
        """Sample luminance (in lux), using specified sensor mode."""
        # continuous modes
        if mode & 0x10 and mode != self.mode:
            self.set_mode(mode)
        # one shot modes
        if mode & 0x20:
            self.set_mode(mode)
        # earlier measurements return previous reading
        sleep_ms(24 if mode in (0x13, 0x23) else 180)
        data = self.bus.readfrom(self.addr, 2)
        factor = 2.0 if mode in (0x11, 0x21) else 1.0
        return (data[0]<<8 | data[1]) / (1.2 * factor)

View raw code

BH1750 micropython library on Thonny IDE

2) Go to File > Save as…

Thonny IDE ESP32 ESP8266 MicroPython Save file library to device save as

3) Select save to “MicroPython device“:

Thonny IDE Save to MicroPython Device

4) Name your file as bh1750.py and press the OK button:

saving bh1750.py to esp32 esp8266

And that’s it. The library was uploaded to your board. To make sure that it was uploaded successfully, go to File > Save as… and select the MicroPython device. Your file should be listed there:

BH1750 file saved on the ESP32 and ESP8266 boards

After uploading the library to your board, you can use the library functionalities in your code by importing the library.

ESP32/ESP8266 – BH1750 Luminance (Lux) – Code

After uploading the library, create a new file and paste the following code. It reads the luminance in lux units and prints the readings into the Shell every two seconds.

# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/micropython-bh1750-esp32-esp8266/

from machine import Pin, SoftI2C
from bh1750 import BH1750
import time

# Initialize I2C communication (ESP32)
i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=400000)


# Initialize I2C communication (ESP8266)
#i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=400000)

# Create BH1750 object
light_sensor = BH1750(bus=i2c, addr=0x23)

try:
    # Read lux every 2 seconds
    while True:
        lux = light_sensor.luminance(BH1750.CONT_HIRES_1)
        print("Luminance: {:.2f} lux".format(lux))
        time.sleep(2)

except Exception as e:
    # Handle any exceptions during sensor reading
    print("An error occurred:", e)

View raw code

How the Code Works

We need to import the Pin and SoftI2C classes from the machine module.

from machine import Pin, SoftI2C
from bh1750 import BH1750
import time

In this case, this library needs SoftI2C instead of I2C. In MicroPython, SoftI2C refers to software I2C and I2C refers to hardware I2C.

Hardware I2C relies on dedicated hardware modules that are optimized for I2C communication. Software-based I2C, on the other hand, uses software-defined GPIO pins to emulate I2C communication.

We initialize an I2C communication on GPIOs 21 and 22 on the ESP32, or GPIOs 4 and 5 on the ESP8266. Make sure to uncomment the pins for the board you’re using.

# Initialize I2C communication (ESP32)
#i2c = SoftI2C(scl=Pin(22), sda=Pin(21), freq=400000)

# Initialize I2C communication (ESP8266)
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=400000)

Then, create a BH1750 instance, called light_sensor on the I2C bus defined previously. We’re using 0x23 I2C address. If you have a different address, change that on the following line.

light_sensor = BH1750(bus=i2c, addr=0x23)

To get luminance values, we just need to use the luminance() method on the BH1750 object and pass a measurement mode as an argument.

lux = light_sensor.luminance(BH1750.CONT_HIRES_1)

The library provides a list of measurement modes you can use. See the table below.

ConstantDescription
CONT_LOWRESContinuous, low-resolution (4lx), sampling takes ~24ms, sensor remains on after reading.
CONT_HIRES_1Continuous, high-resolution (1lx), sampling takes ~180ms, sensor remains on after reading.
CONT_HIRES_2Continuous, very high resolution (.5lx), sampling takes ~180ms, sensor remains on after reading.
ONCE_HIRES_1One-shot, low resolution (4lx), sampling takes ~24ms, sensor powered down after reading
ONCE_HIRES_2One-shot, high resolution (1lx), sampling takes ~180ms, sensor powered down after reading
ONCE_LOWRESOne-shot, very high resolution (.5lx), sampling takes ~180ms, sensor powered down after reading

Finally, we print the readings in the shell:

print("Luminance: {:.2f} lux".format(lux))

Testing the Code

Run the previous code on your ESP32 or ESP8266 board.

Testing the Code Script Thonny IDE

You should get new luminance values in lux units every two seconds.

BH1750 getting luminance values on Thonny IDE ESP32 and ESP8266

Cover the sensor or point some light to see the values changing.

ESP32 with BH1750 Ambient Light Sensor

Wrapping Up

In this tutorial, we’ve covered how to use the BH1750 ambient light sensor with the ESP32 and ESP8266 boards programmed with MicroPython.

The BH1750 sensor can be useful in a wide range of projects to detect if it is day or night, adjust an LED brightness according to ambient light, detect if an LED is lit, and much more.

We hope you’ve found this tutorial useful.

We have tutorials for other sensors with the ESP32/ESP8266 using MicroPython that you may like:

Learn more about MicroPython with our resources:

Thanks for reading.



Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.