
esp-iot-solution BH1750 环境光传感器组件实战从 I2C 接线到光照值读取【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution本篇以 esp-iot-solution 仓库中的 BH1750 环境光传感器组件为核心完整讲清该组件的硬件接线方式SDA/SCL 引脚分配与内部上拉配置、一次测量One-Time与连续测量Continuously两种工作模式的差异以及各核心 API 的调用流程。读完后你可以直接基于 bh1750 驱动源码 和 测试例程 在 ESP32 系列开发板上通过 I2C 总线驱动 BH1750 光照传感器模块如 GY-30 模块稳定读出以 Lux 为单位的照度值。组件定位基于 i2c_bus 的外置 I2C 传感器读取方案BH1750 是一款数字输出环境光照强度传感器组件文档明确说明了它在本仓库中的教学定位展示如何通过 I2C 总线读取外置 I2C 传感器数据硬件上以 BH1750 光照传感器GY-30 模块为例。组件位于 components/sensors/light_sensor/bh1750 目录CMakeLists.txt 中通过REQUIRES i2c_bus声明了它对仓库内 i2c_bus 组件 的依赖——也就是说底层 I2C 通信由i2c_bus抽象层完成驱动本身只负责 BH1750 的命令寄存器读写这是理解整个调用链的起点。BH1750 默认 I2C 器件地址为0x23定义于 bh1750.h 中的BH1750_I2C_ADDRESS_DEFAULT。硬件接线引脚分配与上拉电阻组件文档README.md给出的接线方式如下I2C 主机端引脚分配GPIO18分配给 I2C 主机的数据线SDAGPIO19分配给 I2C 主机的时钟线SCL传感器接线传感器SDA接GPIO18传感器SCL接GPIO19无需外接上拉电阻驱动会启用 GPIO 内部上拉电阻无需外接上拉电阻这一点在源码层面有直接印证。测试例程 bh1750_test.c 创建 I2C 总线时i2c_config_t中显式开启了内部上拉i2c_config_t conf { .mode I2C_MODE_MASTER, .sda_io_num I2C_MASTER_SDA_IO, // 测试例程中使用 GPIO1 .sda_pullup_en GPIO_PULLUP_ENABLE, // 启用内部上拉 .scl_io_num I2C_MASTER_SCL_IO, // 测试例程中使用 GPIO2 .scl_pullup_en GPIO_PULLUP_ENABLE, .master.clk_speed I2C_MASTER_FREQ_HZ, // 100 kHz }; i2c_bus i2c_bus_create(I2C_MASTER_NUM, conf);需要注意组件 README 中示例接线为 GPIO18/GPIO19而 test_apps 例程 实际使用的宏定义是I2C_MASTER_SDA_IO 1与I2C_MASTER_SCL_IO 2100 kHz 时钟。两者并不冲突——i2c_bus_create接受任意 GPIO 配置实际引脚以你的开发板走线为准复制例程时请同步修改这两个宏即可。测量模式One-Time 与 Continuously 的区别BH1750 的测量行为由测量模式命令控制组件文档将模式分为两类一次测量模式One-Time传感器在收到一次测量命令后只测量一次。因此每次想获取新的光照值都必须重新发送一次测量命令。连续测量模式Continuously传感器在收到连续测量命令后持续测量你只需发送一次命令之后反复调用bh1750_get_data()即可不断读到最新的光照值。从 bh1750.h 中的命令枚举可以看到每种模式还进一步细分为三种分辨率档位命令值与数据手册寄存器定义一致枚举值命令值含义BH1750_CONTINUE_1LX_RES0x10连续测量1 lx 分辨率H-ResolutionBH1750_CONTINUE_HALFLX_RES0x11连续测量0.5 lx 分辨率H-Resolution 2BH1750_CONTINUE_4LX_RES0x13连续测量4 lx 分辨率L-ResolutionBH1750_ONETIME_1LX_RES0x20单次测量1 lx 分辨率BH1750_ONETIME_HALFLX_RES0x21单次测量0.5 lx 分辨率BH1750_ONETIME_4LX_RES0x23单次测量4 lx 分辨率除测量命令外bh1750.c 中还定义了两个电源与数据管理命令对应头文件中公开的 API0x00进入 Power Down 低功耗模式bh1750_power_down()0x01Power Onbh1750_power_on()0x07复位数据寄存器bh1750_reset_data_register()注意该命令在掉电模式下不可用源码实现里会先执行bh1750_power_on()再写入复位命令见 bh1750.c核心 API 与内部实现对象创建与销毁bh1750_create/bh1750_delete驱动采用句柄模型。bh1750_create(bus, dev_addr)接收一个i2c_bus总线句柄和传感器 I2C 地址内部通过i2c_bus_device_create()注册一个 I2C 设备继承总线的当前时钟速度成功后返回bh1750_handle_t失败返回NULL见 bh1750.c。用完之后调用bh1750_delete(handle)释放 I2C 设备句柄并回收内存。设置模式bh1750_set_measure_mode该函数只向传感器写一个字节即上文表格中的命令值完成测量模式切换。头文件注释提醒必须在调用bh1750_get_data()读取数据之前先调用它设置测量模式若设置为一次测量模式则只能读到一个测量结果若设置为连续测量模式则可反复调用bh1750_get_data()获取数据。读取原始值bh1750_get_databh1750_get_data(sensor, data)从传感器读出 2 字节原始值并完成浮点换算bh1750.cuint8_t bh1750_data[2] {0}; esp_err_t ret i2c_bus_read_bytes(sens-i2c_dev, NULL_I2C_MEM_ADDR, 2, bh1750_data[0]); *data ((bh1750_data[0] 8 | bh1750_data[1]) / BH_1750_MEASUREMENT_ACCURACY);其中BH_1750_MEASUREMENT_ACCURACY定义为1.2bh1750.c注释说明为 BH1750 的典型测量精度系数即最终光照值 16 位原始值 ÷ 1.2单位为 Lux。头文件注释同时强调必须等测量时间过去之后再读数据不同测量模式的测量时间不同这一点是实际开发中最容易踩的坑。一步式读取bh1750_get_light_intensity组件文档特别指出可以直接调用bh1750_get_light_intensity()一步完成光照值获取其内部工作过程为三步发送测量命令延时一段长于测量时间的时长读取光照值。源码实现bh1750.c印证了这个流程并且根据分辨率档位选择了不同的等待时长esp_err_t ret bh1750_set_measure_mode(sensor, cmd_measure); if (ret ! ESP_OK) { return ret; } if ((cmd_measure BH1750_CONTINUE_4LX_RES) || (cmd_measure BH1750_ONETIME_4LX_RES)) { vTaskDelay(30 / portTICK_RATE_MS); // 4 lx 分辨率约 30 ms 测量时间 } else { vTaskDelay(180 / portTICK_RATE_MS); // 1 lx / 0.5 lx 分辨率约 180 ms 测量时间 } ret bh1750_get_data(sensor, data);可以推断30 ms 对应 BH1750 低分辨率4 lx档位的测量周期180 ms 对应高分辨率档位的测量周期两者都与不同测量模式测量时间不同的文档说明相吻合。如果你的业务循环周期较长、且只关心大致照度选用 4 lx 档位BH1750_ONETIME_4LX_RES/BH1750_CONTINUE_4LX_RES可以让每次采样的等待时间缩短到约 1/6。自定义测量时间bh1750_change_measure_time组件文档的最后一条 Notice 指出BH1750 在不同测量模式下的测量时间不同并且可以通过调用bh1750_change_measure_time()修改测量时间。源码实现bh1750.c向传感器连续写入 2 个字节将 8 位测量时间参数拆分编码uint8_t buf[2] {0x40, 0x60}; buf[0] | measure_time 5; // 高 3 位 buf[1] | measure_time 0x1F; // 低 5 位 i2c_bus_write_bytes(sens-i2c_dev, NULL_I2C_MEM_ADDR, 2, buf[0]);其中0x40/0x60是该组寄存器的命令头measure_time的有效位宽为 8 位高 3 位写入第一字节、低 5 位写入第二字节。修改测量时间后后续读取数据的等待时长也需要同步调整这一点需要使用者自行把握。测试例程走读从 I2C 初始化到两种模式对比test_apps/main/bh1750_test.c 是一个基于 Unity 框架的完整可运行例程app_main()启动unity_run_menu()测试入口为TEST_CASE(Sensor BH1750 test, [bh1750][iot][sensor])。例程分三步初始化bh1750_test_init→ 交替采样bh1750_test_get_data→ 反初始化bh1750_test_deinit。采样循环的逻辑是每次先上电然后分别以一次测量模式BH1750_ONETIME_4LX_RES和连续测量模式BH1750_CONTINUE_4LX_RES各读一次中间统一等待 30 ms4 lx 档位每秒循环一轮、共 10 轮bh1750_power_on(bh1750); cmd_measure BH1750_ONETIME_4LX_RES; bh1750_set_measure_mode(bh1750, cmd_measure); vTaskDelay(30 / portTICK_RATE_MS); ret bh1750_get_data(bh1750, bh1750_data); if (ret ESP_OK) { printf(bh1750 val(one time mode): %f\n, bh1750_data); } else { printf(No ack, sensor not connected...\n); }No ack的报错分支也提示了排查思路若 I2C 写/读返回失败通常是传感器未接线、地址不符或总线冲突。例程的反初始化阶段按先删传感器、再删总线的顺序释放资源bh1750_delete(bh1750); i2c_bus_delete(i2c_bus);依赖与构建配置方面test_apps/main/idf_component.yml 要求idf 4.4并通过override_path将bh1750指向组件本体、i2c_bus指向仓库内的 i2c_bus 组件保证测试始终使用本地最新源码test_apps/sdkconfig.defaults 中关闭了任务看门狗CONFIG_ESP_TASK_WDT_ENnIDF 4.4 为CONFIG_ESP_TASK_WDTn并设置CONFIG_FREERTOS_HZ1000使vTaskDelay(30 / portTICK_RATE_MS)这类 30 ms 级延时能够精确生效——这与等待时长必须覆盖测量时间的要求直接相关。硬件抽象层接口接入光照传感器统一框架除独立使用外BH1750 驱动在CONFIG_SENSOR_LIGHT_INCLUDED_BH1750编译开关下还实现了一组硬件抽象层HAL接口bh1750.hlight_sensor_bh1750_init(i2c_bus_handle_t handle)使用默认地址0x23创建传感器对象light_sensor_bh1750_deinit()释放对象light_sensor_bh1750_test()检查初始化状态light_sensor_bh1750_acquire_light(float *l)一次性读取照度单位 lux。其中acquire_light的实现固定采用BH1750_ONETIME_4LX_RES模式先bh1750_power_on()再设置模式、等待 30 ms、读取数据失败时输出 0 并返回ESP_FAILbh1750.c。这套init/deinit/test/acquire_*接口签名与仓库中其他光照传感器如 VEML6040、VEML6075保持一致docs/zh_CN/sensors/light_sensor.rst 中列出的已适配环境光传感器表也标注 BH1750 已支持硬件抽象层。有了这层接口上层可以直接通过 sensor_hub 的传感器接口以统一方式轮询光照值而不必关心底层芯片差异sensor_hub 测试中的虚拟光照传感器 同样实现了acquire_light这套回调结构可用来在无真实硬件时联调上层逻辑。典型运行输出与验证仓库中还有一个基于 POSIX 风格 API 读取 BH1750 的完整示例工程 examples/extended_vfs/i2c/i2c_bh1750其 README 给出了通过idf.py -p PORT flash monitor烧录后的典型串口输出可作为读取结果正常性的对照基准Opening device /dev/i2c/0 for writing OK, fd3. Sensor val: 190.00 [Lux]. Sensor val: 173.33 [Lux]. Sensor val: 173.33 [Lux]. Sensor val: 176.67 [Lux]. Sensor val: 193.33 [Lux]. Close device OK.可以看到数值稳定落在室内照度范围且以 Lux 为单位该示例还支持在idf.py menuconfig的Example Configuration中修改 SDA/SCL 引脚号以及读取次数方便适配不同开发板。实践要点小结接线SDA/SCL 分别接主机 GPIOREADME 示例为 GPIO18/GPIO19创建总线时开启GPIO_PULLUP_ENABLE内部上拉无需外部上拉电阻模式选择低频采样用 One-Time 模式每次读取前重发命令高频连续采样用 Continuously 模式一次设置、反复bh1750_get_data()等待时长读数据前必须等待超过该分辨率档位的测量时间bh1750_get_light_intensity()内部已按 30 ms / 180 ms 处理手动调用bh1750_set_measure_mode()bh1750_get_data()时需自行vTaskDelay换算关系驱动输出的 Lux 值 16 位原始值 ÷ 1.2如需更高精度场景可自行评估该系数调试手段I2C 读写失败无 ACK时优先检查传感器供电、接线与0x23地址是否被同总线其他器件占用。以上所有说明均可在仓库对应文件中核对组件 README、头文件 API 文档、驱动实现 与 测试例程配合 i2c_bus 组件 与 extended_vfs BH1750 示例 即可完成从硬件接线到应用层读数的完整闭环。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考