1. 项目概述从数字到模拟的传感器实践玩树莓派的朋友尤其是做物联网或者智能家居项目的肯定绕不开传感器。我们之前可能接触过很多数字传感器比如DHT11温湿度模块接上GPIO读取数据相对直接。但这次我们要聊点不一样的模拟电阻式土壤温度传感器。这个名字听起来有点专业但其实它的核心原理非常古老且经典——利用某些材料的电阻值会随温度变化的特性来测温。你可能在工业温控柜、老旧的热水器或者一些DIY的恒温箱里见过它的“亲戚”。为什么要在树莓派上折腾这个树莓派本身没有模拟输入引脚它是个纯数字世界的微电脑。而模拟传感器输出的是一段连续的电压信号这中间就存在一个“数字”与“模拟”的鸿沟。搞定这个传感器本质上是在学习如何让树莓派“听懂”模拟世界的声音。这对于想深入理解传感器原理、数据采集甚至想自己设计简单测量电路的朋友来说是一次绝佳的实践。它不像直接用现成的数字模块那么方便但能让你对“测量”这件事有更底层的认识。无论你是想做一个精准的盆栽土壤温度监控还是为你的小型发酵罐、鱼缸加装温度保护这个项目都能给你打下坚实的基础。2. 核心原理与传感器选型解析2.1 模拟电阻式温度传感器如何工作我们这次聚焦的传感器其核心是一个热敏电阻。热敏电阻是一种电阻值对温度变化极为敏感的半导体元件主要分为两类NTC和PTC。NTC是负温度系数热敏电阻温度升高电阻值下降PTC则相反。在温度测量领域尤其是我们常见的、成本较低的模块中NTC应用得最为广泛。它的工作原理很简单传感器被放置在被测环境中其内部NTC元件的电阻值会随环境温度变化。我们通过一个简单的电路将这个变化的电阻值转换成一个变化的电压值。树莓派无法直接读取电阻但通过模数转换器可以读取这个电压值再通过一套数学公式通常是查表法或利用Steinhart-Hart方程计算将这个电压值反推出对应的电阻值最终计算出温度值。这个过程听起来绕但每一步都有其物理和电子学基础。理解这个链条你就能举一反三应对其他类似的模拟电阻式传感器比如光敏电阻、压力应变片等。2.2 为什么需要ADC模块这是本项目的关键难点也是核心知识点。树莓派GPIO引脚只能识别高电平通常3.3V和低电平0V也就是数字信号0和1。而我们的传感器输出的电压信号是连续变化的模拟信号比如从0V到3.3V之间任意一个值。树莓派无法直接解读“2.1V”这个值。因此我们必须引入一个“翻译官”——模数转换器。ADC模块的作用就是将连续的模拟电压信号按照一定的精度“采样”并转换成树莓派能理解的数字值。这个精度通常用位数来表示比如常见的ADS1115是一个16位ADC。这意味着它可以将参考电压例如3.3V分成 2^16 65536 个等级。每个等级对应的电压变化非常微小约为 3.3V / 65536 ≈ 0.05mV从而实现了高精度的测量。注意切勿尝试将模拟传感器的输出直接连接到树莓派的GPIO引脚上。即使电压在0-3.3V范围内由于GPIO内部结构不确定的电流可能会损坏引脚或得到毫无意义且波动的读数。2.3 传感器与电路方案选择市面上常见的“模拟土壤温度传感器”模块通常已经做好了第一步转换它将热敏电阻集成在一个分压电路中。模块一般会引出三根线VCC供电接3.3V或5V、GND接地、AO模拟信号输出。这个AO引脚输出的电压就是经过分压电路处理后的信号。我们需要将这个AO引脚连接到ADC模块的某个输入通道上。整个系统的连接关系是树莓派 --- ADC模块 --- 传感器模块。方案对比简单分压电路 通用ADC成本最低最灵活但需要自己计算参数适合学习原理。本次教程将以此为重点。专用温度采集模块有些模块集成了热敏电阻和ADC甚至通过I2C直接输出数字温度值使用最简单但成本稍高且“黑盒化”不利于学习。使用DS18B20等数字传感器如果纯粹为了测土壤温度这是一个更简单、抗干扰能力更强的方案。但本课程的目标是掌握“模拟电阻式”传感器的使用方法因此不采用此方案。对于学习而言我们选择第一个方案。你需要准备树莓派4B其他型号亦可但引脚可能不同。一个ADC模块推荐ADS111516位精度I2C接口精度高且稳定或MCP300810位精度SPI接口更常见。本教程以ADS1115为例。一个模拟输出型的土壤温度传感器模块通常标有AO引脚。杜邦线若干。3. 硬件连接与电路搭建详解3.1 ADS1115模数转换器与树莓派连接ADS1115是一个通过I2C总线通信的ADC芯片它有4个模拟输入通道A0-A3非常适合我们这种多传感器或需要高精度的场景。连接非常简单因为I2C总线只需要两根数据线。连接步骤物理连接使用杜邦线将ADS1115模块与树莓派按照下表连接。ADS1115引脚树莓派GPIO引脚 (物理引脚编号)说明VDD3.3V(引脚1)供电。务必接3.3V接5V可能损坏ADS1115或树莓派GNDGND(引脚6, 9, 14, 20等任意一个)共地非常重要。SCLGPIO3 (SCL)(引脚5)I2C时钟线。SDAGPIO2 (SDA)(引脚3)I2C数据线。ADDRGND(或悬空)地址选择引脚。接地表示I2C地址为0x48。悬空则为0x49。我们接地即可。启用I2C接口在树莓派终端中运行sudo raspi-config选择Interface Options-I2C-Yes启用I2C支持。重启或在终端执行sudo i2cdetect -y 1来检测设备。如果看到48出现在网格中说明ADS1115连接成功。3.2 土壤温度传感器与ADS1115连接传感器模块通常有三根线红色(VCC)、黑色(GND)、黄色(AO)。连接如下传感器VCC-ADS1115的VDD或树莓派的3.3V。建议接在ADS1115的VDD上减少树莓派电源的负载波动。传感器GND-ADS1115的GND。传感器AO-ADS1115的A0我们使用第一个通道。至此硬件连接完成。整个信号流是传感器感知温度改变电阻导致AO引脚电压变化 - ADS1115的A0通道读取这个电压并转换为数字值 - 树莓派通过I2C从ADS1115读取这个数字值。4. 软件环境配置与核心代码实现4.1 安装必要的Python库我们需要Adafruit_ADS1x15库来方便地操作ADS1115。同时为了进行数学计算我们也会用到numpy。打开树莓派终端依次执行sudo pip3 install adafruit-circuitpython-ads1x15 sudo pip3 install numpy如果pip3未安装请先运行sudo apt install python3-pip。4.2 读取ADC原始值并转换为电压首先我们编写一个脚本来测试ADS1115是否能正常工作并读取传感器输出的电压值。# test_ads1115.py import time import board import busio import adafruit_ads1x15.ads1115 as ADS from adafruit_ads1x15.analog_in import AnalogIn # 创建I2C总线对象 i2c busio.I2C(board.SCL, board.SDA) # 创建ADS1115对象默认地址0x48 ads ADS.ADS1115(i2c) # 如果你将ADDR接到了VDD地址可能是0x49则需要ads ADS.ADS1115(i2c, address0x49) # 创建模拟输入通道对象连接到A0 chan AnalogIn(ads, ADS.P0) # ADS.P0 对应 A0 通道 print(按下 CtrlC 停止程序) try: while True: # 读取原始ADC值范围取决于增益默认是±4.096V下的16位有符号整数 raw_value chan.value # 读取转换后的电压值单位伏特 voltage chan.voltage print(ADC原始值: {:6d} | 电压值: {:6.3f}V.format(raw_value, voltage)) time.sleep(1) except KeyboardInterrupt: print(\n程序结束)运行这个脚本python3 test_ads1115.py。你应该能看到不断打印的ADC值和电压值。用手握住或吹气加热传感器观察电压值的变化。记录下当前室温下的电压值以及用手温加热后的电压值这有助于后续验证。4.3 从电压到温度的计算理解Steinhart-Hart方程这是最核心的一步。我们得到了电压但我们需要的是温度。这需要两步根据电路从电压反推热敏电阻的当前阻值。根据热敏电阻的阻值利用Steinhart-Hart方程计算温度。第一步计算热敏电阻阻值常见的传感器模块内部是一个简单的分压电路热敏电阻Rt和一个固定阻值的上拉电阻Rref通常是10kΩ串联。VCC3.3V加在这个串联电路上AO点测量的是热敏电阻两端的电压Vout。 根据分压公式Vout VCC * (Rt / (Rref Rt))转换一下得到Rt Rref * Vout / (VCC - Vout)这样我们就用测得的电压Vout、已知的VCC3.3V和Rref需要查看传感器规格书常见为10kΩ算出了热敏电阻的实时阻值Rt。第二步Steinhart-Hart方程计算温度NTC热敏电阻的阻值与温度之间的关系是非线性的最精确的描述是Steinhart-Hart方程1/T A B * ln(R) C * (ln(R))^3其中T是开尔文温度K。R是热敏电阻在当前温度T下的阻值Ω即我们上一步算出的Rt。A,B,C是热敏电阻的特性系数需要从供应商的数据手册中获取。对于精度要求不高的场合有时会使用简化的B值公式但Steinhart-Hart方程更精确。通常数据手册会给出25°C298.15K时的标称阻值例如10kΩ和B值例如3950。但B值公式在较大温度范围内误差较大。更可靠的方法是使用厂家提供的A, B, C系数。如果实在找不到可以尝试在网络上搜索你的传感器型号或使用的NTC型号如“MF52 10K 3950”对应的典型系数。4.4 完整的数据采集与温度转换程序下面我们将所有步骤整合到一个完整的Python程序中。假设我们已知传感器模块使用10kΩ上拉电阻热敏电阻为10kΩ标称值25°CB值为3950。请注意B值公式仅作示例实际应用请尽量获取准确的A,B,C系数。# soil_temperature_monitor.py import time import math import board import busio import adafruit_ads1x15.ads1115 as ADS from adafruit_ads1x15.analog_in import AnalogIn # ---------- 配置参数 ---------- VCC 3.3 # 供电电压 R_REF 10000.0 # 分压电路中的上拉电阻单位欧姆 (10kΩ) # 热敏电阻参数 (示例10K NTC, B3950) R_NOMINAL 10000.0 # 25°C时的标称电阻值 T_NOMINAL 298.15 # 标称温度单位开尔文 (25°C 298.15K) B_COEFFICIENT 3950.0 # B值 # 如果使用Steinhart-Hart系数请取消下面三行的注释并填写 # A_COEFF 1.0 / 298.15 - (1.0/3950.0)*math.log(10000) (1.0/3950.0**3)*(math.log(10000))**3 # 示例计算非真实值 # B_COEFF 1.0 / 3950.0 # C_COEFF 0.0 # ------------------------------ # 初始化I2C和ADS1115 i2c busio.I2C(board.SCL, board.SDA) ads ADS.ADS1115(i2c) ads.gain 2/3 # 设置增益为±6.144V这样3.3V输入在量程内 chan AnalogIn(ads, ADS.P0) def read_temperature_ntc(voltage): 使用B值参数计算温度精度一般适用于小范围 # 1. 计算热敏电阻当前阻值 Rt if voltage VCC: # 避免除零或无效值 voltage VCC - 0.001 Rt R_REF * voltage / (VCC - voltage) # 2. 使用B值公式计算温度 (T in Kelvin) # 公式: 1/T 1/T0 (1/B) * ln(Rt/R0) steinhart (1.0 / T_NOMINAL) (1.0 / B_COEFFICIENT) * math.log(Rt / R_NOMINAL) temp_k 1.0 / steinhart # 3. 转换为摄氏度 temp_c temp_k - 273.15 return temp_c, Rt def read_temperature_steinhart(voltage, A, B, C): 使用Steinhart-Hart系数计算温度精度高 Rt R_REF * voltage / (VCC - voltage) ln_r math.log(Rt) # Steinhart-Hart方程: 1/T A B*ln(R) C*(ln(R))^3 inv_t A B * ln_r C * (ln_r ** 3) temp_k 1.0 / inv_t temp_c temp_k - 273.15 return temp_c, Rt print(土壤温度监测开始... (使用B值公式)) print(按下 CtrlC 停止) try: while True: # 读取电压 voltage chan.voltage # 使用B值公式计算 temperature, resistance read_temperature_ntc(voltage) print(电压: {:5.3f} V | 电阻: {:8.2f} Ω | 温度: {:5.2f} °C.format( voltage, resistance, temperature)) time.sleep(2) # 每2秒读取一次 except KeyboardInterrupt: print(\n监测结束。)运行这个程序你就能在终端看到实时的土壤环境温度读数了。将传感器探头插入土壤中等待几分钟让读数稳定。5. 校准、优化与数据可视化5.1 传感器读数校准与精度提升拿到读数后你可能会发现它和实际温度有偏差。这很正常需要校准。简易两点校准法冰点校准将传感器探头与一个准确的温度计一起放入冰水混合物约0°C中等待读数稳定。记录下程序输出的温度值T_read_cold。室温或体温校准将传感器置于稳定的室温环境中用另一个温度计测出实际温度T_actual_room或者用手紧紧握住体温约36°C记录稳定后的读数T_read_hot。计算偏移量我们可以假设误差主要是线性的。计算一个简单的修正公式T_corrected a * T_read b。将两组数据代入解出系数a和b。T_actual_cold a * T_read_cold b(例如 0.0 a * 2.5 b)T_actual_hot a * T_read_hot b(例如 25.0 a * 26.3 b) 解这个二元一次方程组得到a和b然后在代码的最终输出前应用这个修正。更优方案获取准确的Steinhart-Hart系数联系传感器供应商获取所用NTC热敏电阻的精确A, B, C系数。或者如果你有精确的温度源恒温槽和万用表可以在多个温度点如0°C, 25°C, 50°C, 100°C测量对应的电阻值然后通过数学工具如Excel的回归分析或在线计算器拟合出这三个系数。使用这三个系数在-50°C到150°C范围内都能获得很高的精度。5.2 软件滤波让读数更稳定模拟信号容易受到干扰读数可能会跳动。我们可以通过软件滤波来平滑数据。移动平均滤波这是一种简单有效的方法。我们维护一个最近N次读数的列表输出它们的平均值。# 在循环外初始化一个列表 readings [] window_size 5 # 滤波窗口大小 while True: voltage chan.voltage temp, _ read_temperature_ntc(voltage) # 获取原始温度 readings.append(temp) if len(readings) window_size: readings.pop(0) # 移除最旧的读数 filtered_temp sum(readings) / len(readings) # 计算平均值 print(f原始温度: {temp:.2f} °C, 滤波后: {filtered_temp:.2f} °C) time.sleep(1)中值滤波对去除偶发的尖峰干扰脉冲噪声特别有效。取最近N次读数的中位数作为输出。import statistics # ... readings.append(temp) if len(readings) window_size: readings.pop(0) filtered_temp statistics.median(readings)在实际项目中可以结合使用例如先中值滤波去除野值再移动平均平滑。5.3 数据记录与简单可视化我们可以将数据写入文件以便长期分析。同时用简单的命令行图表也能直观看到趋势。数据记录到CSV文件import csv from datetime import datetime # 在程序开始时打开文件 with open(temperature_log.csv, a, newline) as csvfile: writer csv.writer(csvfile) # 如果是新文件可以写入标题行 # writer.writerow([Timestamp, Temperature_C]) while True: # ... 获取温度 ... timestamp datetime.now().strftime(%Y-%m-%d %H:%M:%S) writer.writerow([timestamp, filtered_temp]) csvfile.flush() # 确保数据立即写入磁盘 time.sleep(300) # 每5分钟记录一次使用Matplotlib进行简单绘图需安装sudo pip3 install matplotlib你可以写一个单独的分析脚本读取CSV文件并绘图。6. 常见问题排查与实战心得6.1 问题排查速查表现象可能原因排查步骤i2cdetect检测不到设备1. I2C未启用。2. 接线错误或接触不良。3. ADS1115模块损坏。4. 地址不对。1. 运行sudo raspi-config确认I2C已启用。2. 检查VCC、GND、SDA、SCL四根线是否接对、接牢。3. 用万用表测量ADS1115的VCC和GND之间是否有3.3V电压。4. 尝试sudo i2cdetect -y 1和sudo i2cdetect -y 0并检查ADDR引脚是否按预期接地或接VCC。能检测到设备但读取的电压值始终为0或满量程1. 传感器AO线未接或接错通道。2. 传感器模块损坏或供电不对。3. ADS1115增益设置不当。1. 确认传感器AO线接到了ADS1115的A0或其他你使用的通道。2. 用万用表测量传感器AO引脚对GND的电压用手加热看是否有变化。若无变化检查传感器VCC供电。3. 检查代码中ads.gain的设置确保其覆盖你的输入电压范围3.3V应使用2/3增益即±6.144V量程。温度读数完全不准或为极端值如几百或负几百摄氏度1. 分压电阻R_REF值设置错误。2. 热敏电阻参数R_NOMINAL, B值错误。3. 计算过程中出现数学错误如除零。1.最重要拆开或查看传感器模块确认上拉电阻的准确阻值。用万用表测量最可靠。2. 寻找传感器或热敏电阻的型号查询其数据手册获取精确参数。B值公式在低温或高温下误差极大。3. 在计算Rt的公式中加入判断避免VCC - voltage等于或接近0。打印出中间变量voltage,Rt的值辅助调试。读数跳动剧烈1. 电源噪声。2. 接线过长或接触电阻大。3. 传感器本身噪声大。1. 为树莓派使用质量好的电源适配器。在ADS1115的VCC和GND之间并联一个10uF和0.1uF的电容进行滤波。2. 缩短连接线确保杜邦线插紧。3. 实施软件滤波如移动平均、中值滤波。温度变化反应迟钝1. 传感器探头的热惰性。2. 软件滤波窗口设置过大。1. 这是物理特性选择热响应时间常数小的传感器。2. 减小滤波窗口window_size在稳定性和响应速度间取得平衡。6.2 实操心得与进阶建议接地是艺术模拟电路项目中“共地”至关重要。确保树莓派、ADS1115、传感器模块的GND都连接在一起并且接触良好。一点微小的地电位差都会引入噪声。供电要干净尽量使用树莓派上独立的3.3V引脚为ADC和传感器供电。如果条件允许使用一个低压差线性稳压器为模拟电路部分单独供电可以极大提高稳定性。参数是关键这个项目90%的精度取决于你输入的热敏电阻参数是否准确。花时间找到正确的R_REF、R_NOMINAL和A,B,C系数比优化任何代码都有效。如果找不到自己进行两点校准是最实用的方法。扩展思考多路监测ADS1115有4个通道你可以轻松连接4个土壤温度传感器分别监测花盆不同位置或不同花盆的温度。与湿度传感器结合常见的土壤湿度传感器也是模拟电阻式或电容式模拟输出你可以用另一个ADC通道连接它同时监测土壤的温湿度打造更完善的植物监护系统。加入告警功能当温度低于或高于某个阈值时让树莓派发送邮件、点亮LED或鸣响蜂鸣器。Web可视化使用Flask或Django框架将读取的温度数据通过网页实时显示出来并绘制历史曲线图。通过这个项目你真正打通了从物理世界温度到模拟信号电压再经过ADC转换到数字世界数值最后通过算法还原为物理量温度的完整链条。这个过程虽然比使用一个现成的数字传感器繁琐但它赋予了你对测量系统更深的理解和控制力这才是DIY和学习的乐趣所在。下次当你遇到其他模拟传感器时你会自信地说不过就是一个ADC分压电路加上对应的转换公式罢了。
树莓派模拟土壤温度传感器实践:从ADC原理到温度采集全解析
1. 项目概述从数字到模拟的传感器实践玩树莓派的朋友尤其是做物联网或者智能家居项目的肯定绕不开传感器。我们之前可能接触过很多数字传感器比如DHT11温湿度模块接上GPIO读取数据相对直接。但这次我们要聊点不一样的模拟电阻式土壤温度传感器。这个名字听起来有点专业但其实它的核心原理非常古老且经典——利用某些材料的电阻值会随温度变化的特性来测温。你可能在工业温控柜、老旧的热水器或者一些DIY的恒温箱里见过它的“亲戚”。为什么要在树莓派上折腾这个树莓派本身没有模拟输入引脚它是个纯数字世界的微电脑。而模拟传感器输出的是一段连续的电压信号这中间就存在一个“数字”与“模拟”的鸿沟。搞定这个传感器本质上是在学习如何让树莓派“听懂”模拟世界的声音。这对于想深入理解传感器原理、数据采集甚至想自己设计简单测量电路的朋友来说是一次绝佳的实践。它不像直接用现成的数字模块那么方便但能让你对“测量”这件事有更底层的认识。无论你是想做一个精准的盆栽土壤温度监控还是为你的小型发酵罐、鱼缸加装温度保护这个项目都能给你打下坚实的基础。2. 核心原理与传感器选型解析2.1 模拟电阻式温度传感器如何工作我们这次聚焦的传感器其核心是一个热敏电阻。热敏电阻是一种电阻值对温度变化极为敏感的半导体元件主要分为两类NTC和PTC。NTC是负温度系数热敏电阻温度升高电阻值下降PTC则相反。在温度测量领域尤其是我们常见的、成本较低的模块中NTC应用得最为广泛。它的工作原理很简单传感器被放置在被测环境中其内部NTC元件的电阻值会随环境温度变化。我们通过一个简单的电路将这个变化的电阻值转换成一个变化的电压值。树莓派无法直接读取电阻但通过模数转换器可以读取这个电压值再通过一套数学公式通常是查表法或利用Steinhart-Hart方程计算将这个电压值反推出对应的电阻值最终计算出温度值。这个过程听起来绕但每一步都有其物理和电子学基础。理解这个链条你就能举一反三应对其他类似的模拟电阻式传感器比如光敏电阻、压力应变片等。2.2 为什么需要ADC模块这是本项目的关键难点也是核心知识点。树莓派GPIO引脚只能识别高电平通常3.3V和低电平0V也就是数字信号0和1。而我们的传感器输出的电压信号是连续变化的模拟信号比如从0V到3.3V之间任意一个值。树莓派无法直接解读“2.1V”这个值。因此我们必须引入一个“翻译官”——模数转换器。ADC模块的作用就是将连续的模拟电压信号按照一定的精度“采样”并转换成树莓派能理解的数字值。这个精度通常用位数来表示比如常见的ADS1115是一个16位ADC。这意味着它可以将参考电压例如3.3V分成 2^16 65536 个等级。每个等级对应的电压变化非常微小约为 3.3V / 65536 ≈ 0.05mV从而实现了高精度的测量。注意切勿尝试将模拟传感器的输出直接连接到树莓派的GPIO引脚上。即使电压在0-3.3V范围内由于GPIO内部结构不确定的电流可能会损坏引脚或得到毫无意义且波动的读数。2.3 传感器与电路方案选择市面上常见的“模拟土壤温度传感器”模块通常已经做好了第一步转换它将热敏电阻集成在一个分压电路中。模块一般会引出三根线VCC供电接3.3V或5V、GND接地、AO模拟信号输出。这个AO引脚输出的电压就是经过分压电路处理后的信号。我们需要将这个AO引脚连接到ADC模块的某个输入通道上。整个系统的连接关系是树莓派 --- ADC模块 --- 传感器模块。方案对比简单分压电路 通用ADC成本最低最灵活但需要自己计算参数适合学习原理。本次教程将以此为重点。专用温度采集模块有些模块集成了热敏电阻和ADC甚至通过I2C直接输出数字温度值使用最简单但成本稍高且“黑盒化”不利于学习。使用DS18B20等数字传感器如果纯粹为了测土壤温度这是一个更简单、抗干扰能力更强的方案。但本课程的目标是掌握“模拟电阻式”传感器的使用方法因此不采用此方案。对于学习而言我们选择第一个方案。你需要准备树莓派4B其他型号亦可但引脚可能不同。一个ADC模块推荐ADS111516位精度I2C接口精度高且稳定或MCP300810位精度SPI接口更常见。本教程以ADS1115为例。一个模拟输出型的土壤温度传感器模块通常标有AO引脚。杜邦线若干。3. 硬件连接与电路搭建详解3.1 ADS1115模数转换器与树莓派连接ADS1115是一个通过I2C总线通信的ADC芯片它有4个模拟输入通道A0-A3非常适合我们这种多传感器或需要高精度的场景。连接非常简单因为I2C总线只需要两根数据线。连接步骤物理连接使用杜邦线将ADS1115模块与树莓派按照下表连接。ADS1115引脚树莓派GPIO引脚 (物理引脚编号)说明VDD3.3V(引脚1)供电。务必接3.3V接5V可能损坏ADS1115或树莓派GNDGND(引脚6, 9, 14, 20等任意一个)共地非常重要。SCLGPIO3 (SCL)(引脚5)I2C时钟线。SDAGPIO2 (SDA)(引脚3)I2C数据线。ADDRGND(或悬空)地址选择引脚。接地表示I2C地址为0x48。悬空则为0x49。我们接地即可。启用I2C接口在树莓派终端中运行sudo raspi-config选择Interface Options-I2C-Yes启用I2C支持。重启或在终端执行sudo i2cdetect -y 1来检测设备。如果看到48出现在网格中说明ADS1115连接成功。3.2 土壤温度传感器与ADS1115连接传感器模块通常有三根线红色(VCC)、黑色(GND)、黄色(AO)。连接如下传感器VCC-ADS1115的VDD或树莓派的3.3V。建议接在ADS1115的VDD上减少树莓派电源的负载波动。传感器GND-ADS1115的GND。传感器AO-ADS1115的A0我们使用第一个通道。至此硬件连接完成。整个信号流是传感器感知温度改变电阻导致AO引脚电压变化 - ADS1115的A0通道读取这个电压并转换为数字值 - 树莓派通过I2C从ADS1115读取这个数字值。4. 软件环境配置与核心代码实现4.1 安装必要的Python库我们需要Adafruit_ADS1x15库来方便地操作ADS1115。同时为了进行数学计算我们也会用到numpy。打开树莓派终端依次执行sudo pip3 install adafruit-circuitpython-ads1x15 sudo pip3 install numpy如果pip3未安装请先运行sudo apt install python3-pip。4.2 读取ADC原始值并转换为电压首先我们编写一个脚本来测试ADS1115是否能正常工作并读取传感器输出的电压值。# test_ads1115.py import time import board import busio import adafruit_ads1x15.ads1115 as ADS from adafruit_ads1x15.analog_in import AnalogIn # 创建I2C总线对象 i2c busio.I2C(board.SCL, board.SDA) # 创建ADS1115对象默认地址0x48 ads ADS.ADS1115(i2c) # 如果你将ADDR接到了VDD地址可能是0x49则需要ads ADS.ADS1115(i2c, address0x49) # 创建模拟输入通道对象连接到A0 chan AnalogIn(ads, ADS.P0) # ADS.P0 对应 A0 通道 print(按下 CtrlC 停止程序) try: while True: # 读取原始ADC值范围取决于增益默认是±4.096V下的16位有符号整数 raw_value chan.value # 读取转换后的电压值单位伏特 voltage chan.voltage print(ADC原始值: {:6d} | 电压值: {:6.3f}V.format(raw_value, voltage)) time.sleep(1) except KeyboardInterrupt: print(\n程序结束)运行这个脚本python3 test_ads1115.py。你应该能看到不断打印的ADC值和电压值。用手握住或吹气加热传感器观察电压值的变化。记录下当前室温下的电压值以及用手温加热后的电压值这有助于后续验证。4.3 从电压到温度的计算理解Steinhart-Hart方程这是最核心的一步。我们得到了电压但我们需要的是温度。这需要两步根据电路从电压反推热敏电阻的当前阻值。根据热敏电阻的阻值利用Steinhart-Hart方程计算温度。第一步计算热敏电阻阻值常见的传感器模块内部是一个简单的分压电路热敏电阻Rt和一个固定阻值的上拉电阻Rref通常是10kΩ串联。VCC3.3V加在这个串联电路上AO点测量的是热敏电阻两端的电压Vout。 根据分压公式Vout VCC * (Rt / (Rref Rt))转换一下得到Rt Rref * Vout / (VCC - Vout)这样我们就用测得的电压Vout、已知的VCC3.3V和Rref需要查看传感器规格书常见为10kΩ算出了热敏电阻的实时阻值Rt。第二步Steinhart-Hart方程计算温度NTC热敏电阻的阻值与温度之间的关系是非线性的最精确的描述是Steinhart-Hart方程1/T A B * ln(R) C * (ln(R))^3其中T是开尔文温度K。R是热敏电阻在当前温度T下的阻值Ω即我们上一步算出的Rt。A,B,C是热敏电阻的特性系数需要从供应商的数据手册中获取。对于精度要求不高的场合有时会使用简化的B值公式但Steinhart-Hart方程更精确。通常数据手册会给出25°C298.15K时的标称阻值例如10kΩ和B值例如3950。但B值公式在较大温度范围内误差较大。更可靠的方法是使用厂家提供的A, B, C系数。如果实在找不到可以尝试在网络上搜索你的传感器型号或使用的NTC型号如“MF52 10K 3950”对应的典型系数。4.4 完整的数据采集与温度转换程序下面我们将所有步骤整合到一个完整的Python程序中。假设我们已知传感器模块使用10kΩ上拉电阻热敏电阻为10kΩ标称值25°CB值为3950。请注意B值公式仅作示例实际应用请尽量获取准确的A,B,C系数。# soil_temperature_monitor.py import time import math import board import busio import adafruit_ads1x15.ads1115 as ADS from adafruit_ads1x15.analog_in import AnalogIn # ---------- 配置参数 ---------- VCC 3.3 # 供电电压 R_REF 10000.0 # 分压电路中的上拉电阻单位欧姆 (10kΩ) # 热敏电阻参数 (示例10K NTC, B3950) R_NOMINAL 10000.0 # 25°C时的标称电阻值 T_NOMINAL 298.15 # 标称温度单位开尔文 (25°C 298.15K) B_COEFFICIENT 3950.0 # B值 # 如果使用Steinhart-Hart系数请取消下面三行的注释并填写 # A_COEFF 1.0 / 298.15 - (1.0/3950.0)*math.log(10000) (1.0/3950.0**3)*(math.log(10000))**3 # 示例计算非真实值 # B_COEFF 1.0 / 3950.0 # C_COEFF 0.0 # ------------------------------ # 初始化I2C和ADS1115 i2c busio.I2C(board.SCL, board.SDA) ads ADS.ADS1115(i2c) ads.gain 2/3 # 设置增益为±6.144V这样3.3V输入在量程内 chan AnalogIn(ads, ADS.P0) def read_temperature_ntc(voltage): 使用B值参数计算温度精度一般适用于小范围 # 1. 计算热敏电阻当前阻值 Rt if voltage VCC: # 避免除零或无效值 voltage VCC - 0.001 Rt R_REF * voltage / (VCC - voltage) # 2. 使用B值公式计算温度 (T in Kelvin) # 公式: 1/T 1/T0 (1/B) * ln(Rt/R0) steinhart (1.0 / T_NOMINAL) (1.0 / B_COEFFICIENT) * math.log(Rt / R_NOMINAL) temp_k 1.0 / steinhart # 3. 转换为摄氏度 temp_c temp_k - 273.15 return temp_c, Rt def read_temperature_steinhart(voltage, A, B, C): 使用Steinhart-Hart系数计算温度精度高 Rt R_REF * voltage / (VCC - voltage) ln_r math.log(Rt) # Steinhart-Hart方程: 1/T A B*ln(R) C*(ln(R))^3 inv_t A B * ln_r C * (ln_r ** 3) temp_k 1.0 / inv_t temp_c temp_k - 273.15 return temp_c, Rt print(土壤温度监测开始... (使用B值公式)) print(按下 CtrlC 停止) try: while True: # 读取电压 voltage chan.voltage # 使用B值公式计算 temperature, resistance read_temperature_ntc(voltage) print(电压: {:5.3f} V | 电阻: {:8.2f} Ω | 温度: {:5.2f} °C.format( voltage, resistance, temperature)) time.sleep(2) # 每2秒读取一次 except KeyboardInterrupt: print(\n监测结束。)运行这个程序你就能在终端看到实时的土壤环境温度读数了。将传感器探头插入土壤中等待几分钟让读数稳定。5. 校准、优化与数据可视化5.1 传感器读数校准与精度提升拿到读数后你可能会发现它和实际温度有偏差。这很正常需要校准。简易两点校准法冰点校准将传感器探头与一个准确的温度计一起放入冰水混合物约0°C中等待读数稳定。记录下程序输出的温度值T_read_cold。室温或体温校准将传感器置于稳定的室温环境中用另一个温度计测出实际温度T_actual_room或者用手紧紧握住体温约36°C记录稳定后的读数T_read_hot。计算偏移量我们可以假设误差主要是线性的。计算一个简单的修正公式T_corrected a * T_read b。将两组数据代入解出系数a和b。T_actual_cold a * T_read_cold b(例如 0.0 a * 2.5 b)T_actual_hot a * T_read_hot b(例如 25.0 a * 26.3 b) 解这个二元一次方程组得到a和b然后在代码的最终输出前应用这个修正。更优方案获取准确的Steinhart-Hart系数联系传感器供应商获取所用NTC热敏电阻的精确A, B, C系数。或者如果你有精确的温度源恒温槽和万用表可以在多个温度点如0°C, 25°C, 50°C, 100°C测量对应的电阻值然后通过数学工具如Excel的回归分析或在线计算器拟合出这三个系数。使用这三个系数在-50°C到150°C范围内都能获得很高的精度。5.2 软件滤波让读数更稳定模拟信号容易受到干扰读数可能会跳动。我们可以通过软件滤波来平滑数据。移动平均滤波这是一种简单有效的方法。我们维护一个最近N次读数的列表输出它们的平均值。# 在循环外初始化一个列表 readings [] window_size 5 # 滤波窗口大小 while True: voltage chan.voltage temp, _ read_temperature_ntc(voltage) # 获取原始温度 readings.append(temp) if len(readings) window_size: readings.pop(0) # 移除最旧的读数 filtered_temp sum(readings) / len(readings) # 计算平均值 print(f原始温度: {temp:.2f} °C, 滤波后: {filtered_temp:.2f} °C) time.sleep(1)中值滤波对去除偶发的尖峰干扰脉冲噪声特别有效。取最近N次读数的中位数作为输出。import statistics # ... readings.append(temp) if len(readings) window_size: readings.pop(0) filtered_temp statistics.median(readings)在实际项目中可以结合使用例如先中值滤波去除野值再移动平均平滑。5.3 数据记录与简单可视化我们可以将数据写入文件以便长期分析。同时用简单的命令行图表也能直观看到趋势。数据记录到CSV文件import csv from datetime import datetime # 在程序开始时打开文件 with open(temperature_log.csv, a, newline) as csvfile: writer csv.writer(csvfile) # 如果是新文件可以写入标题行 # writer.writerow([Timestamp, Temperature_C]) while True: # ... 获取温度 ... timestamp datetime.now().strftime(%Y-%m-%d %H:%M:%S) writer.writerow([timestamp, filtered_temp]) csvfile.flush() # 确保数据立即写入磁盘 time.sleep(300) # 每5分钟记录一次使用Matplotlib进行简单绘图需安装sudo pip3 install matplotlib你可以写一个单独的分析脚本读取CSV文件并绘图。6. 常见问题排查与实战心得6.1 问题排查速查表现象可能原因排查步骤i2cdetect检测不到设备1. I2C未启用。2. 接线错误或接触不良。3. ADS1115模块损坏。4. 地址不对。1. 运行sudo raspi-config确认I2C已启用。2. 检查VCC、GND、SDA、SCL四根线是否接对、接牢。3. 用万用表测量ADS1115的VCC和GND之间是否有3.3V电压。4. 尝试sudo i2cdetect -y 1和sudo i2cdetect -y 0并检查ADDR引脚是否按预期接地或接VCC。能检测到设备但读取的电压值始终为0或满量程1. 传感器AO线未接或接错通道。2. 传感器模块损坏或供电不对。3. ADS1115增益设置不当。1. 确认传感器AO线接到了ADS1115的A0或其他你使用的通道。2. 用万用表测量传感器AO引脚对GND的电压用手加热看是否有变化。若无变化检查传感器VCC供电。3. 检查代码中ads.gain的设置确保其覆盖你的输入电压范围3.3V应使用2/3增益即±6.144V量程。温度读数完全不准或为极端值如几百或负几百摄氏度1. 分压电阻R_REF值设置错误。2. 热敏电阻参数R_NOMINAL, B值错误。3. 计算过程中出现数学错误如除零。1.最重要拆开或查看传感器模块确认上拉电阻的准确阻值。用万用表测量最可靠。2. 寻找传感器或热敏电阻的型号查询其数据手册获取精确参数。B值公式在低温或高温下误差极大。3. 在计算Rt的公式中加入判断避免VCC - voltage等于或接近0。打印出中间变量voltage,Rt的值辅助调试。读数跳动剧烈1. 电源噪声。2. 接线过长或接触电阻大。3. 传感器本身噪声大。1. 为树莓派使用质量好的电源适配器。在ADS1115的VCC和GND之间并联一个10uF和0.1uF的电容进行滤波。2. 缩短连接线确保杜邦线插紧。3. 实施软件滤波如移动平均、中值滤波。温度变化反应迟钝1. 传感器探头的热惰性。2. 软件滤波窗口设置过大。1. 这是物理特性选择热响应时间常数小的传感器。2. 减小滤波窗口window_size在稳定性和响应速度间取得平衡。6.2 实操心得与进阶建议接地是艺术模拟电路项目中“共地”至关重要。确保树莓派、ADS1115、传感器模块的GND都连接在一起并且接触良好。一点微小的地电位差都会引入噪声。供电要干净尽量使用树莓派上独立的3.3V引脚为ADC和传感器供电。如果条件允许使用一个低压差线性稳压器为模拟电路部分单独供电可以极大提高稳定性。参数是关键这个项目90%的精度取决于你输入的热敏电阻参数是否准确。花时间找到正确的R_REF、R_NOMINAL和A,B,C系数比优化任何代码都有效。如果找不到自己进行两点校准是最实用的方法。扩展思考多路监测ADS1115有4个通道你可以轻松连接4个土壤温度传感器分别监测花盆不同位置或不同花盆的温度。与湿度传感器结合常见的土壤湿度传感器也是模拟电阻式或电容式模拟输出你可以用另一个ADC通道连接它同时监测土壤的温湿度打造更完善的植物监护系统。加入告警功能当温度低于或高于某个阈值时让树莓派发送邮件、点亮LED或鸣响蜂鸣器。Web可视化使用Flask或Django框架将读取的温度数据通过网页实时显示出来并绘制历史曲线图。通过这个项目你真正打通了从物理世界温度到模拟信号电压再经过ADC转换到数字世界数值最后通过算法还原为物理量温度的完整链条。这个过程虽然比使用一个现成的数字传感器繁琐但它赋予了你对测量系统更深的理解和控制力这才是DIY和学习的乐趣所在。下次当你遇到其他模拟传感器时你会自信地说不过就是一个ADC分压电路加上对应的转换公式罢了。