第3-6讲:光照强度测量(基于BH1750)
-
- 学习目的
- 了解BH1750光照强度传感器。
- 掌握单片机编程使用BH1750的连续高分辨率模式和单次高分辨率模式下测量光照强度。
- 光强度传感器
- BH1750简介
- 光强度传感器
BH1750是一款用于测量光照强度的数字型光强度传感器IC。他内置了16位的模数转换器,可以将测量结果转为数字信号通过I2C接口输出,因此,用户使用时可以直接获取光照强度数值,而不需要复杂的计算。
- BH1750特点
- 支持I2C总线接口(支持F/S模式)。
- 接近视觉灵敏度的光谱灵敏度特性。
- 输出对应亮度的数字值。
- 对应广泛的输入光范围(1-65535lx)。
- 通过断电功能实现低电流。
- 50Hz/60Hz光噪声抑制功能。
- 支持1.8V逻辑输入接口。
- 无需其他外部器件。
- 对光源的依赖性小(对白炽灯、荧光灯、卤素灯、白色LED、太阳光等光源的依赖)。
- 有两种可选的I2C器件地址。
- 可调整的光学窗口对调测量结果的影响(使用此功能可以检测最小 0.11 lx,最大 100000 lx)。
- 测量偏差小(±20%)。
- 受红外线影响很小。
- 典型应用
移动电话,液晶电视,笔记本电脑,便携式游戏机,数码相机,数码摄像机,汽车定位系统,液晶显示器。
- 相关知识点
光照强度是一种物理术语,简称照度,其物理意义是照射到单位面积上的光通量。照度的单位是每平方米的流明(Lm)数,也叫做勒克斯(lx): 1 lx=1 Lm/㎡。
-
-
- BH1750光照强度传感器模块
-
- 模块简介
艾克姆的BH1750光照强度传感器模块是以ROHM原装的芯片BH1750为核心,为了方便用户接入不同工作电源的电路,模块上做了电平转换电路,使得该模块支持3.3V和5V的电源系统。
图1:BH1750光照强度传感器模块
- 模块尺寸
图2:模块尺寸
- 引脚定义
图3:引脚定义
-
- 软件设计
BH1750有多种分辨率,官方推荐使用H(高)分辨率模式1,H分辨率模式1测量时间长(积分时间长),可以有效过滤频率在50-60Hz的噪声信号,并且H分辨率模式1的分辨率为1lx,适用于黑夜测量。因此,本节我们讲解的主要是H分辨率模式1下的单次测量和连续测量,同时,为了方便初学者理解,代码中没有将模式配置和测量整合成单个函数,而是分别编写不同的函数。
-
-
- 光照强度测量实验(单次高精度模式)
-
- 注:本节的实验是在“实验2-6-1:串口1数据收发实验”的基础上修改,本节对应的实验源码是:“实验3-6-1:单次高分辨率模式测量光照强度(基于BH1750)实验”。
-
-
- 实验内容
-
-
单片机通过I2C向BH1750发送单次高分辨率测量指令,之后读取测量结果数据并通过串口输出数据。
-
-
-
- 代码编写
-
-
- 新建一个名称为“bh1750.c”的文件及其头文件“bh1750.h”保存到工程的“Source”文件夹,并将“bh1750.c”加入到Keil工程中的“SOURCE”组。该文件用于存放BH1750操作相关的函数。
- 引用头文件
因为在“main.c”文件中使用了“bh1750.c”文件中的函数,所以需要引用下面的头文件“bh1750.h”。
代码清单:引用头文件
- //引用bh1750的头文件
- #include "bh1750.h"
- 定义引脚
本例中,我们用P5.1和P5.0分别用于I2C的SDA和SCA信号引脚,定义如下。
代码清单:定义用于I2C通信的引脚
- sbit SDA = P5^1; //定义I2C数据信号引脚SDA
- sbit SCL = P5^0; //定义I2C时钟信号引脚SCL
- 确定BH1750的I2C地址
BH1750有两种I2C地址,通过BH1750的ADDR引脚设置。
- ADDR = ‘H’,I2C地址为“1011100”,对应的8位地址为:10111000(0xB8,I2C读);10111001(0xB9,I2C写)。
- ADDR = ‘L’,I2C地址为“0100011”,对应的8位地址为:01000110(0x46,I2C读);01000111(0x47,I2C写)。
本例中BH1750的ADDR引脚为‘L’,程序中定义BH1750的I2C地址如下。
代码清单:I2C地址
- #define BH1750_ADDR_W 0x46 //I2C从机写地址
- #define BH1750_ADDR_R 0x47 //I2C从机读地址
- 初始化BH1750
本例中使用的是模拟I2C总线,因此I2C初始化部分只需将用于I2C通信的引脚P5.0和P5.1配置为准双向口即可,在代码清单如下。
代码清单:初始化BH1750
- /**************************************************************************************
- * 功 能 : 初始化BH1750
- * 参 数 : 无
- * 返回值 : 无
- **************************************************************************************/
- void BH1750_Init(void)
- {
- I2C_init();
- }
- 写入指令
BH1750使用前,需要写入指令进行配置,根据BH1750数据手册中的指令集表,定义其指令集如下。
代码清单:BH1750指令集
- #define BH1750_POWER_DOWN 0x00 //掉电:未激活状态
- #define BH1750_POWER_ON 0x01 //上电:等待测量指令
- #define BH1750_RESET 0x07 //复位重置:重置数字寄存器值,重置指令在断电模式下不起作用
- #define BH1750_CONT_H_MODE 0x10 //连续 H 分辨率模式:在1 lx 分辨率下开始测量,典型测量时间为
- 120ms
- #define BH1750_CONT_H_MODE2 0x11 //连续 H 分辨率模式2:在0.5 lx 分辨率下开始测量,典型测量时间
- 为120ms
- #define BH1750_CONT_L_MODE 0x13 //连续 L 分辨率模式:在4 lx 分辨率下开始测量,典型测量时间为
- 16ms
- #define BH1750_ONE_H_MODE 0x20 //单次 H 分辨率模式:在1 lx 分辨率下开始测量,典型测量时间为
- 120ms,测量后自动设置为断电模式
- #define BH1750_ONE_H_MODE2 0x21 //单次 H 分辨率模式2:在0.5 lx 分辨率下开始测量,典型测量时间
- 为 120ms,测量后自动设置为断电模式
- #define BH1750_ONE_L_MODE 0x23 //单次 L 分辨率模式:在4 lx 分辨率下开始测量,典型测量时间为
- 16ms,测量后自动设置为断电模式
- #define BH1750_CHG_MEAS_TIME_H 0x40 //设置测量时间( 高位 )
- #define BH1750_CHG_MEAS_TIME_L 0x60 //设置测量时间( 低位 )
BH1750的指令都是单字节的指令,写格式如下图所示。
图4:BH1750写格式
由此,编写BH1750写指令函数如下。
代码清单:向BH1750写入指令
- /**************************************************************************************
- * 功 能 : 向BH1750写入指令
- * 参 数 : reg_addr[in]:指令的地址
- * 返回值 : 无
- **************************************************************************************/
- void BH1750_WriteSingleReg(u8 reg_addr)
- {
- I2C_Start(); //起始信号
- I2C_SendData(BH1750_ADDR_W); //发送设备地址+写信号
- I2C_SendData(reg_addr); //BH1750内部寄存器地址
- I2C_Stop(); //发送停止信号
- }
- 单次高分辨率模式测量光照强度
单次高分辨率模式下,每次测量完成后BH1750会自动进入“POWER DOWN”,因此测量完成后无需发送“POWER DOWN”指令关闭BH1750。BH1750单次高分辨率模式测量步骤入下图所示。
图5:单次高分辨率模式测量步骤
由此,编写BH1750单次高分辨率模式测量函数如下。
代码清单:BH1750单次高分辨率模式测量
- /***************************************************************************************
- * 功 能 : BH1750单次高分辨率模式测量光照强度
- * 参 数 : 无
- * 返回值 : 光照强度
- ***************************************************************************************/
- float BH1750_ReadAmbientLight(void)
- {
- BH1750_WriteSingleReg(BH1750_POWER_ON); //上电(可省略)
- BH1750_WriteSingleReg(BH1750_ONE_H_MODE); //单次高分辨率模式
- //延时180ms,(高分辨率测量时间典型值:120ms,最大值180ms,所以,应等待至少180ms)
- delay_ms(180);
- I2C_Start(); //起始信号
- I2C_SendData(BH1750_ADDR_R); //发送设备地址+读信号
- bh1750_data.val_buf[0] = I2C_RecvData(); //读取光照强度高8位
- I2C_SendACK(); //发送ACK
- bh1750_data.val_buf[1] = I2C_RecvData(); //读取光照强度低8位
- I2C_SendNAK();
- I2C_Stop(); //发送停止命令,产生停止条件
- return (float)bh1750_data.val/1.2;
- }
- 主函数
主函数中完成相关的初始化,之后,在主循环中每秒测量一次光照强度,并通过串口输出测量结果。
代码清单:主函数
- /**************************************************************************
- 功能描述:主函数
- 参 数:无
- 返 回 值:int类型
- **************************************************************************/
- int main(void)
- {
- float lux_value;
- P3M1 &= 0xFE; P3M0 &= 0xFE; //设置P3.0为准双向口(串口1的RxD)
- P3M1 &= 0xFD; P3M0 |= 0x02; //设置P3.1为推挽输出(串口1的TxD)
- P2M1 &= 0x3F; P2M0 &= 0x3F; //设置P2.6~P2.7为准双向口(指示灯D1和D2)
- uart1_init(); //串口1初始化
- EA = 1; //使能总中断
- BH1750_Init(); //BH1750初始化
- delay_ms(10); //初始化后延时
- while(1)
- {
- lux_value = BH1750_ReadAmbientLight(); //执行一次测量
- printf("Measurement value: %.2flx\r\n",lux_value); //串口打印读取的数据
- delay_ms(1000); //延时1s,方便观察数据
- led_toggle(LED_1); //指示灯D1状态翻转,指示操作完成
- }
- }
-
-
- 硬件连接
-
-
如下图所示,将BH1750光照强度传感器安装J23插座上。
图6:硬件连接
-
-
-
- 实验步骤
-
-
- 解压“…\第3部分:配套例程源码”目录下的压缩文件“实验3-6-1:单次高分辨率模式测量光照强度(基于BH1750)实验”,将解压后得到的文件夹拷贝到合适的目录,如“D\STC8”(这样做的目的是为了防止中文路径或者工程存放的路径过深导致打开工程出现问题)。
- 双击“…\BH1750_SIG\project”目录下的工程文件“BH1750_SIG.uvproj”。
- 点击编译按钮编译工程,编译成功后生成的HEX文件“BH1750_SIG.hex”位于工程的“…\BH1750_SIG \Project\Object”目录下。
- 打开STC-ISP软件下载程序,下载使用内部IRC时钟,IRC频率选择:24MHz。
- 电脑上打开串口调试助手,选择开发板对应的串口号,将波特率设置为9600bps。
- 程序运行后,串口调试助手上可以看到测量结果,将BH1750传感器模块向光线亮的地方移动,可以看到测量结果增加,反之则减小,如下图所示。
图7:光照强度测量结果
-
-
- 光照强度测量实验(连续高精度模式)
-
- 注:本节的实验是在“实验3-6-1:单次高分辨率模式测量光照强度(基于BH1750)实验”的基础上修改,本节对应的实验源码是:“实验3-6-2:连续高分辨率模式测量光照强度(基于BH1750)实验”。
-
-
- 实验内容
-
-
单片机通过I2C向BH1750发送连续高分辨率测量指令,之后连续读取5次测量数据并通过串口输出数据。
-
-
-
- 代码编写
-
-
连续高分辨率模式和单次高分辨率测量流程类似, 流程如下图所示。
图8:连续高分辨率模式测量步骤
连续高分辨率模式和单次高分辨率的主要区别是:单次模式测量完成后,BH1750自己会自动进入“POWER DOWN”,而连续模式不会,因此,在连续模式下测量完成后,需要通过I2C发送指令让BH1750进入“POWER DOWN”。
由此,编写BH1750连续高分辨率模式测量函数如下。
代码清单:BH1750连续高分辨率模式测量
- /***************************************************************************************
- * 功 能 : BH1750连续高分辨率模式下测量光照强度
- * 参 数 : 无
- * 返回值 : 光照强度
- ***************************************************************************************/
- void BH1750_ReadAmbientLight_Cons(void)
- {
- u8 i;
- BH1750_WriteSingleReg(BH1750_POWER_ON); //上电(可省略)
- BH1750_WriteSingleReg(BH1750_CONT_H_MODE); //连续高分辨率模式
- for(i=0;i<5;i++) //连续读取5次
- {
- delay_ms(180); //延时180ms(高分辨率测量时间典型值:120ms,最大
- //值180ms,所以,应等待至少180ms)
- I2C_Start(); //起始信号
- I2C_SendData(BH1750_ADDR_R); //发送设备地址+读信号
- bh1750_data.val_buf[0] = I2C_RecvData(); //读取光照强度高8位
- I2C_SendACK(); //发送ACK
- bh1750_data.val_buf[1] = I2C_RecvData(); //读取光照强度低8位
- I2C_SendNAK();
- I2C_Stop(); //发送停止命令,产生停止条件
- printf("Measurement value: %.2flx\r\n",(float)bh1750_data.val/1.2); //串口打印读取的数据
- }
- BH1750_WriteSingleReg(BH1750_POWER_DOWN); //连续模式下测量完成后不会自动“POWER DOWN”,需要通过
- //I2C发送“POWER DOWN”指令
- }
主函数中完成相关的初始化,之后,在主循环中每秒调用一次连续测量函数,连续测量函数中会测量5次光照强度,并通过串口输出测量结果,代码清单如下
代码清单:主函数
- /**************************************************************************
- 功能描述:主函数
- 参 数:无
- 返 回 值:int类型
- **************************************************************************/
- int main(void)
- {
- P3M1 &= 0xFE; P3M0 &= 0xFE; //设置P3.0为准双向口(串口1的RxD)
- P3M1 &= 0xFD; P3M0 |= 0x02; //设置P3.1为推挽输出(串口1的TxD)
- P2M1 &= 0x3F; P2M0 &= 0x3F; //设置P2.6~P2.7为准双向口(指示灯D1和D2)
- uart1_init(); //串口1初始化
- EA = 1; //使能总中断
- BH1750_Init(); //BH1750初始化
- delay_ms(10); //初始化后延时
- while(1)
- {
- BH1750_ReadAmbientLight_Cons(); //连续读出数据,存储在BUF中
- delay_ms(2000); //延时2s,方便观察数据
- led_toggle(LED_1); //指示灯D1状态翻转,指示操作完成
- }
- }
-
-
-
- 硬件连接
-
-
同“实验3-6-1:单次高分辨率模式测量光照强度(基于BH1750)实验”。。
-
-
-
- 实验步骤
-
-
- 解压“…\第3部分:配套例程源码”目录下的压缩文件“实验3-6-2:连续高分辨率模式测量光照强度(基于BH1750)实验”,将解压后得到的文件夹拷贝到合适的目录,如“D\STC8”(这样做的目的是为了防止中文路径或者工程存放的路径过深导致打开工程出现问题)。
- 双击“…\BH1750_CONS\project”目录下的工程文件“BH1750_CONS.uvproj”。
- 点击编译按钮编译工程,编译成功后生成的HEX文件“BH1750_CONS.hex”位于工程的“…\BH1750_CONS\Project\Object”目录下。
- 打开STC-ISP软件下载程序,下载使用内部IRC时钟,IRC频率选择:24MHz。
- 电脑上打开串口调试助手,选择开发板对应的串口号,将波特率设置为9600bps。
- 程序运行后,串口调试助手上可以看到测量结果,将BH1750传感器模块向光线亮的地方移动,可以看到测量结果增加,反之则减小。