树莓派ADS1115 ADC模块实战:高精度模拟信号采集与噪声处理

发布时间:2026/8/2 10:32:30
树莓派ADS1115 ADC模块实战:高精度模拟信号采集与噪声处理 1. 项目缘起为什么树莓派需要一个外置ADC如果你玩过树莓派大概率会尝试过用它的GPIO口去读取一些模拟传感器比如光敏电阻、电位器或者土壤湿度传感器。然后你就会发现一个尴尬的事实树莓派本身没有模拟输入引脚。是的这个强大的微型计算机在处理数字信号上无所不能但在面对真实世界里连续变化的电压信号时却像个“睁眼瞎”。它所有的GPIO都是数字的只能识别高电平通常是3.3V和低电平0V。你想知道环境光线是“有点亮”还是“非常亮”对不起它只能告诉你现在是“亮”高电平还是“暗”低电平至于具体有多亮它无能为力。这就是ADC模数转换器登场的时候。ADC就像一个翻译官把模拟世界连续的语言电压翻译成数字世界能理解的离散数字。市面上有大量廉价的ADC模块而ADS1115是其中口碑和性能都非常突出的一款。它拥有4个差分输入通道或2个单端通道16位的分辨率通过I2C接口与树莓派通信。16位意味着它能将输入的电压范围比如0-3.3V划分为 2^16 65536 个等级理论上的电压分辨率为 3.3V / 65536 ≈ 0.05mV。这个精度对于绝大多数业余电子项目和很多专业应用来说已经绰绰有余了。所以这个项目的核心就是为你的树莓派装上“模拟世界的眼睛”让它能够精确地感知温度、压力、光照、声音等一切由模拟信号表征的物理量。无论是搭建一个家庭气象站、一个高精度电子秤还是一个电池电压监控系统ADS1115都是一个可靠且高性价比的起点。2. ADS1115模块深度解析不只是“插上就用”拿到一个ADS1115模块它通常长这样一块比指甲盖稍大的PCB板上面最显眼的是那个黑色的16脚芯片ADS1115本体旁边可能有一个蓝色的可调电位器用于设置I2C地址以及几个排针。很多人会直接按照教程接线、安装库、读取数据但如果你能理解它内部的运作机制和关键配置就能避开很多坑并充分发挥其性能。2.1 核心芯片ADS1115的“内力”ADS1115是德州仪器TI出品的一款超小型、低功耗、16位精度的Δ-Σ型ADC。我们来拆解这几个关键词Δ-Σ型Delta-Sigma这是一种通过过采样和噪声整形来实现高精度的ADC架构。简单理解它不像传统的逐次逼近型SARADC那样直接比较电压而是通过一个反馈环路用很高的频率远高于最终输出数据速率去“跟踪”输入电压并将量化噪声“推”到高频段再通过数字滤波器滤掉从而在低速应用中获得极高的分辨率和线性度。这意味着ADS1115在低速、高精度的测量场景如传感器信号中表现尤为出色但对高速变化的信号则不适合。16位精度这是它的分辨率。但要注意分辨率不等于精度。精度还受到参考电压稳定性、内部噪声、增益误差、偏移误差等因素影响。ADS1115在数据手册中给出了“无失码”的保证这意味着它的16位输出都是有效的不会出现跳码这是其品质的体现。可编程增益放大器PGA这是ADS1115的一大亮点。PGA可以在ADC前端对微小信号进行放大从而充分利用ADC的量程提高测量小信号时的有效分辨率。它的增益可设置为2/3倍、1倍、2倍、4倍、8倍、16倍。例如当你测量一个最大只有±0.256V的差分信号时可以将PGA增益设置为16倍这样信号就会被放大到接近ADC的满量程±4.096V / 16 ±0.256V此时1个LSB最低有效位对应的电压值最小测量最精确。数据速率ADS1115的转换速度是可调的从8SPS每秒采样8次到860SPS。速率越低噪声抑制能力越强精度通常越高速率越高能捕捉更快变化的信号。你需要根据应用在速度和精度之间做权衡。2.2 模块电路那些容易被忽略的细节市面上常见的模块除了ADS1115芯片周围电路通常包括电平转换电路ADS1115芯片本身是兼容3.3V和5V逻辑的。但模块为了通用性常会集成一个如TXS0108E之类的双向电平转换器使得模块的VCC和I2C引脚可以接受3.3V或5V供电并能与不同电压逻辑的主机如5V的Arduino或3.3V的树莓派安全通信。这一点非常重要这意味着你可以放心地用树莓派的3.3V和GPIO直接连接该模块无需担心烧毁。地址选择跳线ADS1115的I2C地址由ADDR引脚的电平决定。模块通常通过一个跳线帽或焊点将ADDR引脚连接到GND、VDD、SDA或SCL从而产生4个不同的I2C地址0x48, 0x49, 0x4A, 0x4B。这允许你在同一I2C总线上挂载最多4个ADS1115模块实现最多16通道的模拟输入扩展。基准电压ADS1115使用电源电压VDD作为内部基准。因此一个干净、稳定的电源对测量精度至关重要。模块上的滤波电容就是为此服务的。如果你的测量要求极高可以考虑使用外部基准电压源模块但这对绝大多数应用来说不是必须的。输入保护一些好一点的模块会在模拟输入引脚上串联小电阻并加上钳位二极管用于防止过压输入损坏芯片。但不要指望它有很强的保护能力在连接未知信号源时自己额外设计分压、限流或保护电路仍是好习惯。3. 硬件连接与系统配置从物理连接到软件准备在开始写代码之前正确的硬件连接和系统环境是成功的一半。3.1 物理连接四根线搞定连接非常简单只需要四根线树莓派 GPIO引脚 (物理编号)ADS1115模块引脚作用Pin 1 (3.3V Power)VCC提供3.3V电源。强烈建议使用3.3V以匹配树莓派GPIO逻辑电平。Pin 6 (Ground)GND共地。这是所有电路参考的基础必须连接。Pin 3 (GPIO2, SDA1)SDAI2C数据线。Pin 5 (GPIO3, SCL1)SCLI2C时钟线。注意务必确认你的模块支持3.3V逻辑。绝大多数通用模块都支持。连接时最好断开树莓派电源。连接后给模块上电通常能看到一个电源指示灯亮起。3.2 启用树莓派I2C接口树莓派的I2C接口默认是关闭的需要手动开启。在终端中运行sudo raspi-config。选择Interface Options-I2C。当询问是否启用ARM I2C接口时选择Yes。退出raspi-config并重启树莓派。3.3 安装必要的软件工具重启后安装I2C工具和Python库。# 更新软件包列表 sudo apt update sudo apt upgrade -y # 安装i2c-tools用于检测I2C设备 sudo apt install i2c-tools -y # 安装Python的smbus库这是与I2C设备通信的基础 sudo apt install python3-smbus -y # 安装Adafruit_ADS1x15库这是专门为ADS1015/ADS1115编写的、易于使用的Python库 pip3 install adafruit-circuitpython-ads1x15如果pip3命令找不到可能需要先安装python3-pipsudo apt install python3-pip -y。3.4 检测设备地址连接好模块并安装工具后运行以下命令检测ADS1115是否被正确识别sudo i2cdetect -y 1如果一切正常你会在输出表格中看到一个十六进制数字例如0x48。这个地址取决于你模块上ADDR引脚的设置通常默认是接地地址为0x48。记下这个地址后续编程会用到。4. 编程实战从基础读取到高级应用现在进入最核心的部分编写Python代码来读取数据。我们将使用Adafruit的库因为它封装了底层细节让操作变得非常简单。4.1 基础单次读取读取一个电位器的电压假设你将一个电位器的两端分别接模块的A0和GND中间滑动端接A0与一端相同构成单端输入。我们来读取其电压值。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) # 如果你修改了地址例如0x49则使用ads ADS.ADS1115(i2c, address0x49) # 创建模拟输入通道对象参数为ADS对象和通道号0-3 # 单端输入测量该引脚与GND之间的电压 chan0 AnalogIn(ads, ADS.P0) # 对应模块上的A0引脚 # 也可以配置为差分输入例如测量A0和A1之间的电压差 # chan_diff AnalogIn(ads, ADS.P0, ADS.P1) print(按下 CtrlC 停止程序) try: while True: # 直接读取电压值单位伏特 print(电压: {:.3f}V.format(chan0.voltage)) # 读取原始ADC值0-32767对于单端正电压-32768-32767对于差分 # print(原始值:, chan0.value) time.sleep(1) except KeyboardInterrupt: print(\n程序结束)这段代码的核心是AnalogIn类它自动处理了从原始ADC值到电压的转换。转换公式基于你设置的增益默认增益为1量程为±4.096V和参考电压。4.2 关键配置增益、速率与模式基础的读取往往不够我们需要根据传感器特性调整ADC的配置。这需要通过ADS1115对象直接操作其配置寄存器。import time import board import busio import adafruit_ads1x15.ads1115 as ADS from adafruit_ads1x15.ads1x15 import Mode from adafruit_ads1x15.analog_in import AnalogIn i2c busio.I2C(board.SCL, board.SDA) ads ADS.ADS1115(i2c) # --- 关键配置示例 --- # 1. 设置增益PGA。测量小信号时提高增益。 # 可选值GAIN_TWOTHIRDS (±6.144V), GAIN_ONE (±4.096V), GAIN_TWO (±2.048V), # GAIN_FOUR (±1.024V), GAIN_EIGHT (±0.512V), GAIN_SIXTEEN (±0.256V) ads.gain GAIN_SIXTEEN # 例如用于测量热电偶等毫伏级信号 # 2. 设置数据速率。在噪声和速度间权衡。 # 可选值RATE_8, RATE_16, RATE_32, RATE_64, RATE_128, RATE_250, RATE_475, RATE_860 ads.data_rate RATE_128 # 128 SPS一个兼顾精度和速度的常用值 # 3. 设置操作模式。 # Mode.CONTINUOUS: 连续转换模式ADC不停转换读取速度最快但功耗稍高。 # Mode.SINGLE: 单次转换模式默认每次读取时启动一次转换转换完成自动进入省电模式功耗极低适用于电池供电。 ads.mode Mode.SINGLE # 创建通道对象配置会在读取时生效 chan0 AnalogIn(ads, ADS.P0) print(增益: x16, 数据速率: 128SPS, 模式: 单次) try: while True: # 在单次模式下每次读取都会触发一次转换 print(电压: {:.6f}V.format(chan0.voltage)) # 高增益下显示更多小数位 time.sleep(0.5) # 即使休眠时间短于转换时间库也会等待转换完成 except KeyboardInterrupt: print(结束)如何选择增益这取决于你的输入信号范围。原则是让信号的预期最大电压尽可能接近但不超过ADC的满量程。例如信号范围是±0.2V那么选择GAIN_SIXTEEN量程±0.256V就比GAIN_ONE量程±4.096V能获得高得多的有效分辨率。如何选择数据速率更高的速率产生更多噪声。对于直流或缓慢变化的信号如温度、光照使用较低的速率如8-128 SPS可以获得更稳定、更精确的读数。对于需要捕捉快速变化的场景如音频信号尽管ADS1115并不擅长才需要使用最高速率。4.3 差分测量与多通道轮询ADS1115的4个通道可以配置为4个单端输入或者2组差分输入。差分测量能有效抑制共模噪声在长导线传输或噪声环境中特别有用。import time import board import busio import adafruit_ads1x15.ads1115 as ADS from adafruit_ads1x15.analog_in import AnalogIn i2c busio.I2C(board.SCL, board.SDA) ads ADS.ADS1115(i2c) # 创建多个通道对象 # 单端通道 chan_single_0 AnalogIn(ads, ADS.P0) # 差分通道测量 A0 和 A1 之间的电压差 chan_diff_0_1 AnalogIn(ads, ADS.P0, ADS.P1) # 另一个差分通道测量 A2 和 A3 之间的电压差 chan_diff_2_3 AnalogIn(ads, ADS.P2, ADS.P3) print(开始读取多通道...) try: while True: # 读取并打印所有通道 print(A0-GND: {:.3f}V | A0-A1: {:.3f}V | A2-A3: {:.3f}V.format( chan_single_0.voltage, chan_diff_0_1.voltage, chan_diff_2_3.voltage )) time.sleep(1) except KeyboardInterrupt: print(结束)轮询多通道ADS1115内部只有一个ADC核心因此无法真正同时采样多个通道。上述代码是顺序读取即读完一个通道再切换到下一个通道进行转换。如果需要“同步”采样你需要使用多个ADS1115模块或者选择具有多路同步采样ADC的芯片。5. 精度提升与噪声应对实战技巧16位ADC的理论性能很好但实际电路中的噪声会严重侵蚀这些精度。以下是一些来自实战的、能显著提升测量质量的技巧。5.1 电源去耦与滤波干净的电源是基石这是最重要也是最容易被忽视的一点。数字电路树莓派本身的电源噪声很大会通过电源线耦合到ADC影响其基准电压从而直接反映在读数上。模块端确保你的ADS1115模块上电源引脚VCC和GND附近有足够的滤波电容通常模块已设计。如果可能可以额外并联一个10μF的钽电容和一个0.1μF的陶瓷电容分别滤除低频和高频噪声。电源选择最佳实践为ADS1115模块提供独立的、干净的线性稳压电源如LM7805/LM1117-3.3而不是直接从树莓派的3.3V引脚取电。树莓派的3.3V引脚噪声可能高达几十毫伏。折中方案如果必须从树莓派取电请使用一个LC电感-电容或RC电阻-电容滤波器将树莓派的电源“净化”后再供给ADC模块。一个简单的办法是串联一个几欧姆的电阻并在模块的VCC和GND之间并联一个100μF的电解电容。测量验证你可以用ADS1115的一个通道来测量它自己的电源电压VCC观察其波动情况。如果波动超过你精度要求的范围就必须处理电源问题。5.2 信号调理与抗混叠滤波传感器出来的信号往往不能直接送入ADC。阻抗匹配与缓冲ADS1115的输入阻抗很高10GΩ对于大多数传感器是足够的。但如果信号源阻抗很高如某些光电传感器微小的输入偏置电流就会在源阻抗上产生误差电压。此时需要在信号源和ADC输入之间加入一个电压跟随器运算放大器构成提供高输入阻抗和低输出阻抗。抗混叠滤波这是针对变化信号的。根据奈奎斯特采样定理采样频率必须大于信号最高频率的两倍。虽然ADS1115速率不高但如果信号中含有高于半采样频率的噪声它们会被“混叠”到低频段造成无法消除的测量误差。必须在ADC输入端加入一个低通滤波器一阶RC滤波器即可其截止频率略高于你关心的信号频率但远低于采样频率的一半。过压保护如前所述可以在输入端串联一个数百欧姆的电阻并配合钳位二极管如BAT54S到电源和地防止意外高压冲击。5.3 软件滤波从数据中提取真值即使硬件做了优化读数依然会有随机跳动。软件滤波是最后一道也是极其有效的防线。移动平均滤波最简单有效。连续取N个样本求平均值。import collections class MovingAverageFilter: def __init__(self, window_size10): self.window collections.deque(maxlenwindow_size) def update(self, new_value): self.window.append(new_value) return sum(self.window) / len(self.window) filter_voltage MovingAverageFilter(window_size20) while True: raw_voltage chan0.voltage smoothed_voltage filter_voltage.update(raw_voltage) print(f原始: {raw_voltage:.4f}V, 滤波后: {smoothed_voltage:.4f}V) time.sleep(0.1)中值滤波对去除偶发的、幅度大的脉冲噪声尖峰特别有效。取N个样本排序后取中间值。卡尔曼滤波如果系统有模型如温度变化缓慢卡尔曼滤波能提供最优估计。但实现较复杂。降低数据速率在代码中设置更低的数据速率如8SPS本身就是一种强大的硬件滤波能大幅降低噪声。一个综合建议对于缓慢变化的信号采用“低数据速率如16SPS 移动平均滤波窗口大小10-50”的组合通常能得到非常稳定平滑的数据。6. 典型应用场景与传感器连接实例理论说了这么多我们来点实际的。看看ADS1115如何与具体传感器连接。6.1 实例一高精度称重传感器HX711的替代方案称重传感器应变片输出的是毫伏级的差分信号。虽然HX711是专用芯片但ADS1115凭借其高增益和差分输入也是一个非常好的选择尤其适合需要更高精度或灵活性的场合。连接称重传感器的E、E-接激励电压如5V或3.3V的稳压源。输出信号A、A-分别接ADS1115的A0和A1作为差分输入CH0。注意务必为称重传感器提供极其稳定的激励电压因为ADS1115使用电源作为参考激励源的任何波动都会被直接测量为重量变化。建议使用独立的精密基准电压源。代码要点ads.gain GAIN_SIXTEEN # 量程±0.256V适合大多数称重传感器的输出范围 ads.data_rate RATE_10 # 称重不需要快追求极低噪声 chan_weight AnalogIn(ads, ADS.P0, ADS.P1) # 差分输入 # 校准先读取空载时的值零点再放置已知重量的砝码得到比例系数 zero_offset 0.0 scale_factor 1.0 # ... (校准过程代码) weight_kg (chan_weight.voltage - zero_offset) * scale_factor6.2 实例二4-20mA电流环传感器工业传感器常用4-20mA电流输出抗干扰能力强。我们需要一个精密采样电阻将其转换为电压。连接在传感器电流回路中串联一个精密电阻例如125Ω。根据欧姆定律4mA对应0.5V20mA对应2.5V。将这个电阻两端的电压是差分信号接入ADS1115的差分输入通道如A2和A3。ADS1115的增益设置为GAIN_ONE±4.096V或GAIN_TWO±2.048V即可覆盖此电压范围。注意确保采样电阻的精度和温漂满足要求。电阻的功率也要足够PI²R20mA时125Ω电阻功耗为0.05W0805封装的电阻即可。计算电流R_sense 125.0 # 欧姆 ads.gain GAIN_TWO # 量程±2.048V为2.5V留有余量 chan_current AnalogIn(ads, ADS.P2, ADS.P3) voltage_across_resistor chan_current.voltage # 差分电压 current_ma (voltage_across_resistor / R_sense) * 1000 # 转换为毫安 # 4mA对应物理量最小值20mA对应最大值中间线性计算 physical_value min_value (current_ma - 4.0) * (max_value - min_value) / (20.0 - 4.0)6.3 实例三多路温度监控热电偶/RTD热电偶输出信号很小每度几十微伏需要高增益和冷端补偿。ADS1115的高增益模式非常适合。连接热电偶的正负极直接接入一个差分通道如A0, A1。必须进行冷端补偿你需要另一个温度传感器如DS18B20、LM35来测量ADS1115模块接线端子处的温度冷端温度。在软件中根据热电偶类型K型、J型等查表或计算将测量的热电势加上冷端温度对应的电势才能得到真实的被测温度。注意热电偶信号非常微弱必须使用屏蔽双绞线并远离电源等噪声源。可以考虑在输入端增加一个RC低通滤波器。7. 故障排查与常见问题即使按照教程你也可能会遇到问题。下面是一些常见坑点及其解决方案。问题1运行i2cdetect -y 1看不到设备地址显示--。检查接线这是最常见的原因。反复检查SDA、SCL、VCC、GND四根线是否接错、接松。特别是电源和地。检查电源用万用表测量模块VCC和GND之间的电压确认是3.3V左右。检查地址确认模块的I2C地址选择跳线。尝试运行sudo i2cdetect -y 1扫描所有地址0x03到0x77看看设备是否在其他地址上。检查上拉电阻I2C总线需要上拉电阻通常4.7kΩ-10kΩ将SDA和SCL拉到高电平。树莓派内部已有上拉电阻但对于长导线或多个设备可能强度不够。可以尝试在模块的SDA和SCL到3.3V之间外接4.7kΩ电阻。冲突设备是否有其他设备占用了I2C总线尝试只连接ADS1115模块。问题2读数不稳定跳动很大。电源噪声90%的原因在此。参照第5.1节优化电源。最简单的测试用电池如3.7V锂电池串联一个二极管降压给ADS1115模块单独供电看看读数是否变稳。信号源噪声传感器本身输出是否稳定用示波器观察输入到ADC引脚的信号。软件滤波立即实施第5.3节的软件滤波。降低数据速率将ads.data_rate设置为RATE_8或RATE_16。输入悬空如果输入引脚什么都没接它会拾取环境噪声读数乱跳是正常的。将不用的输入引脚接地或接一个固定电压。问题3读数永远为0或接近0或者是一个固定值。通道配置错误确认你代码中指定的通道号ADS.P0与实际连接的物理引脚A0一致。单端/差分模式混淆如果你将传感器接在A0和GND之间却使用了差分通道AnalogIn(ads, ADS.P0, ADS.P1)读数会是A0和A1的差值可能很小。增益设置过高如果输入电压很小但增益设置过低如GAIN_TWOTHIRDS导致电压值远小于1个LSB读数可能始终为0。尝试提高增益。传感器或电路故障用万用表测量ADC输入引脚的实际电压与代码读出的电压对比。问题4读数似乎有固定的偏移零点误差。输入偏置电流在单端模式下将输入引脚直接短路到GND理论上应该读数为0。如果有一个很小的固定电压如几十到几百微伏这就是ADC的输入偏移电压。你可以在软件中记录这个值并在后续测量中减去它校准。共模电压范围在差分模式下要确保两个输入引脚上的电压都在ADS1115的允许输入范围内GND-0.3V 到 VDD0.3V。即使差值正确如果某个引脚电压超出此范围测量也会出错。问题5同时使用多个ADS1115模块时只有一个能被识别。地址冲突确保每个模块的I2C地址设置跳线不同。用i2cdetect分别扫描每个模块单独连接时的地址。总线负载I2C总线上设备太多可能导致通信失败。确保总线总电容在规范内必要时降低通信速度树莓派I2C速度可调但Adafruit库可能不支持动态修改这是个进阶话题。折腾硬件项目就是在与噪声、接触不良和意料之外的行为作斗争。耐心地、系统地用万用表、逻辑分析仪如果有和分段测试法总能找到问题所在。每次解决问题的过程都是对电路和芯片理解加深的过程。当你终于获得那条稳定平滑的传感器曲线时那种成就感就是驱动我们不断探索的最大乐趣。