1. 为什么需要高精度模数转换很多刚接触Arduino的朋友可能会有疑问UNO板载的ADC不是已经能读取模拟信号了吗为什么还要外接ADS1115这样的模数转换模块这个问题我刚开始玩电子制作时也困惑过。直到有一次做土壤湿度监测项目发现板载ADC测出的数值总是跳变严重这才意识到问题的关键——精度。Arduino UNO内置的是10位ADC意味着它能把0-5V电压分成1024个等级每个等级约4.88mV。这个分辨率对于LED亮度调节可能够用但遇到需要测量微小电压变化的场景就力不从心了。比如热电偶输出可能只有几毫伏的变化或者称重传感器的信号需要精确到0.1%的精度这时候16位的ADS1115就能大显身手——它能将同样电压范围分成65536个等级分辨率高达0.076mV使用±6.144V量程时足足比UNO内置ADC精确64倍我最近用ADS1115做的电池组电压监测项目就很能说明问题。需要同时监测8节锂电池的电压每节满电4.2V放电截止3.0V。用UNO直接测量时电压读数总是上下波动0.1V左右根本无法判断电池真实状态。换上ADS1115后不仅能看到0.01V级别的精确变化还能通过它的差分输入功能直接测量两节电池之间的电压差这对平衡充电太有用了。2. 硬件连接详解2.1 模块引脚功能解析第一次拿到ADS1115模块时我看到上面密密麻麻的引脚也有点发怵。其实只要搞清楚几个关键接口就很简单了。模块正面最显眼的是4个模拟输入口A0-A3这是连接传感器的入口。背面则有标准的I2C接口SCL/SDA和两个特殊功能引脚ADDR地址选择脚。通过接地或接VCC可以设置4种I2C地址0x48-0x4B这样一条总线上最多能挂4个ADS1115。我在多通道数据采集项目中就用了这个特性。ALERT中断输出脚。当测量值超过预设阈值时会触发信号适合需要实时响应的场景。不过初学者可以先不接这个脚。模块通常还自带两个实用设计一个是电平转换电路使得3.3V和5V系统都能兼容另一个是板上稳压器为ADS1115提供稳定工作电压。这些细节设计让我们接线时省心不少。2.2 与Arduino UNO的接线方案实际接线比想象中简单得多只需要4根线就能让系统跑起来。这是我的经典接法电源部分ADS1115的VCC接UNO的5V输出GND对GND相连注意虽然模块支持3.3V供电但用5V能获得更好的抗干扰性能I2C通信SCL接UNO的A5引脚SDA接UNO的A4引脚这是UNO的硬件I2C接口比软件模拟的更稳定可选配置如果需要多个ADS1115把ADDR引脚通过跳线接到不同电平ALERT引脚可接UNO的数字引脚做中断输入第一次接线时我犯过一个典型错误把SCL和SDA接反了。结果当然是无法通信但通过I2C扫描程序很快定位了问题。建议大家在通电前先用万用表检查线路能避免很多头疼事。3. 软件配置技巧3.1 库函数的选择与安装市面上有好几种ADS1115的Arduino库经过对比测试我推荐Adafruit_ADS1X15库。它不仅支持ADS1115还兼容12位的ADS1015而且文档齐全、更新活跃。安装方法很简单打开Arduino IDE点击工具→管理库搜索Adafruit ADS1X15点击安装会自动安装依赖的Adafruit BusIO库这个库提供了非常清晰的API接口。比如设置增益只需要一行代码ads.setGain(GAIN_ONE); // 设置±4.096V量程相比直接操作寄存器用库函数不仅省事还能避免很多配置错误。我早期尝试直接写寄存器配置结果因为一个位设置错误导致读数完全不对调试了大半天才发现问题。3.2 关键参数配置详解ADS1115的强大之处在于它的可编程性但这也意味着需要理解几个重要参数增益选择PGA这个设置直接影响测量范围和精度。比如GAIN_TWOTHIRDS±6.144V适合测量5V系统信号GAIN_ONE±4.096V精度提高到0.125mVGAIN_SIXTEEN±0.256V测量微小信号时分辨率达0.0078mV我的经验法则是预估被测信号最大电压后选择最接近的上一档增益。比如测3.3V信号就选±4.096V档既保证不超量程又获得最佳精度。采样速率设置从8SPS到860SPS可选。速率越高噪声越大我通常这样选择128SPS常规传感器读取32SPS高精度测量860SPS快速变化的信号捕捉工作模式单次转换模式适合间歇性测量更省电连续转换模式适合实时监控这里有个实用技巧在setup()里先快速采样几次丢弃初始不稳定数据再切换到正式采样率。我发现ADS1115上电后的前几次读数往往有偏差这个技巧能显著提高初始稳定性。4. 实战应用案例4.1 多路温度监测系统去年我给温室大棚做环境监控时需要同时采集8个DS18B20温度传感器的数据。UNO的ADC通道不够用而且DS18B20的1-Wire总线在长距离传输时不稳定。我的解决方案是使用两个ADS1115地址分别设0x48和0x49每个DS18B20接一个精密分压电阻将温度变化转为电压变化输入ADS1115通过I2C轮询读取所有通道这个方案不仅解决了通道不足问题测量精度还达到了0.1℃。关键代码如下float readTemp(uint8_t ch) { int16_t adc ads.readADC_SingleEnded(ch); float voltage (adc * 0.1875)/1000; // 转换为电压值(mV) return (voltage - 0.5) * 100; // 转换为温度值(℃) }4.2 称重传感器的高精度测量另一个成功案例是电子秤项目。常见的HX711模块虽然专用但分辨率只有24位有效位数约20位而且容易受干扰。改用ADS1115后配合适当的滤波算法实现了更稳定的测量使用差分输入模式连接称重电桥设置GAIN_SIXTEEN±0.256V量程采用64SPS采样率在代码中实现移动平均滤波#define SAMPLE_COUNT 10 int16_t getStableValue() { long sum 0; for(int i0; iSAMPLE_COUNT; i){ sum ads.readADC_Differential_0_1(); delay(20); } return sum/SAMPLE_COUNT; }实测表明这个方案能检测到0.1g的重量变化比HX711方案更抗电源干扰。特别是在电池供电场合ADS1115的低功耗特性单次模式仅0.15mA让设备续航时间大幅延长。5. 常见问题排查指南5.1 I2C通信失败遇到设备无响应时可以按照以下步骤排查先用I2C扫描程序检查地址#include Wire.h void setup() { Wire.begin(); Serial.begin(115200); } void loop() { byte error, address; for(address0x48; address0x4B; address) { Wire.beginTransmission(address); error Wire.endTransmission(); if(error0) Serial.print(Found at 0x);Serial.println(address,HEX); } delay(5000); }如果扫描不到检查接线和电源确认上拉电阻UNO的I2C线路需要4.7kΩ上拉电阻部分ADS1115模块已内置检查电源噪声我在工业现场遇到过电源干扰导致通信失败的情况解决方法是在VCC和GND之间加装0.1μF去耦电容5.2 读数不稳定问题当测量值跳动较大时可以尝试优化硬件缩短传感器引线长度使用屏蔽线在信号线对地加100nF电容软件滤波// 中值平均滤波算法 int16_t getFilteredValue(uint8_t ch) { #define FILTER_SIZE 5 int16_t samples[FILTER_SIZE]; for(int i0; iFILTER_SIZE; i){ samples[i] ads.readADC_SingleEnded(ch); delay(10); } // 排序后取中值 std::sort(samples, samplesFILTER_SIZE); return samples[FILTER_SIZE/2]; }检查接地确保所有设备的GND良好连接避免地环路干扰6. 进阶应用技巧6.1 差分测量的妙用ADS1115支持真正的差分输入不是简单的两个单端测量相减这个特性在很多场景非常实用消除共模噪声在电机附近测量时环境噪声会同时影响信号线的正负端差分测量能自动抵消这部分干扰直接测量小电阻我的四线制毫欧表方案恒流源通过被测电阻ADS1115差分测量电阻两端电压计算电阻值分辨率达0.01Ω电池组平衡监测直接测量相邻电池的电压差比单独测量再相减更准确// 测量两节电池的电压差 int16_t diff ads.readADC_Differential_0_1(); float voltage_diff diff * 0.1875; // 单位mV6.2 低功耗设计对于电池供电设备可以这样优化使用单次转换模式ads.setMode(MODE_SINGLE); // 单次模式在两次测量间让UNO进入休眠#include avr/sleep.h void enterSleep() { set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_mode(); sleep_disable(); }通过ALERT引脚唤醒配置比较器阈值当测量值超限时触发中断唤醒系统我的户外气象站采用这种方案后两节AA电池可以连续工作6个月。关键是要合理设置采样间隔根据实际需求平衡响应速度和功耗。