发布日期:2022-10-09 点击率:38
OPT3001 传感器特点:
OPT3001 感器的光谱响应与人眼的视觉响应紧密匹配,较强的 IR阻隔功能, 能够如人眼般准确测量光强且不受光源影响。 OPT3001 专门针对构建基于光线的人于保持高精度。 OPT3001 专门针对构建基于光线的人力差的光电二极管、 光敏电阻或其它环境光传感器的首选理想替代产品。测量范围可达 0.01lux 至 83k lux, 且内置有满量程设置功能, 无需手动选择满量程范围。此功能允许在 23位有效动态范围内进行光测量。数字操作可灵活用于系统集成。测量既可连续进行也可单次触发。控制和中断系统可自主操作,数字输出通过 I2C 以及 SMBus兼容的两线制串口报告。
OPT3001传感器特性如下:
目录
一、前言二、芯片介绍三、IIC通讯介绍IIC通讯过程简介IIC通讯实例BH1750的通讯过程
四、BH1750的命令五、BH1750编程教学六、测试七、总结
一、前言
之所以写这篇文章,原因有两个。
一是:有个师弟跟我说我发布的文章都偏向于工作者,能不能写一些大学生能用到的东西,我想了一下,确实是,我写的文章大多是我在工作中总结出来的心得,对于初学者来说确实有点难以理解。
二是:我觉得这个光照传感器很多大学生都能用到,但是网上的教程虽多却也不一定能够帮助大家深入了解这款传感器。大家更多的是看完攻略之后能够驱动,但是其实并不了解它的工作原理,想要在光照传感器的基础上增加别的功能也无从下手。
所以,我觉得我还是有必要写一篇更加详细更加深入的攻略来帮助大家理解。我觉得能驱动一个芯片和会驱动一个芯片是不一样的,如果你学会了如何去驱动一个芯片,那么换了别的类似的芯片你也能够得举一反三。不然的话你每次换一个芯片都只能去找人家写好的代码。
好了,废话不多说了,BH1750的讲解马上开始。(注:请一定要从头到尾看下去,粗略看一下也行,因为内容是环环相扣的,一直看,一直爽!!!)
我再多说一句,就一句,真的,接下来我讲的所有代码以及相关的所有文件都可以免费发给你们,链接在文章底部,自己去下载吧。
除了本文这个驱动外,还有另外一种使用方法,可以参考我发布的博文:
基于stm32驱动bh1750光照传感器的一种超简单的编程方法
二、芯片介绍
BH1750FVI是一款数字型光强度传感器集成芯片。某宝上面很多写着GY30模块,那些其实也是用BH1750FVI芯片,只不过是它把BH1750FVI芯片以及外围的一些电路做到了一个板子上面,然后把BH1750FVI的通讯引脚引出来方便你们用单片机控制而已。(话说大部分国产芯片都是这个套路,把人家的芯片拿过来,加一点外围电路,然后重新包一层外壳,换个型号,就变成自己的产品了)
电路工作原理:如图1所示,BH1750的内部由光敏二极管、运算放大器、ADC采集、晶振等组成。PD二极管通过光生伏特效应将输入光信号转换成电信号,经运算放大电路放大后,由ADC采集电压,然后通过逻辑电路转换成16位二进制数存储在内部的寄存器中(注:进入光窗的光越强,光电流越大,电压就越大,所以通过电压的大小就可以判断光照大小,但是要注意的是电压和光强虽然是一一对应的,但不是成正比的,所以这个芯片内部是做了线性处理的,这也是为什么不直接用光敏二极管而用集成IC的原因)。BH1750引出了时钟线和数据线,单片机通过I2C协议可以与BH1750模块通讯,可以选择BH1750的工作方式,也可以将BH1750寄存器的光照度数据提取出来。
引脚定义:
引脚号名称说明1VCC供电电压源正极2SCLIIC时钟线,时钟输入引脚,由MCU输出时钟3SDAIIC数据线,双向IO口,用来传输数据4ADDRIIC地址线,接GND时器件地址为 ,接VCC时器件地址为GND供电电压源负极
三、IIC通讯介绍
IIC通讯过程简介
既然BH1750是用IIC通讯的,那么我们就要先了解IIC的通讯原理。IIC由时钟线(SCL)和数据线(SDA)组成。时钟线,听这个名字就知道和时间有关系,没错,它其实管理着IIC的通讯时间。而数据线,顾名思义就是用来传输数据的线。那么时钟线和数据线它们是什么关系呢?你可以把时钟线理解为红绿灯,高电平是绿灯,低电平是红灯,而数据线传输的每一个数据则相当于一辆汽车,高电平是奔驰,低电平是宝马。当绿灯亮了的时候,汽车就可以过去,只不过这里的交通规则是每亮一次绿灯,只能通过一辆汽车。所以,IIC通讯的过程就是红绿灯交替闪烁(也就是时钟线输出方波脉冲),汽车跟着一辆一辆的过去,过去的是奔驰,就是传输了一个“1”,过去的宝马,就是传输了一个“0”,连续传输8次,就可以组成一个8位的二进制数,也就是一个字节的数据,反复这个过程就能实现两个设备之间的通讯。
好,上面已经大概讲解了IIC的通讯过程,那么下面来补充一些细节。IIC通讯的两个设备是有主从关系的,比如我们的单片机在这里就是主设备,BH1750是从设备。
时钟线是由主设备输出,从设备输入的,也就是单片机和BH1750通讯的时候,单片机的IO口要给SCL引脚输出一个方波脉冲,因为IIC设备支持的最大通讯频率一般都是400kHz,也就是说一个时钟周期(一个高电平加一个低电平为一个周期)不能小于2.5us。单片机输出时钟的时候一定要注意高低电平延时的时间,延时的时间越长,通讯的速率越慢。另外,时钟线不会一直输出脉冲,只会在需要通讯的时候输出,并且要遵循一定的规则。需要通讯的时候时钟线先要输出一个“起始信号”告诉从设备我要开始通讯了,其实就是电平由高到低跳变,但是这个高电平的持续时间不能太短,具体最少要多少时间需要看芯片手册,反正延长一点准没错。然后再根据固定的时间输出高低脉冲,直到到了要停止通讯的时候,时钟线要输出一个“结束信号”告诉从设备我不通讯了,其实就是电平一直拉高。
而数据线传输的数据是双向的,单片机可以给BH1750发数据,也可以读取BH1750的数据(也就是BH1750给单片机发)。需要注意的,单片机给BH1750发的数据不是随便发的,也要符合一定的规则。首先,单片机要先发一个器件地址(器件地址是7位的,详细的内容我后面再说),再发送一个读写位(0表示是写入,1表示读取),器件地址和读写位加起来刚好是一个字节,然后BH1750会给你回一个应答位,意思就是“我收到了”。然后单片机就可以接着发送数据了,每次都是以1个字节为间隔发。收也是类似的,只是把单片机发数据改成收数据,这里就不多说了,后面会详细讲。(注:器件地址是用来区分从设备的,因为有时候同一根时钟线和数据线可能会连接多个从设备,也就是说主设备发送的数据所有的从设备都可以收到,所以主设备要先发送一个器件地址,告诉所有的从设备我是给哪个设备发命令,其他设备收到了也不要执行)。
IIC通讯实例
下面我们看一个实际的例子。图2是OPT3001通讯的读写过程,(OPT3001是我在项目中用到一款低功耗光照传感器,和BH1750类似,也是IIC通讯协议,感兴趣的同学可以看一下我发之前的博文,有讲解这个IC的驱动方式),看懂了这个图你就理解IIC的通讯方式了,你就可以当着博主的面大声地说“你写的博文有毛用,你说的我全都知道”,如果你还有不理解的地方,那么就坐下来好好听我解说吧。
首先,我们看一下IIC的写入过程,最左边先是有一个“Start by Master”,也就是单片机先给一个“起始信号”,然后后面接着传输了8位数据(1 0 0 0 1 A1 A0 R/W)。其中,“1 0 0 0 1 A1 A0”是器件地址,因为这里的器件地址有4个可选,所以用了A1和A0表示,(注:BH1750只有2个器件地址),“R/W”是读写位,上面我有说到,这里是写入,所以这里的R/W应该是一个“0”。 接着是“ACK by OPT3001”,这是从设备给主设备发的应答,就是说“你发的数据我收到了,你可以接着发了”,然后接下来的RA7-RA0是寄存器地址(因为寄存器不止一个所以要先发地址,告诉它你接下来要把数据存到哪里),再后面的D15-D0是两个字节的数据(这些数据就是存到前面发的那个地址的寄存器里面)。
读取的过程和写入类似,先是“起始信号”,再是器件地址+读写位,接着是应答,然后开始接收数据(单片机的IO口要从输出改成输入了),D15-D0是接收到两个字节的数据,“ACK by Master”是单片机给OPT3001发的应答。(只要是接收的一方都要发应答,不应答的话通讯就会结束,比如读取的第二个字节后面的“No ACK by Master”)
好,如果你能坚持看到这里,那我敬你是条汉子!!如果你看懂了,那么恭喜你,如果没看懂,那也没关系,上面那是IIC一般的通讯方式,后面BH1750的通讯要更加简单。
(问:那你为什么不直接讲BH1750。答:我喜欢,你咬我呀,略略略….啪,略略啪,略别别….我错了。)
BH1750的通讯过程
其实前面之所以要先讲这个OPT3001而不是直接讲BH1750,是因为BH1750的IIC其实算是一个简化版的,不具有通用性,你学会了OPT3001的通讯方法,你再去驱动BH1750就很简单,相反,如果你只会驱动BH1750,那么换成别的IIC的芯片你就不一定会了。
好了,接下来我们来看一下BH1750的通讯,BH1750的通讯过程可以分成5步,中间3步如图3所示。
(啪啪,问:为什么要用英文的图,别以为我不知道有中文版的手册,说你是不是在装*。答:冤枉,真不是,那个中文版的图太糊了,而且英文版其实也不影响大家去看,老实说我是一个英语学渣,我还写了一篇博文讲述一个学渣如何看懂英文数据手册,有兴趣的同学可以看一下。真不是打广告哦。)
第1步:发送上电命令。(上电命令是0x01)。
因为这里没有图,我就不详细说了,发送的过程和第2步基本一致。就是把测量命令(0x10)改成上电命令(0x01)。
第2步:发送测量命令。
下面图片上的例子,ADDR引脚是接GND的,发送的测量命令是“连续高分辨率测量(0x10)”。
发送数据的过程和之前讲的OPT3001写入的过程基本一样,先是“起始信号(ST)”,接着是“器件地址+读写位”(器件地址我在上面引脚定义那里有写),然后是应答位,紧接着就是测量的命令“”(关于测量命令,下面会详细说明),然后应答,最后是“结束信号(SP)”。(相比于OPT3001的写入过程,BH1750少了一个发送寄存器地址的步骤,因为它只有一个寄存器,所以就没必要了)
第3步:等待测量结束。
测量的时间手册上面有写,我这里就不列出来了,高分辨率连续测量需要等待的时间最长,手册上面写的是平均120ms,最大值180ms,所以为了保证每次读取到的数据都是最新测量的,程序上面可以延时200ms以上,当然也不用太长,浪费时间。如果你用别的测量模式,等待时间都比这个模式要短。
第4步:读取数据。
先是“起始信号(ST)”,接着是“器件地址+读写位”,然后是应答位,紧接着接收1个字节的数据(单片机在这个时候要把SDA引脚从输出改成输入了),然后给BH1750发送应答,继续接收1个字节数据,然后不应答(因为我们接收的数据只有2个字节,收完就可以结束通讯了),最后是“结束信号(SP)”。
第5步:计算结果。
接收完两个字节还不算完成,因为这个数据还不是测量出来的光照强度值,我们还需要进行计算,计算公式是:光照强度 =(寄存器值[15:0] * 分辨率) / 1.2 (单位:勒克斯lx)
因为我们从BH1750寄存器读出来的是2个字节的数据,先接收的是高8位[15:8],后接收的是低8位[7:0],所以我们需要先把这2个字节合成一个数,然后乘上分辨率,再除以1.2即可得到光照值。
例如:我们读出来的第1个字节是0x12(0001 0010),第2个字节是0x53(0101 0011),那么合并之后就是0x1253(0001 0010 0101 0011),换算成十进制也就是4691,乘上分辨率(我用的分辨率是1),再除以1.2,最后等于3909.17 lx。
四、BH1750的命令
BH1750所有的命令都在图4。这次我用的是中文版的图,方便大家看,有点糊勿怪。 这里的指令虽然多,但是实际上如果仅仅是测光照值,只用两条就够了,通电指令和测量指令。这里的几条测量指令我就不详细说了,手册上是有讲的,如果后面你们需要的话我再补上吧。寄存器也只有一个,没什么好说的。(才不是因为懒也不是因为天天都要加班)
五、BH1750编程教学
下面的编程我以stm32为例,其实换成51,stm8或者别的单片机,程序也基本一样的,不同的单片机在程序上只是引脚配置的写法不太一样,别的基本没差别。
我的这个程序是用OLED显示光照强度的,想用串口,蓝牙或者别的方式也可以。
注:我下面展示的程序跟我发给你们的工程会有一点不一样,主要是备注,因为为了让你们更好理解,我展示的代码是加了很多备注的,而工程是以前的,备注会少一点。
1、IIC驱动代码
2、BH1750写入和读取的函数
3、BH1750初始化函数
4、获取光照度函数
5、main函数
六、测试
我这个程序是大学的时候做的一个课程设计,现在也没有实物可以测试了,我就发我以前报告里的图给你们看一下效果吧。图5是亮度大于100lx的时候,图6是低于100lx的时候。
七、总结
要驱动BH1750,或者其他IIC通讯的芯片,最好还是先了解IIC通讯的时序,了解通讯的原理,然后才是写驱动程序。驱动程序也可以分成三部分,第一部分是IIC通讯基本的协议(一般抄就完事了),第二部分是芯片的读写过程,需要根据实际芯片的通讯方式写。第三部分是指令控制相关的函数,BH175比较简单,只有测量和计算。有些可能还有多个设置不同的模式的函数,校验数据的函数等等,不过它们其实都是发送指令,只是发不同的指令执行不同的操作而已。
OPT3001的驱动教程你们可以大概看一下:
最后再说点闲话吧,写到这里刚好有点感触,其实写博文的初衷只是为了把工作中总结出来的一些经验记录下来,加强记忆。因为像我们这种做硬件研发的,经验是最值钱的,然后上传资源也只是为了赚点积分,因为还在大学那会想下载别人的程序的时候总是恨自己没有积分。后来发现我写的博文和上传的资源能够帮助到一些人,所以我就一直坚持着更新,哪怕每天加班也会抽空写一下文章写一下代码,即使我自己赚的积分其实一次都没用过。可能这就是传承吧,以前遇到问题的时候总能在前辈的博文中找到答案,现在轮到自己分享自己的经验给后来者了,希望我的文章也能够帮助到你。
本文用到的工程源码可以在下面的链接下载:
源码下载链接1: ,提取码:xs8o
源码下载链接2:提取码:abcd
除了本文这个驱动外,还有另外一种使用方法,可以参考我的博文:
基于stm32驱动bh1750光照传感器的一种超简单的编程方法
创作不易,希望你们尊重别人的劳动,点赞+关注支持一下吧,谢谢大家了,博主也会继续更新更多的大学生专栏,如果你们还有什么问题,可以评论留言或者私信给我。
#include
typedef unsigned char BYTE; //声明新的类型名来代替原有的类型名
typedef unsigned short WORD;
BYTE BUF[8]; //接收数据缓存区
uchar ge,shi,bai,qian,wan; //显示变量
int dis_data; //变量
int w_data;
void Multiple_Read_BH1750(); //连续的读取内部寄存器数据
//------------------------------------
bit BH1750_RecvACK(); //读ack
BYTE BH1750_RecvByte(); //IIC单个字节读
void conversion(uint temp_data) // 数据转换出 个,十,百,千,万
{
wan=temp_data/+0x30 ;
temp_data=temp_data%; //取余运算
qian=temp_data/1000+0x30 ;
temp_data=temp_data%1000; //取余运算
bai=temp_data/100+0x30 ;
temp_data=temp_data%100; //取余运算
shi=temp_data/10+0x30 ;
temp_data=temp_data%10; //取余运算
ge=temp_data+0x30;
}
//-------------------------------------------------------------------------------------//
//函数: wr_BH1750_one_data()
//功能: 写一位bh1750数据
//address: 芯片从地址
//saddress: 写寄存器地址
//w_data: 待写数据
//-------------------------------------------------------------------------------------//
void wr_BH1750_one_data(int saddress)
{
_nop_();
iic_start();
_nop_();
iic_sendbyte(address);
_nop_();
iic_sendbyte(saddress);
_nop_();
iic_sendbyte(w_data);
_nop_();
iic_stop();
_nop_();
}
//-------------------------------------------------------------------------------------//
//函数: rd_BH1750_one_data()
//功能: 读一位max数据
//address: 芯片从地址
//saddress: 读寄存器地址
//rda: 读出的数据
//-------------------------------------------------------------------------------------//
void rd_BH1750_one_data(void)
{
iic_start();
_nop_();
iic_sendbyte(address+1);
BUF[0]=iic_rcvbyte_nack(); //BUF[0]存储0x32地址中的数据
_nop_();
_nop_();
iic_start();
_nop_();
BUF[1]=iic_rcvbyte_nack();
_nop_();
_nop_();
iic_stop();
}
void uart_putchar(unsigned char dat)
{
SBUF=dat; //把数据送给sbuf缓存器中
while(TI!=1);//发送标志位 TI如果发送了为1,没发送为0,没发送等待,到了退出循环
TI=0; //到了,TI清为0
}
void uart_printf(unsigned char *buff)
{
while(*buff)
uart_putchar(*buff++);
}
//-------------------------------------------------------------------------------------//
//函数: 主程序
//功能:
//-------------------------------------------------------------------------------------//
main()
{
float temp;
unsigned char str[5];
TMOD=0x21;
SCON=0x50;
TH1=0xFD;
TL1=0xFD;
TR1=1;
TI=1;
//设置51的波特率为 9600 N 8 1
//51主频为11.0592MHz
wr_BH1750_one_data(0x01);
while(1)
{
wr_BH1750_one_data(0x01); // power on
wr_BH1750_one_data(0x10); // H- resolution mode 连续H分辨率模式 在1lx分辨率下开始测量。 测量时间一般为120ms。
delayms(180);
rd_BH1750_one_data();
dis_data=BUF[0];
dis_data=(dis_data<<8)+BUF[1];//合成数据,即光照数据
temp=(float)dis_data/1.2;
conversion(temp); //计算数据和显示
str[0]=wan;
str[1]=qian;
str[2]=bai;
str[3]=shi;
str[4]=ge;
uart_printf("light:");
uart_printf(str);
uart_printf(" lx");
delayms(200);
uart_printf("
");
delayms(100);
}
}
GY-30光照传感器.rar
2018-1-9 22:12 上传
点击文件名下载附件
下载积分: 黑币 -5
1004.25 KB, 下载次数: 46, 下载积分: 黑币 -5
中文数据手册加全程序
光照传感器作为传感器的一种,主要用于检测光照强度,工作原理是将光照强度值转为电压值,运用范围包括了现代化养殖业、农业、仓库存储等。基于上述要求在根据光照传感器的特点进行产品设计过程中,对于传感器芯片的选择上也需要进行多方位对比。
当光照传感器运用于货物监测设备过程中,首先需要保障光照传感器芯片的高性价比与实用性。Yunxion作为资产监测设备的开发公司,其产品包括了货物监测、人员定位、运输状态监测设备等。在相关设备开发过程中,经过全面的市场调查最终选择了OPT3001光照传感器,运用于资产监测设备中。
OPT3001 传感器特点:
OPT3001 感器的光谱响应与人眼的视觉响应紧密匹配,较强的 IR阻隔功能, 能够如人眼般准确测量光强且不受光源影响。 OPT3001 专门针对构建基于光线的人于保持高精度。 OPT3001 专门针对构建基于光线的人力差的光电二极管、 光敏电阻或其它环境光传感器的首选理想替代产品。测量范围可达 0.01lux 至 83k lux, 且内置有满量程设置功能, 无需手动选择满量程范围。此功能允许在 23位有效动态范围内进行光测量。数字操作可灵活用于系统集成。测量既可连续进行也可单次触发。控制和中断系统可自主操作,数字输出通过 I2C 以及 SMBus兼容的两线制串口报告。
OPT3001传感器特性如下:
封装如下图所示:
结论:OPT3001 传感器兼具精密的频谱响应和较强的 IR阻隔功能,以及单芯片照度计的设计。能够最大程度上保障资产监测设备在开发过程中,对光照传感器的选择符合设备的需求。
?
下一篇: PLC、DCS、FCS三大控
上一篇: 电气控制线路图控制原