← 返回传感器图鉴

BH1750 数字光照传感器

最后更新 2026-06-20
⏱ 约 5 分钟 🟡 涉接线/强电
🛒 器材清单
器材数量参考
BH1750 模块(GY-302)1

价格随渠道波动,以购买页实时为准。

想让屏幕背光随环境亮度自动调暗调亮,或者让阳台的补光灯在天阴下来时自动补光——第一步都是先知道"现在到底有多亮"。如果用光敏电阻(LDR),读出来是个 0~4095 之间的数,800 算亮还是 2000 算亮?换一颗电阻、换一块板子,这个数还会变,根本没法跨设备复用。

BH1750 解决的就是这件事:它直接吐给你一个带单位的数字——勒克斯(lux)。室内办公照度大概 300~500 lux,阴天户外 1000 lux,正午暴晒 10 万 lux,这些都是世界通用的标准值。读到 "350 lux",无论换哪块板子都是同一个亮度,背光阈值直接写死成数字就行。

工作原理

BH1750 内部是一颗对可见光敏感的光电二极管,它把照射进来的光强转换成微小的电流——光越强,电流越大。这股电流送进芯片内置的 ADC(模数转换) 变成数字量,再经过芯片内部按 datasheet 校准好的换算公式,直接算出对应的 lux 值,最后通过 I2C 总线交给单片机

关键差别在"谁来换算":

  • 光敏电阻 LDR:只是一个阻值随光变化的电阻。它给的是相对的模拟电压,要变成 lux 得自己拿照度计一点点标定,而且每颗电阻特性都有偏差,温度一变还会漂。详见 /sensor/ldr/
  • BH1750:换算这一步在芯片出厂时就标定好了,封装在内部。直接读出 lux,拿来即用,跨设备一致,精度也高得多。

它对人眼可见光谱的响应做了拟合(接近人眼感受),所以测出来的 lux 和"人觉得亮不亮"比较吻合,特别适合做照度相关的自动控制。想深入看 I2C 和 ADC 的底层机制,参考 /principle/i2c//principle/adc/

接线

BH1750(GY-302 模块)板载稳压,VCC 接 3.3V 即可,I2C 走 SDA/SCL 两根线。ADDR 引脚决定芯片在总线上的地址:

BH1750 ESP32 说明
VCC 3.3V 模块自带稳压,接 3.3V 最稳
GND GND 公共地
SDA GPIO21 I2C 数据线
SCL GPIO22 I2C 时钟线
ADDR 接 GND 地址 = 0x23(默认)
ADDR 接 VCC 地址 = 0x5C

GY-302 模块上 SDA/SCL 通常已带上拉电阻,多数情况下不用额外加。如果总线上挂了多个设备或读不到数据,可在 SDA、SCL 各接一颗 4.7kΩ 上拉到 3.3V,原理见 /principle/pullup/

ADDR 引脚是用来在同一条 I2C 总线上挂两颗 BH1750 的:一颗 ADDR 接地走 0x23,另一颗 ADDR 接高电平走 0x5C,互不冲突。

完整代码

用现成的 BH1750 库(Arduino 库管理器里搜 "BH1750",claws/BH1750 这个最常用),几行就能跑:

#include <Wire.h>
#include <BH1750.h>

// 默认地址 0x23(ADDR 接地);若 ADDR 接高电平改成 0x5C
BH1750 lightMeter(0x23);

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);              // ESP32 指定 SDA=21, SCL=22

  // 连续高分辨率模式:分辨率 1 lx,约 120ms 一次测量
  if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
    Serial.println("BH1750 已就绪");
  } else {
    Serial.println("BH1750 初始化失败,检查接线和地址(0x23/0x5C)");
  }
}

void loop() {
  float lux = lightMeter.readLightLevel();   // 直接读出 lux,无需换算
  Serial.print("光照: ");
  Serial.print(lux);
  Serial.println(" lux");
  delay(1000);
}

CONTINUOUS_HIGH_RES_MODE 是连续高分辨率模式,分辨率 1 lx、一次测量约 120ms,是最常用的档位。库还提供 HIGH_RES_MODE_2(0.5 lx,弱光更细腻)和 LOW_RES_MODE(4 lx,更快),按需要选。readLightLevel() 返回的就是 lux 浮点值,不用任何标定换算。

你应该看到什么

打开串口监视器(115200 波特率),正常情况下每秒打印一行:

BH1750 已就绪
光照: 312.50 lux
光照: 318.33 lux
光照: 45.00 lux        ← 用手挡住传感器开窗
光照: 1583.00 lux      ← 拿手机手电筒照

拿手挡住、用手电筒照、走到窗边,数值会明显跟着变。对照一下:手机手电直射近处能轻松冲到几千甚至上万 lux,遮住后掉到几十 lux,这就说明传感器工作正常。

读数解读

BH1750 的量程约 1 ~ 65535 lux,覆盖从夜晚到烈日的绝大多数场景。常见环境对照:

场景 大致照度(lux)
满月夜晚 约 1
路灯下的夜街 5 ~ 20
室内一般照明 100 ~ 300
办公室/教室 300 ~ 500
阴天的室外 1000 ~ 2000
日出日落时分 400 ~ 1000
晴天阴影处 10000 ~ 20000
正午直射阳光 50000 ~ 100000+

定阈值时拿这张表当参考:做室内自动背光,把"暗"判到 200 lux 以下、"亮"判到 500 lux 以上,留一段缓冲带避免在临界点反复跳变(这叫迟滞,控制里很常用)。

选型 / 避坑

需求 选谁 理由
直接读 lux、要精度、跨设备一致 BH1750 内部已校准,数字输出
只要"亮/暗"相对判断、极致便宜 光敏电阻 LDR 几毛钱,但要自己标定、会漂,见 /sensor/ldr/
要识别颜色(RGB)/ 色温 TCS34725 带 RGB+Clear 四通道,能算颜色
🚧 避坑

I2C 扫不到设备:先确认地址——ADDR 接地是 0x23,接高电平是 0x5C,库里地址填错就 begin 失败。再查 SDA/SCL 有没有接反、上拉是否到位。可以先跑一个 I2C 扫描程序看总线上到底出现哪个地址。

读数饱和/卡在最大值:强光(比如正午阳光、激光笔)超过量程时读数会顶到 65535 附近不再变化。这不是坏,是超量程了。需要测强光场景可改用低分辨率模式或加遮光/减光片。

进阶 / 变体

自动背光控制:把 lux 映射到 PWM 占空比。环境越暗、屏幕背光越低(省电又护眼),越亮则调高保证可读。加迟滞和平滑滤波(取最近几次的平均),避免人影一晃就闪屏。

植物补光阈值控制:设定一条目标照度线,比如多肉需要全天累计足够光照。当实测 lux 低于阈值(阴天、傍晚)就开补光灯,高于阈值就关。进阶可以累加每天的光照"时间×强度"做光照积分,更接近植物真实需求。

自动窗帘:清晨 lux 上升到设定值自动拉开窗帘,正午过强时半闭遮光,傍晚关闭。配合时间判断能避免阴天误动作。

想把这类"传感器读数 → 自动决策"做成一个完整闭环项目,配合 OLED 显示和 AI 辅助开发,参考 /guide/l2-oled//guide/l4-sensor-ai/

典型应用

  • 屏幕/灯具自动调光(手机、电视、智能台灯都靠它)
  • 智能窗帘按光照自动开合
  • 植物补光灯的开关与时长控制
  • 室内照度记录、考勤教室照明达标检测
  • 摄影测光、环境光数据采集

小结 · 相关

BH1750 的核心价值是"直接给你带单位的标准 lux",省掉了光敏电阻必须自己标定的麻烦,精度高、跨设备一致,量程从月光覆盖到烈日。接线就是 I2C 四线加一个决定地址的 ADDR,代码用 BH1750 库三五行搞定。做任何"亮度自动控制"的项目,它都是首选。

相关阅读:/sensor/ldr/(便宜的相对方案)、/principle/i2c//principle/adc//principle/pullup//guide/l4-sensor-ai/,更多器件见 /sensor//principle//guide/

参数以 datasheet 为准;本页公开资料整理,接线与代码请结合实物验证。

📄 来源 / 自校链接

本文为公开资料整理,非亲测。关键参数与代码请结合实物与下列官方来源验证。

内容有错、看不懂、或想看下一期?告诉我们 →

本文为公开资料的学习整理,非亲测。涉接线/花钱/合规的步骤请结合实物与官方最新资料验证,风险自负。见免责声明