一、简介
BH1750FVI 它是一种用于两线串行总线接口的数字光强度传感器集成电路。该集成电路可根据收集的光强数据调整液晶或键盘背景灯的亮度。利用其高分辨率,可以探测到大范围的光强度变化。
传感器特点:
- 支持I2CBUS接口
- 接近视觉灵敏度的光谱灵敏度特征
- 输出相应亮度的数字值
- 对应广泛的输入光范围。(相当于1-65535lx)
- 通过降低功率功能,实现低电流化。
- 通过50Hz/60Hz实现除光噪声功能的稳定测定。
- 支持1.8v逻辑输入接口。
- 没有其他外部部件。
- 光源依赖性弱。
- 有两种选择I2Cslave地址。
- 影响可调测量结果的因素是光入口大小。
- 使用此功能计算1.1lx到100000lx马克斯/分钟范围。
- 最小误差变化在±20%。
- 受红外线影响很小。
1.1 测量程序步骤
1.2 指令集合
1.3 说明测量模式
二、硬件连接
功能口 | 引脚 |
---|---|
SCL | GPIO23 |
SDA | GPIO18 |
ADDR | ADDR ≥ 0.7VCC 从机地址为1011100ADDR ≤ 0.3VCC 0100011从机地址 |
三、添加I2C驱动
查看 ESP32学习笔记(17)——I2C接口使用
四、I2C通信流程
测量结果为2字节(高字节) High Byte 和低字节 Low Byte)计算公式为:
光强(单位)lx)=(High Byte Low Byte)/ 1.2
五、ESP32作为主机与BH1750光强传感器通信
I2C_Init()
初始化I2C后 ↓
BH1750_Init()
配置BH1750连续高分辨率模式 ↓
BH1750_ReadLightIntensity()
获取光强度
#include <stdio.h> #include "esp_log.h" #include "driver/i2c.h" static const char *TAG = "i2c-example"; #define I2C_MASTER_SCL_IO GPIO_NUM_23 /*!< gpio number for I2C master clock */ #define I2C_MASTER_SDA_IO GPIO_NUM_18 /*!< gpio number for I2C master data */ #define I2C_MASTER_NUM 1 /*!< I2C port number for master dev */ #define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */ #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ #define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */ #define READ_BIT I2C_MASTER_READ /*!< I2C master read */ #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ #define ACK_VAL 0x0 /*!< I2C ack value */
#define NACK_VAL 0x1 /*!< I2C nack value */
#define BH1750_SLAVE_ADDR 0x23 // 从机地址
#define BH1750_PWR_DOWN 0x00 // 关闭模块
#define BH1750_PWR_ON 0x01 // 打开模块等待测量指令
#define BH1750_RST 0x07 // 重置数据寄存器值在PowerOn模式下有效
#define BH1750_CON_H 0x10 // 连续高分辨率模式,1lx,120ms
#define BH1750_CON_H2 0x11 // 连续高分辨率模式,0.5lx,120ms
#define BH1750_CON_L 0x13 // 连续低分辨率模式,4lx,16ms
#define BH1750_ONE_H 0x20 // 一次高分辨率模式,1lx,120ms,测量后模块转到PowerDown模式
#define BH1750_ONE_H2 0x21 // 一次高分辨率模式,0.5lx,120ms,测量后模块转到PowerDown模式
#define BH1750_ONE_L 0x23 // 一次低分辨率模式,4lx,16ms,测量后模块转到PowerDown模式
SemaphoreHandle_t print_mux = NULL;
/** @brief I2C驱动初始化 @param 无 @return 无 */
int I2C_Init(void)
{
int i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf;
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = I2C_MASTER_SDA_IO;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
conf.scl_io_num = I2C_MASTER_SCL_IO;
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
i2c_param_config(i2c_master_port, &conf);
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}
/** @brief I2C写数据函数 @param slaveAddr -[in] 从设备地址 @param regAddr -[in] 寄存器地址 @param pData -[in] 写入数据 @param dataLen -[in] 写入数据长度 @return 错误码 */
int I2C_WriteData(uint8_t slaveAddr, uint8_t regAddr, uint8_t *pData, uint16_t dataLen)
{
int ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (slaveAddr << 1) | WRITE_BIT, ACK_CHECK_EN);
if(NULL != regAddr)
{
i2c_master_write_byte(cmd, regAddr, ACK_CHECK_EN);
}
i2c_master_write(cmd, pData, dataLen, ACK_CHECK_EN);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(1, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
/** @brief I2C读数据函数 @param slaveAddr -[in] 从设备地址 @param regAddr -[in] 寄存器地址 @param pData -[in] 读出数据 @param dataLen -[in] 读出数据长度 @return 错误码 */
int I2C_ReadData(uint8_t slaveAddr, uint8_t regAddr, uint8_t *pData, uint16_t dataLen)
{
int ret;
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (slaveAddr << 1) | READ_BIT, ACK_CHECK_EN);
if(NULL != regAddr)
{
i2c_master_write_byte(cmd, regAddr, ACK_CHECK_EN);
}
i2c_master_read(cmd, pData, dataLen, ACK_VAL);
i2c_master_stop(cmd);
ret = i2c_master_cmd_begin(1, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
/** @brief BH1750初始化函数 @param 无 @return 无 */
void BH1750_Init(void)
{
uint8_t data;
data = BH1750_PWR_ON; // 发送启动命令
I2C_WriteData(BH1750_SLAVE_ADDR, NULL, &data, 1);
data = BH1750_CON_H; // 设置连续高分辨率模式,1lx,120ms
I2C_WriteData(BH1750_SLAVE_ADDR, NULL, &data, 1);
}
/** @brief BH1750获取光强度 @param 无 @return 光强度 */
float BH1750_ReadLightIntensity(void)
{
float lux = 0.0;
uint8_t sensorData[2] = {
0};
I2C_ReadData(BH1750_SLAVE_ADDR, NULL, sensorData, 2);
lux = (sensorData[0] << 8 | sensorData[1]) / 1.2;
return lux;
}
static void i2c_test_task(void *arg)
{
int cnt = 0;
float lux;
BH1750_Init();
vTaskDelay(180 / portTICK_RATE_MS); // 设置完成后要有一段延迟
while (1) {
ESP_LOGI(TAG, "test cnt: %d", cnt++);
lux = BH1750_ReadLightIntensity();
xSemaphoreTake(print_mux, portMAX_DELAY);
printf("sensor val: %.02f [Lux]\n", lux);
xSemaphoreGive(print_mux);
vTaskDelay(1000 / portTICK_RATE_MS);
}
vSemaphoreDelete(print_mux);
vTaskDelete(NULL);
}
void app_main(void)
{
print_mux = xSemaphoreCreateMutex();
ESP_ERROR_CHECK(I2C_Init());
xTaskCreate(i2c_test_task, "i2c_test_task_0", 1024 * 2, NULL, 10, NULL);
}
查看打印:
• 由 Leung 写于 2021 年 5 月 14 日
• 参考:BH1750FVI光强度传感器及其STM32驱动程序 BH1750 STM32 驱动程序