光照传感器集成
光照传感器集成
本节介绍如何在 ESP32 中集成 BH1750 光照传感器,包括 I2C 配置、数据读取和代码实现。学习完成后,您将能够:
- 理解 I2C 通信协议的基本原理
- 安装和配置 BH1750 库
- 编写光照强度读取代码
- 处理多 I2C 设备的共存问题
在开始本节之前,请确保:
- 已完成硬件接线
- 了解 I2C 通信的基本概念(地址、SDA、SCL)
- 已完成 DHT22 传感器集成
- 已安装 PlatformIO 或 Arduino IDE
I2C Communication Basics
Section titled “I2C Communication Basics”What is I2C?
Section titled “What is I2C?”I2C(Inter-Integrated Circuit)是一种同步、多主从的串行通信协议,由 Philips 在 1982 年开发。
特点:
- 仅需两根线:SDA(数据线)和 SCL(时钟线)
- 支持多个设备和多个主机
- 每个设备有唯一地址(7 位或 10 位)
- 速度标准模式 100kHz,快速模式 400kHz
在 IoT 中的应用:
- 连接传感器(BH1750、BME280、MPU6050)
- 连接显示模块(OLED SSD1306、LCD1602)
- 连接 ADC/DAC 扩展芯片
ESP32 I2C Pins
Section titled “ESP32 I2C Pins”ESP32 有两组 I2C 控制器,默认引脚如下:
| 信号 | 默认引脚 | 可配置引脚 |
|---|---|---|
| SDA | GPIO 21 | 任意 GPIO |
| SCL | GPIO 22 | 任意 GPIO |
ESP32 的优势在于所有 GPIO 都可作为 I2C 引脚,这提供了极大的布线灵活性。
Library Setup
Section titled “Library Setup”Arduino IDE
Section titled “Arduino IDE”1. 打开 工具 → 管理库2. 搜索 "BH1750" by Christopher Laws3. 安装最新版本PlatformIO
Section titled “PlatformIO”; platformio.ini[env:esp32dev]platform = espressif32board = esp32devframework = arduinomonitor_speed = 115200
lib_deps = adafruit/DHT sensor library@^1.4.4 adafruit/Adafruit Unified Sensor@^1.1.9 claws/BH1750@^1.3.0Code Implementation
Section titled “Code Implementation”Basic BH1750 Reading
Section titled “Basic BH1750 Reading”#include <Wire.h>#include <BH1750.h>
BH1750 lightMeter; // 创建 BH1750 对象
void setup() { Serial.begin(115200); Wire.begin(); // 初始化 I2C 总线 lightMeter.begin(); // 初始化 BH1750
Serial.println("BH1750 Light Sensor Test"); Serial.println("------------------------");}
void loop() { float lux = lightMeter.readLightLevel();
Serial.print("Light: "); Serial.print(lux); Serial.print(" lux");
// 添加描述性标签 if (lux < 50) { Serial.println(" (Dim / Indoor)"); } else if (lux < 500) { Serial.println(" (Normal Office)"); } else if (lux < 1000) { Serial.println(" (Bright Office)"); } else if (lux < 10000) { Serial.println(" (Overcast Outdoor)"); } else { Serial.println(" (Direct Sunlight)"); }
delay(1000); // BH1750 支持更快的采样率}With Configuration Options
Section titled “With Configuration Options”#include <Wire.h>#include <BH1750.h>
BH1750 lightMeter; // 默认模式:连续高分辨率模式
void setup() { Serial.begin(115200); Wire.begin();
// 配置 BH1750 模式 // 可选模式: // - BH1750_CONTINUOUS_HIGH_RES_MODE: 连续高分辨率模式 (1 lux 精度) // - BH1750_CONTINUOUS_HIGH_RES_MODE_2: 连续高分辨率模式2 (0.5 lux 精度) // - BH1750_CONTINUOUS_LOW_RES_MODE: 连续低分辨率模式 (4 lux 精度, 更快) // - BH1750_ONE_TIME_HIGH_RES_MODE: 单次高分辨率模式 (省电)
if (lightMeter.begin(BH1750_CONTINUOUS_HIGH_RES_MODE)) { Serial.println("BH1750 initialized successfully"); } else { Serial.println("Error: BH1750 not found!"); while (1); // 停止执行 }}
void loop() { float lux = lightMeter.readLightLevel();
if (lux < 0) { Serial.println("Error reading BH1750!"); } else { Serial.print("Brightness: "); Serial.print(lux, 1); Serial.println(" lux"); }
delay(2000);}I2C Address Configuration
Section titled “I2C Address Configuration”BH1750 有两种可能的 I2C 地址:
#include <Wire.h>#include <BH1750.h>
// ADDR 引脚接 GND → 地址 0x23 (默认)BH1750 lightMeter1;
// ADDR 引脚接 VCC → 地址 0x5CBH1750 lightMeter2;
void setup() { Serial.begin(115200); Wire.begin();
// 使用自定义地址初始化 lightMeter1.begin(BH1750_ONE_TIME_HIGH_RES_MODE, 0x23); lightMeter2.begin(BH1750_ONE_TIME_HIGH_RES_MODE, 0x5C);
Serial.println("Two BH1750 sensors initialized");}
void loop() { // 读取第一个传感器 float lux1 = lightMeter1.readLightLevel();
delay(150); // 切换传感器间的短暂延迟
// 读取第二个传感器 float lux2 = lightMeter2.readLightLevel();
Serial.print("Sensor 1 (0x23): "); Serial.print(lux1, 1); Serial.print(" lux, Sensor 2 (0x5C): "); Serial.print(lux2, 1); Serial.println(" lux");
delay(2000);}I2C Scanner Utility
Section titled “I2C Scanner Utility”在调试或添加新 I2C 设备时,使用此代码扫描所有连接的 I2C 设备:
#include <Wire.h>
void setup() { Serial.begin(115200); Wire.begin(); Serial.println("I2C Scanner");}
void loop() { byte error, address; int deviceCount = 0;
Serial.println("Scanning I2C devices...");
for (address = 1; address < 127; address++) { Wire.beginTransmission(address); error = Wire.endTransmission();
if (error == 0) { Serial.print("I2C device found at address 0x"); if (address < 16) Serial.print("0"); Serial.print(address, HEX); Serial.println(); deviceCount++; } else if (error == 4) { Serial.print("Error at address 0x"); if (address < 16) Serial.print("0"); Serial.println(address, HEX); } }
if (deviceCount == 0) { Serial.println("No I2C devices found!"); } else { Serial.print("Total: "); Serial.print(deviceCount); Serial.println(" device(s)"); }
Serial.println("--------------------"); delay(5000); // 每 5 秒扫描一次}Integration with DHT22
Section titled “Integration with DHT22”将 DHT22 和 BH1750 集成到同一个项目中:
#include <Wire.h>#include <BH1750.h>#include <DHT.h>
// DHT22 配置#define DHTPIN 4#define DHTTYPE DHT22DHT dht(DHTPIN, DHTTYPE);
// BH1750 配置BH1750 lightMeter;
// 传感器数据结构struct EnvironmentData { float temperature; float humidity; float lux; unsigned long timestamp;};
void setup() { Serial.begin(115200);
// 初始化 I2C 总线 Wire.begin();
// 初始化 DHT22 dht.begin();
// 初始化 BH1750 if (!lightMeter.begin()) { Serial.println("BH1750 initialization failed!"); } else { Serial.println("All sensors initialized"); }}
void loop() { EnvironmentData data; data.timestamp = millis();
// 读取 DHT22 data.humidity = dht.readHumidity(); data.temperature = dht.readTemperature();
// 读取 BH1750 data.lux = lightMeter.readLightLevel();
// 检查传感器状态 bool dhtError = isnan(data.temperature) || isnan(data.humidity); bool bh1750Error = (data.lux < 0);
if (dhtError) { Serial.println("DHT22 read error"); }
if (bh1750Error) { Serial.println("BH1750 read error"); }
if (!dhtError && !bh1750Error) { // 构建 JSON 格式输出 Serial.print("{\"temp\":"); Serial.print(data.temperature, 1); Serial.print(",\"hum\":"); Serial.print(data.humidity, 1); Serial.print(",\"lux\":"); Serial.print(data.lux, 0); Serial.println("}"); }
delay(3000); // 每 3 秒采集一次}验证光照传感器
Section titled “验证光照传感器”# 使用 I2C 扫描确认 BH1750 已被识别预期输出:
I2C device found at address 0x23Total: 1 device(s)光照测试方法:
| 测试条件 | 预期 lux 值 | 验证结果 |
|---|---|---|
| 完全遮盖传感器 | 0-5 lux | |
| 室内自然光 | 100-500 lux | |
| 日光灯下 | 300-1000 lux | |
| 手机闪光灯照射 | 1000-5000 lux | |
| 阳光直射 | 10000-65000 lux |
Issue 1: BH1750 无响应
Section titled “Issue 1: BH1750 无响应”症状:读取返回 -1 或 I2C 扫描找不到设备
可能原因:
- I2C 地址错误
- 供电不足
- SDA/SCL 接线反接
解决方案:
- 运行 I2C 扫描确认设备地址
- 检查供电电压(应为 3.3V)
- 交换 SDA 和 SCL 线缆
Issue 2: 光照值跳动过大
Section titled “Issue 2: 光照值跳动过大”症状:相同光照条件下读数波动 > 20%
可能原因:
- 传感器窗口有污渍
- I2C 总线噪声
- 电源不稳定
解决方案:
- 清洁传感器窗口
- 缩短 I2C 线缆长度
- 在 VCC 和 GND 间添加滤波电容
Issue 3: 与 DHT22 同时工作异常
Section titled “Issue 3: 与 DHT22 同时工作异常”症状:单独测试正常,同时连接后 BH1750 读取异常
可能原因:
- I2C 总线与 DHT22 中断冲突
- 间距过近导致电磁干扰
解决方案:
- 在 I2C 线上添加 4.7kΩ 上拉电阻
- 将 DHT22 和 BH1750 分开一定距离
- 读取 DHT22 和 BH1750 之间添加短暂延时
- ✅ 推荐: 对光照值进行滑动平均滤波(取最近 5 次读数的平均值)
- ✅ 推荐: 根据环境选择合适的 BH1750 测量模式(室内用高分辨率,户外用低分辨率)
- ✅ 推荐: 多传感器布局时避免遮挡
- ❌ 避免: 传感器放置在窗口正对阳光的位置(会导致读数饱和)
- ❌ 避免: I2C 总线长度超过 50cm(信号衰减)
- ❌ 避免: 在同一个 I2C 总线上连接过多设备(超过 5-8 个建议添加多路复用器)
Summary
Section titled “Summary”本节要点总结:
- BH1750 光照传感器:I2C 接口,地址 0x23(默认)或 0x5C
- 测量范围:1-65535 lux,覆盖从黑暗到阳光直射的广泛应用场景
- 多种模式:连续/单次、高/低分辨率模式可选
- 集成要点:使用 Wire 库初始化 I2C 总线,调用
readLightLevel()获取数据 - I2C 调试:使用 I2C 扫描工具快速排查设备连接问题