發布日期:2022-10-09 點擊率:61
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三大控
上一篇: 電氣控制線路圖控制原