第12章:环境光与紫外线传感器
本章介绍光敏传感器、紫外线传感器的工作原理、数据采集与应用场景。
12.1 光敏传感器
12.1.1 工作原理
光敏电阻(LDR)是一种光控电阻:
光线 → 光敏材料 → 电阻变化
强光 → 电阻小 → 分压电压低 → ADC 值小
弱光 → 电阻大 → 分压电压高 → ADC 值大
12.1.2 电路结构
VCC
│
[R1 10K] 上拉电阻
│
├───────── S (ADC 输入)
│
[LDR] 光敏电阻
│
GND
输出电压 = VCC × R_LDR / (R1 + R_LDR)
12.1.3 数据编码
| 光线强度 | ADC 值 | 说明 |
|---|---|---|
| 强光 | 低(0-20000) | LDR 阻值小 |
| 室内 | 中(20000-45000) | |
| 暗处 | 高(45000-65535) | LDR 阻值大 |
注意:不同厂家的模块可能有不同的电路设计,需要根据实际测试确定数值范围。
12.1.4 读取代码
'''
实验:光敏传感器读取
接线:S 端连接 GP26 (ADC0)
'''
from machine import ADC
import time
light_sensor = ADC(26)
def get_light_level():
"""读取光线强度"""
raw = light_sensor.read_u16()
# 反转:值越大表示越亮
inverted = 65535 - raw
percent = inverted / 65535 * 100
return raw, percent
while True:
raw, percent = get_light_level()
print(f"ADC: {raw:5d} 亮度: {percent:5.1f}%")
time.sleep(0.5)
12.1.5 智能照明控制
'''
实验:自动照明系统
环境变暗时自动开灯
'''
from machine import ADC, Pin, PWM
import time
light_sensor = ADC(26)
led = PWM(Pin(0))
led.freq(1000)
# 阈值设定
DARK_THRESHOLD = 45000 # 暗环境阈值
BRIGHT_THRESHOLD = 30000 # 亮环境阈值
def auto_brightness():
"""根据环境光自动调节 LED 亮度"""
ambient = light_sensor.read_u16()
if ambient > DARK_THRESHOLD:
# 环境暗,LED 全亮
duty = 65535
elif ambient < BRIGHT_THRESHOLD:
# 环境亮,LED 关闭
duty = 0
else:
# 中间区域,线性调节
duty = int((ambient - BRIGHT_THRESHOLD) /
(DARK_THRESHOLD - BRIGHT_THRESHOLD) * 65535)
led.duty_u16(duty)
return ambient, duty
while True:
ambient, duty = auto_brightness()
print(f"环境光: {ambient} LED: {duty/65535*100:.0f}%")
time.sleep(0.5)
12.2 紫外线传感器
12.2.1 传感器介绍
套件中的紫外线传感器主要针对太阳光中的 UVA 波段(320-400nm):
- 适用于 UV 指数监测
- 可用于紫外线消毒检测
- 火焰探测
12.2.2 UV 指数对照
| UV 指数 | 辐射强度 | 防护建议 |
|---|---|---|
| 0-2 | 低 | 无需防护 |
| 3-5 | 中等 | 戴帽子、太阳镜 |
| 6-7 | 高 | 涂防晒霜 |
| 8-10 | 很高 | 减少户外活动 |
| 11+ | 极高 | 避免外出 |
12.2.3 数据转换
UV 传感器输出电压与 UV 指数的关系(典型值):
def voltage_to_uv_index(voltage):
"""
电压转 UV 指数
基于 ML8511 传感器特性(仅供参考)
"""
if voltage < 0.99:
return 0
elif voltage >= 2.8:
return 11
else:
# 线性近似
uv_index = (voltage - 0.99) / (2.8 - 0.99) * 11
return uv_index
12.2.4 UV 检测代码
'''
实验:紫外线强度检测
接线:S 端连接 GP26 (ADC0)
'''
from machine import ADC
import time
uv_sensor = ADC(26)
def read_uv_index():
"""读取 UV 指数"""
raw = uv_sensor.read_u16()
voltage = raw * 3.3 / 65535
# UV 指数估算(需要根据实际传感器校准)
if voltage < 0.5:
uv = 0
else:
uv = (voltage - 0.5) / 0.2
return voltage, max(0, min(11, uv))
def get_uv_warning(uv_index):
"""获取防护建议"""
if uv_index < 3:
return "低风险"
elif uv_index < 6:
return "中等,建议防护"
elif uv_index < 8:
return "高风险,需要防护"
elif uv_index < 11:
return "很高风险,避免暴露"
else:
return "极端风险,禁止外出"
while True:
voltage, uv = read_uv_index()
warning = get_uv_warning(uv)
print(f"电压: {voltage:.2f}V UV指数: {uv:.1f} {warning}")
time.sleep(1)
12.2.5 UV 日志记录
'''
实验:UV 数据记录
定时记录 UV 强度,保存到文件
'''
from machine import ADC, RTC
import time
uv_sensor = ADC(26)
rtc = RTC()
LOG_INTERVAL = 60 # 每分钟记录一次
def log_uv_data():
"""记录 UV 数据到文件"""
raw = uv_sensor.read_u16()
timestamp = rtc.datetime()
# 格式化时间
time_str = f"{timestamp[0]}-{timestamp[1]:02d}-{timestamp[2]:02d} " \
f"{timestamp[4]:02d}:{timestamp[5]:02d}"
# 追加到日志文件
with open('uv_log.csv', 'a') as f:
f.write(f"{time_str},{raw}\n")
print(f"[{time_str}] UV ADC: {raw}")
# 创建日志文件头
with open('uv_log.csv', 'w') as f:
f.write("时间,ADC值\n")
while True:
log_uv_data()
time.sleep(LOG_INTERVAL)
12.3 火焰传感器
12.3.1 工作原理
火焰传感器检测火焰发出的特定波长红外光:
- 检测波长:760-1100nm
- 探测角度:约 60°
- 探测距离:0.5-1m(取决于火焰大小)
12.3.2 双输出模式
火焰传感器通常有两种输出:
- 数字输出 (D):超过阈值输出低电平
- 模拟输出 (A):与火焰强度成反比
12.3.3 检测代码
'''
实验:火焰传感器
接线:A 端→GP26, D 端→GP22
'''
from machine import ADC, Pin
import time
flame_analog = ADC(26)
flame_digital = Pin(22, Pin.IN)
def check_flame():
"""检测火焰"""
digital = flame_digital.value()
analog = flame_analog.read_u16()
# 数字:0=检测到火焰
# 模拟:值越小火焰越强
is_flame = digital == 0 or analog < 30000
return is_flame, analog
while True:
is_flame, intensity = check_flame()
if is_flame:
print(f"⚠️ 检测到火焰! 强度ADC: {intensity}")
else:
print(f"正常 ADC: {intensity}")
time.sleep(0.5)
12.3.4 火灾报警系统
'''
实验:火灾报警系统
'''
from machine import ADC, Pin
import time
flame_sensor = ADC(26)
buzzer = Pin(20, Pin.OUT)
led = Pin(0, Pin.OUT)
FLAME_THRESHOLD = 30000
def alarm_on():
"""触发报警"""
for _ in range(5):
buzzer.value(1)
led.value(1)
time.sleep(0.1)
buzzer.value(0)
led.value(0)
time.sleep(0.1)
while True:
flame = flame_sensor.read_u16()
if flame < FLAME_THRESHOLD:
print(f"🔥 火灾警报! ADC: {flame}")
alarm_on()
else:
buzzer.value(0)
led.value(0)
time.sleep(0.2)
12.4 声音传感器
12.4.1 工作原理
声音传感器使用驻极体麦克风(ECM)检测声音:
声波 → 麦克风 → 微弱电信号 → 放大电路 → 输出
12.4.2 输出特性
- 模拟输出:电压随声音强度变化
- 无声时:约 VCC/2(中点电压)
- 有声时:在中点上下波动
12.4.3 声音检测代码
'''
实验:声音传感器
接线:S 端连接 GP26
'''
from machine import ADC
import time
sound = ADC(26)
# 计算基准值(静音时的中点)
baseline = sum(sound.read_u16() for _ in range(100)) // 100
def detect_sound(threshold=5000):
"""检测声音"""
raw = sound.read_u16()
deviation = abs(raw - baseline)
return deviation > threshold, deviation
while True:
detected, level = detect_sound()
if detected:
print(f"检测到声音! 偏差: {level}")
time.sleep(0.05)
12.4.4 声控开关
'''
实验:拍手开灯
'''
from machine import ADC, Pin
import time
sound = ADC(26)
led = Pin(0, Pin.OUT)
THRESHOLD = 8000
CLAP_GAP = 300 # 两次拍手间隔 (ms)
baseline = sum(sound.read_u16() for _ in range(100)) // 100
last_clap = 0
clap_count = 0
led_state = False
while True:
raw = sound.read_u16()
deviation = abs(raw - baseline)
if deviation > THRESHOLD:
now = time.ticks_ms()
if time.ticks_diff(now, last_clap) > CLAP_GAP:
clap_count += 1
print(f"拍手 {clap_count}")
if clap_count >= 2:
led_state = not led_state
led.value(led_state)
print(f"LED {'开' if led_state else '关'}")
clap_count = 0
last_clap = now
# 等待声音结束
while abs(sound.read_u16() - baseline) > THRESHOLD / 2:
time.sleep_ms(10)
# 超时重置
if time.ticks_diff(time.ticks_ms(), last_clap) > 1000:
clap_count = 0
time.sleep_ms(10)
12.5 水滴传感器
12.5.1 工作原理
水滴传感器通过检测电导率变化检测液体:
- 干燥时:阻抗高,输出高电平
- 有水时:阻抗低,输出低电平(模拟值降低)
12.5.2 雨水检测
'''
实验:雨水检测
'''
from machine import ADC, Pin
import time
rain_sensor = ADC(26)
led = Pin(0, Pin.OUT)
DRY_THRESHOLD = 50000
WET_THRESHOLD = 30000
def check_rain():
"""检测降雨状态"""
raw = rain_sensor.read_u16()
if raw > DRY_THRESHOLD:
return "干燥", raw
elif raw > WET_THRESHOLD:
return "小雨", raw
else:
return "大雨", raw
while True:
status, raw = check_rain()
print(f"状态: {status} ADC: {raw}")
led.value(status != "干燥")
time.sleep(0.5)
12.6 本章小结
本章介绍了多种光电和环境传感器:
- 光敏传感器:
- 基于光敏电阻,阻值随光强变化
- 适用于自动照明控制
- 紫外线传感器:
- 检测 UVA 波段
- 输出电压与 UV 强度成正比
- 火焰传感器:
- 检测特定波长红外光
- 数字+模拟双输出
- 声音传感器:
- 驻极体麦克风检测声音
- 适用于声控开关
- 水滴传感器:
- 电导率检测
- 雨水/液体检测
下一章将学习温度与湿度传感器。