三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

不只是电压测量:用ADS1115和树莓派DIY一个高精度环境监测站(Python代码分享)

不只是电压测量:用ADS1115和树莓派DIY一个高精度环境监测站(Python代码分享)

不只是电压测量:用ADS1115和树莓派DIY一个高精度环境监测站(Python代码分享)

树莓派作为创客手中的瑞士军刀,其GPIO扩展能力让各种传感器有了用武之地。但当你需要同时监测多个环境参数时,内置ADC的精度和通道数往往捉襟见肘。ADS1115这款16位ADC芯片,配合Python的简洁语法,可以轻松搭建专业级的多通道监测系统——从土壤湿度到光照强度,甚至电池电压都能一手掌控。

1. 硬件选型与电路设计

ADS1115是TI推出的16位精度、4通道ADC转换器,相比树莓派内置的10位ADC,分辨率提升了64倍。其I2C接口与树莓派完美兼容,工作电压2.0-5.5V的特性也使其能适应各种传感器场景。

典型接线方案

  • SDA → 树莓派GPIO2(物理引脚3)
  • SCL → 树莓派GPIO3(物理引脚5)
  • VDD → 3.3V电源
  • GND → 共地
  • A0-A3 → 传感器信号输入

注意:ADS1115的ALERT引脚需要接10kΩ上拉电阻,输入信号线建议串联499Ω电阻并并联4.7nF电容滤波

传感器选型参考表:

监测参数推荐传感器输出范围转换公式
土壤湿度FC-28电压型0-3V湿度% = (Vout/3)*100
光照强度BH17500-3.3VLux = Vout*1000/3.3
环境温度LM350-1.5V℃ = Vout*100
电池电压电阻分压电路0-5VVin = Vout*(R1+R2)/R2

2. Python驱动开发实战

抛弃复杂的寄存器操作,我们用smbus2库三行代码就能启动ADS1115:

import smbus2 bus = smbus2.SMBus(1) # 树莓派I2C总线编号 DEVICE_ADDRESS = 0x48 # ADS1115默认地址

四步完成数据采集

  1. 配置转换寄存器:
    config = 0x8583 # AIN0-GND, 4.096V量程, 128SPS bus.write_i2c_block_data(DEVICE_ADDRESS, 0x01, [(config>>8)&0xFF, config&0xFF])
  2. 触发单次转换:
    bus.write_byte_data(DEVICE_ADDRESS, 0x01, 0x85)
  3. 等待转换完成(约8ms):
    import time time.sleep(0.01)
  4. 读取转换结果:
    data = bus.read_i2c_block_data(DEVICE_ADDRESS, 0x00, 2) raw = (data[0] << 8) | data[1]

电压转换公式:

def raw_to_voltage(raw, gain=4.096): return (raw * gain) / 32767.0

3. 多传感器融合方案

利用ADS1115的4路差分输入,可以设计多种组合方案:

方案一:独立单端测量

CHANNEL_CONFIG = { 0: 0x8583, # AIN0 1: 0x9583, # AIN1 2: 0xA583, # AIN2 3: 0xB583 # AIN3 } def read_channel(ch): bus.write_i2c_block_data(DEVICE_ADDRESS, 0x01, [(CHANNEL_CONFIG[ch]>>8)&0xFF, CHANNEL_CONFIG[ch]&0xFF]) # ...后续读取操作相同

方案二:差分测量组合

  • AIN0-AIN1:土壤湿度差值监测
  • AIN2-AIN3:温度传感器桥接电路

提示:差分模式能有效抑制共模噪声,特别适合长导线传输场景

4. 数据可视化与持久化

采集到的数据可以通过Flask快速构建Web仪表盘:

from flask import Flask, render_template import sqlite3 app = Flask(__name__) @app.route('/') def dashboard(): conn = sqlite3.connect('sensor.db') data = conn.execute('SELECT * FROM readings ORDER BY time DESC LIMIT 10') return render_template('dashboard.html', readings=data)

定时采集脚本示例:

import schedule def job(): humidity = read_channel(0) light = read_channel(1) timestamp = datetime.now() conn = sqlite3.connect('sensor.db') conn.execute('INSERT INTO readings VALUES (?,?,?)', (timestamp, humidity, light)) conn.commit() schedule.every(5).minutes.do(job) while True: schedule.run_pending() time.sleep(1)

数据库表结构建议:

CREATE TABLE readings ( time TIMESTAMP PRIMARY KEY, humidity REAL, light_intensity REAL, temperature REAL, battery_voltage REAL );

5. 实战技巧与避坑指南

精度优化三要素

  1. 电源去耦:在VDD和GND之间并联10μF+0.1μF电容
  2. 信号滤波:输入通道串联电阻+电容组成低通滤波
  3. 软件校准:采集已知电压值计算比例系数

常见问题排查

  • I2C设备未发现:检查i2cdetect -y 1输出
  • 数据跳动大:尝试降低采样率或增加滤波电容
  • 负电压测量:使用AINx作为参考地构成伪差分输入

性能测试数据

采样率(SPS)实际耗时(ms)噪声水平(mV)
81250.05
1287.80.15
8601.20.8

对于需要长时间运行的项目,建议:

# 在脚本开头添加自启动逻辑 if not os.path.exists('/tmp/sensor_pid'): with open('/tmp/sensor_pid', 'w') as f: f.write(str(os.getpid())) else: print("Already running") exit()

这个项目最让我惊喜的是ADS1115的稳定性——连续运行两周,数据漂移不超过0.5%。特别是在清晨监测露水形成时,16位分辨率能清晰捕捉到湿度曲线的每一个微妙变化。

← 返回列表