BH1750光照传感器接ESP32:直接读勒克斯

2026-11-13 20:17:11 46阅读 所属项目:ESP32 开发板

做光照相关的项目,绕不开勒克斯(lx)这个单位:台灯自动调光、屏幕背光自适应、判断白天黑夜,本质上都是在读"这个环境有多亮"。光敏电阻加分压电阻的老方案能凑合,但读到手的只是模拟电压,换算勒克斯要自己标定曲线,同一批管子的离散性还不小。BH1750 的思路不一样:芯片内部把光强转成数字,通过 I2C 直接吐一个以勒克斯为单位的数给你,量程 1 到 65535 lx,16 位输出,中间不需要任何换算。

这篇把 BH1750 接 ESP32 的完整流程理一遍:引脚与 I2C 地址、量程模式怎么选、装哪个库、代码每一行在干什么。参数与代码对照了 ROHM 官方数据手册(BH1750FVI,Rev.D,2011.11 版)和底稿教程页,例程代码取自库自带的 BH1750test 示例,除头文件写法外逐字符未动。

BH1750光照传感器与ESP32开发板

BH1750 的底子:先把数据摆出来

数据手册里列出的关键参数,逐条照抄:

  • I2C 总线接口,光谱响应接近人眼
  • 照度数字转换,量程 1 - 65535 lx
  • 红外影响很小
  • 50Hz / 60Hz 光噪声抑制
  • 功耗低,带 power down 功能
  • 两路可选 I2C 从机地址
  • 测量偏差 ±20% 左右
  • 支持连续测量与单次测量两种模式

±20% 这个数值得单独说一句:它是芯片级的偏差,日常做亮暗判断、调背光完全够用,但别指望拿它替代专业照度计。也正因为红外影响小,它在白炽灯、日光灯下的读数都比光敏电阻稳定得多。

和 LDR 分压方案的区别在于:LDR 占一个 ADC 通道,读的是分压比,转勒克斯要自己标定,个体差异大;BH1750 数字接口直接给照度值,不占 ADC,两根线挂总线就能读。代价是多花几块钱,外加占用一个 I2C 地址。

量程与分辨率模式:三档精度怎么挑

BH1750 有连续测量和单次测量两种模式,每种又分三档分辨率,精度与耗时直接决定怎么选:

分辨率档位精度测量时间
低分辨率 Low4 lx16 ms
高分辨率 High1 lx120 ms
高分辨率 2 High 20.5 lx120 ms

低分辨率档 16 ms 出一个数、精度 4 lx,适合"判断白天黑夜"这种粗粒度场景;高分辨率档 120 ms、1 lx,是库里的默认档,通用项目用它就好;高分辨率 2 档把精度做到 0.5 lx,适合调光这类需要细腻曲线的项目。

换算口径数据手册写得明白:高分辨率模式下原始计数除以 1.2 就是勒克斯,手册给的例子是原始值 (2^15 + 2^9 + 2^8 + 2^7 + 2^4) 除以 1.2 约等于 28067 lx。这一步库函数已经替你算完,readLightLevel() 返回的直接就是 float 型勒克斯值,不用碰原始计数。

单次测量模式的价值在省电:测完一次芯片自动进 power down 状态,电池项目隔几秒读一次,比一直连续测量划算。

I2C 地址与接线:ADD 悬空就是 0x23

常见的五脚模块丝印是 VCC、GND、SCL、SDA、ADD,有的板子丝印写作 ADDR,指同一个地址选择脚。ADD 引脚上的电压决定 I2C 从机地址,数据手册的阈值口径是低于 0.3 倍 VCC 算低、高于 0.7 倍 VCC 算高:

  • ADD 悬空或接 GND → 地址 0x23(二进制 0100011)
  • ADD 接 VCC → 地址 0x5C(二进制 1011100)

想在一个总线上挂两颗 BH1750,一颗悬空、一颗接 VCC,两个地址互不打架。

下面这张实拍图能看清模块背面的引脚丝印,自上而下是 VCC、SCL、DAT、GND、ADDR——不同厂家的板子丝印顺序可能不同,接线前先对一眼自己的板子:

BH1750FVI模块引脚丝印

接 ESP32 用默认 I2C 引脚,对照表如下:

BH1750ESP32
VCC3.3V
GNDGND
SCLGPIO 22
SDAGPIO 21
ADD不接

ADD 不接就固定选 0x23;想换 0x5C,把它接到 3.3V 即可。换其他 GPIO 也可以,只要在代码里把引脚号传给 Wire.begin()。官方教程页给的接线原理图如下:

BH1750与ESP32接线原理图

装库与代码:读勒克斯只有一个函数

库用 Christopher Laws 维护的 BH1750 库(GitHub 仓库 claws/BH1750),兼容 Arduino、ESP8266、ESP32。Arduino IDE 里打开 工具 - 管理库,搜索 BH1750,装列表里第一个就是,写作时库管理器里显示的版本是 1.2.0。前置条件是 IDE 里已装好 ESP32 板支持包。

Arduino IDE库管理器中的BH1750库

完整例程如下,取自库自带的 BH1750test 示例。头文件写法由尖括号改成了双引号——站点会剥掉尖括号头文件,两种写法在 Arduino 的库搜索路径下等价,除此之外代码一个字符没动:

/*
  Example of BH1750 library usage. This example initialises the BH1750 object using the default high resolution continuous mode and then makes a light level reading every second.
*/

#include "Wire.h"
#include "BH1750.h"

BH1750 lightMeter;

void setup(){
  Serial.begin(9600);

  // Initialize the I2C bus (BH1750 library doesn't do this automatically)
  Wire.begin();
  // On esp8266 you can select SCL and SDA pins using Wire.begin(D4, D3);
  // For Wemos / Lolin D1 Mini Pro and the Ambient Light shield use Wire.begin(D2, D1);

  lightMeter.begin();

  Serial.println(F("BH1750 Test begin"));
}

void loop() {
  float lux = lightMeter.readLightLevel();
  Serial.print("Light: ");
  Serial.print(lux);
  Serial.println(" lx");
  delay(1000);
}

代码结构一句话讲完。Wire.begin() 先把 I2C 总线跑起来——BH1750 库不会替你初始化总线,这一步不能省;lightMeter.begin() 按默认的连续高分辨率模式初始化传感器;loop() 里每秒读一次数。

#include "Wire.h"
#include "BH1750.h"

核心就一行,readLightLevel() 直接返回勒克斯值:

float lux = lightMeter.readLightLevel();

想换测量模式,把模式常量传给 begin():

lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)

库里有六个模式常量可选:

  • BH1750_CONTINUOUS_LOW_RES_MODE
  • BH1750_CONTINUOUS_HIGH_RES_MODE(默认)
  • BH1750_CONTINUOUS_HIGH_RES_MODE_2
  • BH1750_ONE_TIME_LOW_RES_MODE
  • BH1750_ONE_TIME_HIGH_RES_MODE
  • BH1750_ONE_TIME_HIGH_RES_MODE_2

读数怎么用:串口验证与两个落地建议

代码烧进去后,串口监视器开 9600 波特率,按一下板子的 RST 键,每秒会刷一行 Light: xxx lx。教程页的演示截图里,室内光读数在 100 lx 上下浮动,拿手在传感器上方挡一下,数值立刻掉到个位数:

串口监视器的勒克斯读数

两个落地建议。第一,做自动调光别拿绝对值硬卡阈值——先开串口观察你那个场景里亮和暗分别对应多少勒克斯,再定自己的阈值。常见量级可以心里有数:室外日光上万 lx,办公室 300 到 500 lx,夜间走廊灯 100 lx 以下,这些是照明行业的常见参考量级,不是 BH1750 的标称值。

第二,电池项目改用单次测量模式,再拉长读取间隔:测完芯片自己进低功耗,ESP32 这头配合 deep sleep,整套光照采集方案能跑很久。

BH1750 属于接上就能用的那类传感器:接线四根、代码二十行、读数直接是勒克斯。把这一步跑通之后,接屏幕背光、驱动继电器控灯、把数据推上 MQTT,都是顺路的事。


作者:数据媛小满
链接:https://www.aiddithome.com/p/9b5201809ca6a.html
本作版权归作者所有,未经允许请勿转载。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
5条评论
板砖搬不动
1楼 · 11小时前

0.5 lx 那档做屏幕背光自适应正合适,mark 一下周末试试

只看不说话
2楼 · 11小时前

这个方案我年前就搭过一版,拿来做了阳台花房的日照记录,ESP32 加 BH1750 挂 MQTT 上 home assistant,数据每分钟推一条,跑了两个多月没断过。有一点补充:透明雨棚会让读数偏低不少,传感器最好露装,外壳用白色亚克力的透光损耗比灰色小很多。

锡点
3楼 · 11小时前

当初拿光敏电阻调台灯,同一个房间两只管子读数差得离谱,后来换 BH1750 才算消停,确实省心

刷视频进来围观
4楼 · 11小时前

ADD 悬空 0x23 接 VCC 变 0x5C 这个讲清楚了,之前抄别人的代码不知道为啥要 Wire.begin() 两次,原来是库不初始化总线

默默点赞的路人
5楼 · 11小时前

已下单,三块多一个,比我还便宜的只有杜邦线了