最近在整理智能家居项目时,发现一个有趣的现象:大多数树莓派爱好者止步于点亮LED或读取传感器数据这类基础实验,却很少将这些技能转化为实际可用的生活解决方案。这让我想起去年梅雨季节的经历——当时出差在外,突然暴雨导致书房窗户未关,损失了几本珍贵的绝版书。于是萌生了一个想法:用树莓派+PCF8591模数转换器打造一个雨天自动关窗系统,不仅能实时监测降雨情况,还能通过多种方式预警并自动触发关窗动作。
这个项目的独特价值在于:
| 组件 | 型号 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | 树莓派4B | 1 | 兼容3B+ |
| 模数转换 | PCF8591 | 1 | I2C接口 |
| 雨滴传感器 | YL-83 | 1 | 带模拟/数字双输出 |
| 执行机构 | SG90舵机 | 1 | 模拟关窗动作 |
| 其他 | 面包板/跳线 | 若干 | 建议使用防氧化镀金线 |
python复制# PCF8591与树莓派连接示意
# SDA -> GPIO2 (物理引脚3)
# SCL -> GPIO3 (物理引脚5)
# VCC -> 5V
# GND -> 地线
# 雨滴传感器接线
# AO -> PCF8591的AIN0
# DO -> GPIO17 (可选)
# VCC -> 5V
# GND -> 地线
# 舵机连接
# 信号线 -> GPIO18
# 红线 -> 5V
# 棕线 -> GND
注意:实际接线时建议先断开电源,使用万用表确认线路通断。PCF8591的I2C地址通常为0x48,可通过
i2cdetect -y 1命令验证。
遇到信号不稳定时,可以尝试:
gpio readall检查GPIO状态python复制# rain_monitor.py 主程序框架
import PCF8591 as ADC
import RPi.GPIO as GPIO
from servo_control import WindowServo
from notification import send_alert
class RainMonitor:
def __init__(self):
self.rain_threshold = 50 # 模拟量阈值
GPIO.setmode(GPIO.BCM)
ADC.setup(0x48)
def read_sensor(self):
return ADC.read(0) # 获取AIN0通道数据
def check_rain(self):
analog_val = self.read_sensor()
return analog_val < self.rain_threshold
通过Server酱实现微信推送:
python复制# notification.py
import requests
def send_wechat(msg):
api_url = "https://sc.ftqq.com/YOUR_KEY.send"
params = {
"text": "雨天警报",
"desp": msg
}
requests.post(api_url, params=params)
邮件通知方案(需配置SMTP):
python复制import smtplib
from email.mime.text import MIMEText
def send_email(subject, content):
msg = MIMEText(content)
msg['Subject'] = subject
msg['From'] = 'your_email@example.com'
msg['To'] = 'target@example.com'
with smtplib.SMTP('smtp.server.com', 587) as server:
server.starttls()
server.login('user', 'password')
server.send_message(msg)
python复制# servo_control.py
import RPi.GPIO as GPIO
import time
class WindowServo:
def __init__(self, pin=18):
self.pin = pin
GPIO.setup(pin, GPIO.OUT)
self.pwm = GPIO.PWM(pin, 50) # 50Hz
self.pwm.start(0)
def set_angle(self, angle):
duty = angle / 18 + 2
self.pwm.ChangeDutyCycle(duty)
time.sleep(0.5)
self.pwm.ChangeDutyCycle(0) # 防止抖舵
def close_window(self):
self.set_angle(90) # 关窗位置
def open_window(self):
self.set_angle(0) # 开窗位置
python复制def calibrate_threshold():
dry_val = ADC.read(0)
print("请滴加水滴...")
time.sleep(10)
wet_val = ADC.read(0)
threshold = (dry_val + wet_val) * 0.6
print(f"推荐阈值: {threshold:.0f}")
return threshold
使用SQLite存储历史数据:
python复制import sqlite3
from datetime import datetime
def log_rain_data(value):
conn = sqlite3.connect('rain.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS rain_log
(timestamp TEXT, value INTEGER)''')
c.execute("INSERT INTO rain_log VALUES (?,?)",
(datetime.now().isoformat(), value))
conn.commit()
conn.close()
防水处理:
电源管理:
bash复制# 设置树莓派定时开关机
sudo crontab -e
# 添加以下内容
0 6 * * * /sbin/shutdown -r now
0 23 * * * /sbin/shutdown -h now
异常处理机制:
python复制try:
while True:
if monitor.check_rain():
servo.close_window()
send_wechat("检测到降雨,已自动关窗")
time.sleep(60)
except Exception as e:
send_wechat(f"系统异常: {str(e)}")
这个项目最让我惊喜的是PCF8591的稳定性——连续运行三个月没有出现数据漂移。不过在实际部署时发现,安装在金属窗框附近会导致传感器读数异常,后来改用塑料支架解决了这个问题。