ADS1115 16位ADC接Arduino:差分读小信号

2026-11-10 20:30:36 20阅读

Arduino 板载 ADC 只有 10 位,Uno 上 A0 读出来是 0-1023,一格就是约 4.9mV。想测一个几十毫伏的小信号——电桥输出、微弱压差——这个分辨率直接不够用。TI 的 ADS1115 是这类问题的标准解法之一:16 位输出、I2C 接口、四路输入还自带可编程增益,官方标称最高 860SPS。这篇把它接到 Arduino 上,从接线到四通道单端、差分读取、增益设置,一次走完。

ADS1115 16位ADC模块

模块速览:先把数字摆出来

ADS1115 是 TI 的 16 位 delta-sigma ADC,官方产品页给的关键参数很齐:供电 2.0V 到 5.5V,连续转换模式下功耗 150µA,数据率 8SPS 到 860SPS 可编程,PGA 输入量程 ±256mV 到 ±6.144V,内置基准源和振荡器,I2C 接口有四个可选地址,工作温度 -40°C 到 +125°C。输入端可以配成四路单端,也可以配成两路差分。

Adafruit 的 STEMMA QT 版转接板把这块芯片做成了即插即用的小板,2V 到 5V 的电源和逻辑电平都能直接吃,3.3V 和 5V 主控通吃。同一根 I2C 总线最多挂 4 块板,单端 16 通道或者差分 8 通道。这款转接板在 Adafruit 官方商城标价 14.95 美元(截至11月10日);同板的 ADS1015 版本 12 位、3300SPS,标价 9.95 美元。两者只差分辨率和速度,其余玩法一样。

参数ADS1115ADS1015
分辨率16 位12 位
最高数据率860SPS3300SPS
输入通道4 单端 / 2 差分4 单端 / 2 差分
PGA 量程±256mV 至 ±6.144V±256mV 至 ±6.144V
供电范围2.0V 至 5.5V2.0V 至 5.5V

ADS1015与ADS1115两块转接板俯视图

接线:四根线搞定

接线非常省事。5V 主控(Uno、Metro 这类)用 5V 接 VIN;3.3V 主控(Feather 这类)就接 3.3V。剩下三根:SCL 接 SCL,SDA 接 SDA,GND 接 GND。板子带 STEMMA QT / Qwiic 插口的话,一根 JST 线直插,连杜邦线都省了。

Arduino与ADS1115通过STEMMA QT接线面包板图

模块上还有一个 ADDR 引脚,用来改 I2C 地址:接 GND 是 0x48(默认),接 VDD 是 0x49,接 SDA 是 0x4A,接 SCL 是 0x4B。悬空时 Adafruit 板子的默认地址是 0x48。想在一根总线上多挂几块板,就把不同板的 ADDR 接到不同位置,配成 0x48 到 0x4B 四个地址。

如果要测真正的差分信号,比如电桥的两个输出端,把它们分别接 AIN0 和 AIN1 就行。普通传感器输出则走单端:传感器输出接 AIN0 到 AIN3 任意一路,共地即可。

ADS1115与传感器在面包板上的I2C接线图

装库与四通道单端读数

库用 Adafruit 官方的 Adafruit_ADS1X15,在 Arduino IDE 的库管理器里搜 ADS1X15 安装即可。下面这段四通道单端读取的示例照官方教程页原样搬来。说明一点:站点正文会剥掉尖括号头文件,所以 #include 和 #include 在这里按编译等价写法换成双引号形式,两种写法对库搜索路径等价,其余字符一字未动。

#include "Wire.h"
#include "Adafruit_ADS1X15.h"

Adafruit_ADS1015 ads1015;  	// Construct an ads1015 

void setup(void)
{
  Serial.begin(9600);
  Serial.println("Hello!");
  
  Serial.println("Getting single-ended readings from AIN0..3");
  Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV)");
  ads1015.begin();
}

void loop(void)
{
  int16_t adc0, adc1, adc2, adc3;

  adc0 = ads1015.readADC_SingleEnded(0);
  adc1 = ads1015.readADC_SingleEnded(1);
  adc2 = ads1015.readADC_SingleEnded(2);
  adc3 = ads1015.readADC_SingleEnded(3);
  Serial.print("AIN0: "); Serial.println(adc0);
  Serial.print("AIN1: "); Serial.println(adc1);
  Serial.print("AIN2: "); Serial.println(adc2);
  Serial.print("AIN3: "); Serial.println(adc3);
  Serial.println(" ");
  
  delay(1000);
}

注意官方示例代码是按 ADS1015 写的,量程注释里的 3mV 一格也是 12 位版的换算。换成 ADS1115 时,把对象改成 Adafruit_ADS1115 ads1115;、调用 ads1115.begin(),换算系数相应变成 0.1875mV 一格(官方教程页给的口径是约 188µV/bit),原始读数范围变成 16 位的整数。readADC_SingleEnded 括号里的 0 到 3 就对应 AIN0 到 AIN3 四路输入。

库也支持在 begin 时直接传地址:手头板子把 ADDR 接了 VDD,就写 ads1115.begin(0x49),这个写法官方示例里同样有。

差分模式:读两点的电压差

差分是这块芯片对小白最值钱的功能。单端读的是某一路对地的电压,而差分读的是两路之间的电压差,共模干扰、地电位漂移在很大程度上被抵掉,小信号干净得多。ADS1115 提供两组差分对:AIN0 对 AIN1、AIN2 对 AIN3。官方差分示例原样如下:

#include "Wire.h"
#include "Adafruit_ADS1X15.h"

Adafruit_ADS1015 ads1015;

void setup(void)
{
  Serial.begin(9600);
  Serial.println("Hello!");
  
  Serial.println("Getting differential reading from AIN0 (P) and AIN1 (N)");
  Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV)");
  ads1015.begin();
}

void loop(void)
{
  int16_t results;

  results = ads1015.readADC_Differential_0_1();
  Serial.print("Differential: "); Serial.print(results); Serial.print("("); Serial.print(results * 3); Serial.println("mV)");

  delay(1000);
}

readADC_Differential_0_1() 返回的是 int16_t 有符号数:AIN0 电位高于 AIN1 时是正值,反过来就是负值,这一点和单端的 0 起步完全不同,解析读数时要留意符号。示例里 results * 3 把原始值换算成毫伏,同样是 ADS1015 口径;ADS1115 上把这个乘数换成 0.1875 才是毫伏值,函数名换成 ads1115.readADC_Differential_0_1() 即可,AIN2 对 AIN3 那组对应的是 readADC_Differential_2_3()。

增益设置:把小信号放大了读

PGA 是这块芯片的另一半价值。量程默认 ±6.144V,一格 0.1875mV;信号本身只有几百毫伏时,缩窄量程等效于放大输入,分辨率利用率直线上升。六档增益对应关系官方代码注释里列得明明白白:

ads1015.setGain(GAIN_TWOTHIRDS);  // 2/3x gain +/- 6.144V  1 bit = 3mV (default)

// ads1015.setGain(GAIN_ONE);     // 1x gain   +/- 4.096V  1 bit = 2mV
// ads1015.setGain(GAIN_TWO);     // 2x gain   +/- 2.048V  1 bit = 1mV
// ads1015.setGain(GAIN_FOUR);    // 4x gain   +/- 1.024V  1 bit = 0.5mV
// ads1015.setGain(GAIN_EIGHT);   // 8x gain   +/- 0.512V  1 bit = 0.25mV
// ads1015.setGain(GAIN_SIXTEEN); // 16x gain  +/- 0.256V  1 bit = 0.125mV

选档思路很简单:信号峰值是多少,就选一个比它大一点的量程。比如传感器输出 1V 上下,官方示例给的就是 GAIN_FOUR(±1.024V 档)。对 ADS1115 来说,每档的量程和上面完全相同,但一格代表的电压是 ADS1015 的十六分之一:±6.144V 档一格 0.1875mV,依次除以 2,到 ±0.256V 档一格约 0.0078mV。0.0078mV 换个说法就是接近 8µV 一格,这才是 16 位 ADC 的真正牌面。

两处细节别踩。其一,增益会改变原始读数但不改变电压本身——同一个 0.168V 的信号,增益 1 倍时原始值 84,增益 16 倍时变成 1335 左右,官方教程用这组实测数演示过这层关系,最终换算回电压都是 0.168V 附近。其二,量程必须罩得住信号:把 2V 的信号塞进 ±0.256V 档,读数直接顶满饱和,不是坏事但数据没法用。

库还留了 getGain() 读当前增益、getLastConversionResults() 取最近一次转换结果,以及比较器模式——超过阈值就在 ALRT 引脚上拉信号,可以轮询也可以当中断用。想做的通道守门场景(比如某路电压越限就报警),不用主循环反复读,比较器是更省 CPU 的做法。

写在最后

从数据角度看,ADS1115 的性价比逻辑很清楚:十几美元一块板,换来 16 位分辨率、六档 PGA、四路可复用输入和一个硬件比较器,四块板还能并到同一根 I2C 总线上扩到 16 个单端通道。Arduino 板载 ADC 处理不了的毫伏级信号,它接手后一格能细到几微伏。唯一要适应的是示例代码里 ADS1015 与 ADS1115 的换算系数差异——3mV 与 0.1875mV 一字之差,算错就是 16 倍的偏差,接线对了数据不对时先查这个。


作者:数据媛小满
链接:https://www.aiddithome.com/p/12ab129cbdaf18.html
本作版权归作者所有,未经允许请勿转载。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
4条评论
刷着刷着入坑了
1楼 · 3小时前

STEMMA QT 插口是真省心,一根线接完就能用

入门没多久的新手
2楼 · 3小时前

刚入门想问下,四块板挂同一根总线的话,地址是不是只能用 0x48 到 0x4B 这四个?再多就得换别的方案了吧

线比代码多
3楼 · 3小时前

接线图比代码看着踏实,先收藏了

拆开看看再说
4楼 · 3小时前

之前用 Uno 板载 ADC 测过应变片电桥,输出才二十几毫伏,读数跳得没法看,后来才明白 10 位 ADC 一格 4.9mV,信号直接淹在分辨率里。换成 ADS1115 把增益拉到 16 倍档,量程 ±0.256V,一格不到 8µV,曲线立刻稳定了。差分接法把两根线共模的漂移抵掉这点确实值,文章里 int16_t 有符号那个提醒也很关键,我第一次接反极性时还以为是模块坏了。