本篇我们来学习环境光传感器。我们将为您介绍环境光传感器的工作原理、常见种类,如何查找和购买,以及通过MCU实际演示对于环境光传感器数据的读取过程。
环境光传感器|从零开始认识各种传感器
1. 什么是环境光传感器
环境光传感器是一种能够测量周围光线强度的传感器。在我们的日常生活中处处可以看到它的应用。
尤其是在手机,平板电脑等电子设备中都配备了环境光检测器,用来自动检测环境光的强度,从而实现对屏幕亮度的智能控制。在环境亮度较高时,屏幕显示会自动调高亮度,而当外界环境较暗时,会调节屏幕到低亮度。不仅有助于保护使用者的眼睛,而且可以有效降低设备的功耗。
图1 环境光传感器
2. 环境光传感器是如何工作的
环境光传感器的工作原理是应用了光电效应。 也就是某种材料吸收光子的能量后产生相应的电效应。我们以最常见的光电二极管来举例说明。 图中光电二极管通过的电流大小与照射到它上面的光线强度成正比,这个变化经过放大和数模转换处理后,再由智能芯片进行相应的处理,我们手机屏幕的亮度控制就是通过这样的电路逻辑完成的。
图2 环境光传感器工作原理
3. 常见的环境光传感器的种类
3.1 光敏电阻
光敏电阻是一种特殊的电阻,它常用的制作材料为硫化镉。 它具有在特定波长的光照射下其阻值迅速减小的特性。它的优点是体积小,灵敏度高,性能稳定,价格低,在自动控制和家用电器以及各种光控玩具中有着广泛应用。
图3 光敏电阻和其电路图符号
3.2 光电二极管和光电三极管
它们的内部都使用具有光敏特性的PN结,因此它们对光线的变化非常敏感,对于光线的响应速度要快于光敏电阻。具有很好的线性度以及低噪声特性。
光电二极管和光电三极管各有所长。光电二极管温度特性和输出线性度好、响应时间快;光电三极管可以看作是一种内置电流放大器的光电二极管,它具有更大的输出光电流能力,所以具有更高灵敏度。因此,在对输出线性要求较高或工作频率较高的场合应选光电二极管;如果是要求灵敏度高的光电控制电路,应选择光电三极管。
图4 光敏二极管和其电路图符号
图5 光敏三极管和其电路图符号
3.3 IC型环境光传感器
图6 IC型环境光传感器
目前大多数的光感应用要求模拟人眼对光线的感知,基于IC的单片光电二极管是最好的选择之一。因为它的高集成度,可以有效的补偿光电二极管对光线感知的差异。
图7 人眼对不同波长光线感知能力
图7中彩色图谱是人眼对于光线的感知能力,基本集中在可见光部分。而光电管(黑色曲线)的频率响应显然集中在红外线的高频段。为了消除这种感知差异,多数集成Ic式的光电传感器,例如MAX44009都内置了补偿用的红外光感二极管。两个传感器获得的信号经过ADC模块数字化后,交给DSP数字信号处理模块,可以精确的做出红外补偿。而且IC芯片具有数字接口输出,体积小巧的优点,是便携以及智能设备的最佳选择。
图8 MAX44009结构框图
4. 环境光传感器演示
最后,我们来演示如何使用配备显示屏的树莓派读取环境光传感器的数据并将结果显示出来。 这里我们选用的是一款贴片光电三极管TEMT6000。树莓派MCU通过模拟接口读取到的数字进行数字化处理后,在显示屏上直观地显示出来。
图9 树莓派读取环境光传感器过程展示
主控板卡:基于RP2040的带屏调试助手
以下是完整程序:
from breakout_colourlcd240x240 import BreakoutColourLCD240x240
from machine import Pin, SPI
from utime import sleep
import math,array
#------------------------------------------------------------------
######################################################################
#全局变量
current_temp = 0
#-------------------------------------------------------------------
#屏幕基本图形绘制
def display_init():
display.set_pen(0,255,0)
display.rectangle(58,30,13,160)
display.circle(64,190,6)
display.set_pen(255,0,0)
display.text("current", 150, 20, 194, 2)
display.text("light", 150, 35, 194, 2)
display.update()
for i in range(6):
display.set_pen(0,200,0)
display.pixel_span(80,27 + i*30,10)
display.text(str(100 - i *20), 100, 20+i*30, 194, 2)
display.set_pen(0,0,220)
if i < 5:
for j in range(4):
display.pixel_span(80,33 + j*6 + i * 30,5)
display.update()
display.update()
#---------------------------------------------------------------------
def display_change(temp, color):
global current_temp
current_temp = temp
display.set_pen(color[0], color[1], color[2])
display.rectangle(58,30,13,160)
display.circle(64,190,5)
display.set_pen(0,0,150)
display.rectangle(58,20,13,7+int((50-temp/2)/2)*6)
display.set_pen(0,0,0)
display.rectangle(150,50,90,40)
display.set_pen(0,255,0)
display.text(str(temp), 150, 50, 5, 5)
display.update()
#-----------------------------------------------------------------------
def read_adc():
CS.off()
data = TEMP_spi.read(2)
value = (data[1]) | (data[0]<<8)
value = value / 4096 *100
CS.on()
return value
#显示屏
width = BreakoutColourLCD240x240.WIDTH
height = BreakoutColourLCD240x240.HEIGHT
display_buffer = bytearray(width * height*2)
display = BreakoutColourLCD240x240(display_buffer)
color = [0,255,0]
display_init()
while True:
TEMP_spi = SPI(0,1000000,miso = Pin(20,Pin.OUT),sck = Pin(22,Pin.OUT))
CS = Pin(21,Pin.OUT)
display_change(round(read_adc(),1), color)