光照传感器在生活中应用很广泛,比如根据光线自动控制路灯的开关、自动窗帘根据光线进行调整、根据光线调节屏幕背光等等;光照强度的测量我们可以选用光敏电阻、光敏二极管或者类似本文这样的数字光照传感器。
下图中所示即为GY-302(BH1750FVI )光照传感器,他们除了封装不一样以外,驱动方法是一样的。
模块参数
- 采用ROHM原装BH1750FVI芯片
- 供电电源:3-5V
- 传感器内置16bitAD转换器,光照度范围:0-65535 Lx
- 结果直接数字输出,省略繁杂的计算,省略标定
- 标准NXP IIC通信协议
- 模块内部包含通信电平转换,与5V单片机IO直接连接
- 不区分环境光源,接近于视觉灵敏度的分光特性,可对广泛的亮度进行1勒克斯的高精度测定
光源在单位时间、向周围空间辐射并引起视觉的能量,称为光通量。用Φ表示,单位为流明(Lm)。单位面积上接受的光通量称为照度,用E表示,单位勒克司(Lx) 。E=Φ/S ,其中Φ-光通量(Lm), S-受照面积(㎡) 。1勒克司=1流明的光通量均匀分布在1平方米面积上的照度。
硬件原理图
因为我们选用的是模拟IIC的方式与GY-302模块通信,所以我们随意选择两个GPIO即可。
ADDR引脚为地址选择引脚,当ADDR引脚接地时,即R35电阻未焊接、R36选择10K电阻,此时地址为0x46(0b0100 0110);当ADDR引脚通过R35的10K电阻上拉至3.3V,R36未焊接时,地址为0xB8(0b1011 1000)。
本文实例中,我们选择ADDR接地。
时序图分析
对于I2C总线驱动的模块,都要实现I2C的起始信号、停止信号、发送应答三个函数。
起始信号
void BH1750_Start()
{
IIC_OUTPUT_MODE_SET();
IIC_SDA_OUT = 1;
IIC_SCL = 1;
delay_us(5);
IIC_SDA_OUT = 0;
delay_us(5);
IIC_SCL = 0;
}
停止信号
void BH1750_Stop()
{
IIC_OUTPUT_MODE_SET();
IIC_SDA_OUT = 0;
IIC_SCL = 1;
delay_us(5);
IIC_SDA_OUT = 1;
delay_us(5);
}
发送应答
/**************************************
发送应答信号
参数:ack (0:ACK 1:NAK)
**************************************/
void BH1750_SendACK(char ack)
{
IIC_OUTPUT_MODE_SET();
IIC_SCL = 0;
if(ack) IIC_SDA_OUT = 1;
else IIC_SDA_OUT = 0;
delay_us(2);
IIC_SCL = 1;
delay_us(5);
IIC_SCL = 0;
}
发送命令
发送命令的函数封装如下:
void Single_Write_BH1750(u8 REG_Address)
{
BH1750_Start();
BH1750_SendByte(SlaveAddress);
BH1750_RecvACK();
BH1750_SendByte(REG_Address);
BH1750_RecvACK();
BH1750_Stop();
}
上面函数封装与手册中下图是对应的:
上面截图中对应的寄存器的地址,我们可以看出,操作码为0001_0000就是下面截图所示指令,即Continuously H-Resolution Mode。
读取指令
读取命令的函数封装如下,读取的结果暂存至BUF数组中待用:
void Multiple_Read_BH1750()
{
BH1750_Start();
BH1750_SendByte(SlaveAddress+1);
BH1750_RecvACK();
BUF[0] = BH1750_RecvByte();
BH1750_SendACK(0);
BUF[1] = BH1750_RecvByte();
BH1750_SendACK(1);
BH1750_Stop();
delay_ms(5);
}
因为这个函数是读操作,所以SlaveAddress+1,上面函数封装与手册中下图是对应的:
求取实际光强值
float Get_Sunlight_Value()
{
int dis_data=0;
float temp;
u8 i=0;
Single_Write_BH1750(0x01); // power on
Single_Write_BH1750(0x10); // H- resolution mode
delay_ms(180); // 测量时间 max. 180ms
Multiple_Read_BH1750(); //连续读取数据,存储在BUF数组中
//合并数据并计算光强值
dis_data=BUF[0]; //BUF[0]为高8位
dis_data=(dis_data<<8)+BUF[1];
temp=(float)dis_data/1.2;
return
上面函数与手册中的测量流程对应:
至于结果值为什么除以1.2,是因为手册中给了一个例子供参考:
程序移植
修改GY302.h文件
修改GY302.c文件
程序移植的话,只需要修改上面两个文件对应位置即可。
实例演示
本实例演示可用于模拟根据光线强度自动调整窗帘的开关。
视频中步进电机及OLED屏的使用方法,请参见今天的2-4条网文。