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).
Using Arduino IDE? Follow the next tutorials instead:
Table of Contents:
This tutorial covers the following topics:
- Introducing the BH1750 Ambient Light Sensor
- BH1750 Pinout
- Wiring the BH1750 to the ESP32 or ESP8266
- BH1750 MicroPython Library
- BH1750 Read Ambient Light with ESP32/ESP8266 (MicroPython)
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:
- Thonny IDE:
- uPyCraft IDE:
- Getting Started with uPyCraft IDE
- Install uPyCraft IDE (Windows, Mac OS X, Linux)
- Flash/Upload MicroPython Firmware to ESP32 and ESP8266
Learn more about MicroPython: MicroPython Programming with ESP32 and ESP8266
Parts Required
To follow this tutorial you need the following part:
- BH1750 ambient light sensor
- ESP32 or ESP8266
- Breadboard (optional)
- Jumper wires (optional)
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 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 Mode | 4 lux precision | 16 ms measurement time |
High Resolution Mode | 1 lux precision | 120 ms measurement time |
High Resolution Mode 2 | 0.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
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
Here’s the BH1750 Pinout:
VCC | Powers the sensor (3.3V or 5V) |
GND | Common GND |
SCL | SCL 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:
BH1750 | ESP32 | ESP8266 |
VCC | 3.3V | 3.3V |
GND | GND | GND |
SCL | GPIO 22 | GPIO 5 (D1) |
SDA (Data) | GPIO 21 | GPIO 4 (D2) |
ADD* | Don’t connect | Don’t connect |
You can also use the following schematic diagrams as a reference.
Schematic – ESP32 with BH1750
Schematic – ESP8266 NodeMCU with BH1750
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)
2) Go to File > Save as…
3) Select save to “MicroPython device“:
4) Name your file as bh1750.py and press the OK button:
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:
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)
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.
Constant | Description |
CONT_LOWRES | Continuous, low-resolution (4lx), sampling takes ~24ms, sensor remains on after reading. |
CONT_HIRES_1 | Continuous, high-resolution (1lx), sampling takes ~180ms, sensor remains on after reading. |
CONT_HIRES_2 | Continuous, very high resolution (.5lx), sampling takes ~180ms, sensor remains on after reading. |
ONCE_HIRES_1 | One-shot, low resolution (4lx), sampling takes ~24ms, sensor powered down after reading |
ONCE_HIRES_2 | One-shot, high resolution (1lx), sampling takes ~180ms, sensor powered down after reading |
ONCE_LOWRES | One-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.
You should get new luminance values in lux units every two seconds.
Cover the sensor or point some light to see the values changing.
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:
- MicroPython: ESP32/ESP8266 with DHT11/DHT22 Temperature and Humidity Sensor
- MicroPython: BME280 with ESP32 and ESP8266 (Pressure, Temperature, Humidity)
- MicroPython: BME680 with ESP32 and ESP8266 (Temperature, Humidity, Pressure, Gas)
- MicroPython: DS18B20 Temperature Sensor with ESP32 and ESP8266
- MicroPython: HC-SR04 Ultrasonic Sensor with ESP32 and ESP8266 (Measure distance)
- MicroPython: RCWL-0516 Microwave Radar Sensor – Detect Motion with ESP32/ESP8266
Learn more about MicroPython with our resources:
Thanks for reading.