BH1750FVI 是一种用于两线式串行总线接口的数字型光强度传感器集成电路。这种集成电路可以根据收集的光线强度数据来调整液晶或者键盘背景灯的亮度。利用它的高分辨率可以探测较大范围的光强度变化。
传感器特点:
- 支持I2CBUS接口
- 接近视觉灵敏度的光谱灵敏度特性
- 输出对应亮度的数字值
- 对应广泛的输入光范围。(相当于1-65535lx)
- 通过降低功率功能,实现低电流化。
- 通过50Hz/60Hz除光噪音功能实现稳定的测定。
- 支持1.8v逻辑输入接口。
- 无需其他外部件。
- 光源依赖性弱。
- 有两种可选的I2Cslave地址。
- 可调的测量结果影响较大的因素为光入口大小。
- 使用这种功能计算1.1lx到100000lx马克斯/分钟的范围。
- 最小误差变动在±20%。
- 受红外线影响很小。
功能口 | 引脚 |
---|---|
SCL | GPIO23 |
SDA | GPIO18 |
ADDR | ADDR ≥ 0.7VCC 从机地址为”1011100“ ADDR ≤ 0.3VCC 从机地址为”0100011“ |
查看 ESP32学习笔记(17)——I2C接口使用
测量结果为2字节(高字节 High Byte 和低字节 Low Byte)数据,计算公式为:
光照强度(单位lx)=(High Byte + Low Byte)/ 1.2
连续高分辨率模式
I2C_Init()
初始化I2C后
↓
BH1750_Init()
配置BH1750连续高分辨率模式
↓
BH1750_ReadLightIntensity()
获取光强度
#include
#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 驱动程序