Learn to use the BH1750 ambient light sensor with the Raspberry Pi Pico programmed with MicroPython to get ambient light measurements. We’ll show you how to wire the sensor, install the required libraries, and get sensor measurements in LUX unit, the standardized unit for illuminance.
New to the Raspberry Pi Pico? Read the following guide: Getting Started with Raspberry Pi Pico (and Pico W).
Table of Contents:
Throughout this tutorial, we’ll cover the following subjects:
- Introducing the BH1750 Ambient Light Sensor
- Wiring the BH1750 to the Raspberry Pi Pico
- BH1750 MicroPython Library
- Raspberry Pi Pico – BH1750 Luminance (Lux) – MicroPython Code
Prerequisites
Before proceeding with this tutorial, make sure you follow the next prerequisites.
MicroPython Firmware
To follow this tutorial you need MicroPython firmware installed in your Raspberry Pi Pico board. You also need an IDE to write and upload the code to your board.
The recommended MicroPython IDE for the Raspberry Pi Pico is Thonny IDE. Follow the next tutorial to learn how to install Thonny IDE, flash MicroPython firmware, and upload code to the board.
Alternatively, if you like programming using VS Code, you can start with the following tutorial:
Parts Required
To follow this tutorial, you need the following parts:
- BH1750 ambient light sensor
- Raspberry Pi Pico or Pico W
- Breadboard (optional)
- Jumper wires (optional)
Introducing the 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 picture below. Both are BH1750 sensors.
BH1750 Features
Here’s a list of the BH1750 sensor features. For more information consult the BH1750 sensor datasheet.
- I2C bus Interface
- 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;
- …
Wiring the BH1750 to the Raspberry Pi Pico
The BH1750 sensor uses I2C communication protocol to interface with microcontrollers. Take a look at its pinout in the table below.
Here’s the BH1750 Pinout, it’s the same for both breakout boards:
VCC | Powers the sensor (3.3V or 5V) |
GND | GND |
SCL | SCL pin for I2C communication |
SDA/DAT | SDA pin for I2C communication |
ADDR | Selects address |
The ADDR 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:
- ADDR pin floating or connected to GND → address: 0x23
- ADDR pin connected to VCC → address: 0x5C
We’ll wire the sensor to the Raspberry Pi Pico GPIO 4 (SDA) and GPIO 5 (SCL).
BH1750 | Raspberry Pi Pico |
VCC | 3V3(OUT) |
GND | GND |
SCL | GPIO 5 |
SDA | GPIO 4 |
ADDR* | Don’t connect |
By not connecting the ADDR pin, we’re selecting 0x23 I2C address. However, it’s always better to run an I2C scanner to be sure:
Circuit Diagram
You can use the following diagram as a reference.
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 Pico board:
1) Copy the library code to a new file. The bh1750.py library code can be found here.
# Micropython BH1750 ambient light sensor driver: https://github.com/PinkInk/upylib/tree/master/bh1750
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 “Raspberry Pi Pico“:
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 Raspberry Pi Pico 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.
Raspberry Pi Pico – BH1750 Luminance (Lux) – Code
After uploading the library to the Raspberry Pi Pico, 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/raspberry-pi-pico-bh1750-micropython/
from machine import Pin, SoftI2C
from bh1750 import BH1750
import time
# Initialize I2C communication
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 5 and 4, the I2C pins that the sensor is connected to.
# Initialize I2C communication
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=400000)
Then, create a BH1750 instance, called light_sensor on the I2C bus defined previously.
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 Raspberry Pi Pico 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 guide, you learned how to use the BH1750 luminance sensor with the Raspberry Pi Pico to get measurements of ambient light in LUX units.
We have a similar guide for other boards:
- ESP32 with BH1750 Ambient Light Sensor (Arduino IDE)
- ESP8266 NodeMCU with BH1750 Ambient Light Sensor (Arduino IDE)
- Arduino with BH1750 Ambient Light Sensor
We also have tutorials for other sensors with the Raspberry Pi Pico that you may like:
- Raspberry Pi Pico: BME280 Get Temperature, Humidity, and Pressure (MicroPython)
- Raspberry Pi Pico: RCWL-0516 Microwave Radar Proximity Sensor
- Raspberry Pi Pico: DS18B20 Temperature Sensor (MicroPython) – Single and Multiple
- Raspberry Pi Pico: DHT11/DHT22 Temperature and Humidity Sensor (MicroPython)
We hope you found this tutorial useful. Thanks for reading.
The new pico 2 has arrived.
raspberrypi.com/products/raspberry-pi-pico-2/
thanks for sharing.
Regards,
Sara