零知IDE——基于ESP32的ADS1115 多通道数据采集系统:从差分测量到Web实时监控

零知IDE——基于ESP32的ADS1115 多通道数据采集系统:从差分测量到Web实时监控

  ✔零知开源(零知IDE)是一个专为电子初学者/电子兴趣爱好者设计的开源软硬件平台,在硬件上提供超高性价比STM32系列开发板、物联网控制板。取消了Bootloader程序烧录,让开发重心从 “配置环境” 转移到 “创意实现”,极大降低了技术门槛。零知IDE编程软件,内置上千个覆盖多场景的示例代码,支持项目源码一键下载,项目文章在线浏览。零知开源(零知IDE)平台通过软硬件协同创新,让你的创意快速转化为实物,来动手试试吧!

✔访问零知实验室,获取更多实战项目和教程资源吧!

www.lingzhilab.com

目录

一、系统接线部分

1.1 硬件清单

1.2 接线方案表

1.3 接线示意图

1.4 实物连接图

二、安装与使用部分

三、代码讲解部分

3.1 初始化配置

3.2 多模式数据采集

3.3 Web数据接口

3.4 前端数据可视化

四、项目结果演示

4.1 操作流程

4.2 视频演示

五、ADS1115技术讲解

5.1 寄存器配置

5.2 I2C 通信协议

六、常见问题解答(FAQ)

Q1:测量负电压的原理?

Q2:Web 页面能打开,但数值不更新 / 波形无变化?

Q3: I2C地址冲突怎么办?


项目概述

       本项目基于零知ESP32-WROOM-32主控板,结合TI ADS1115 16位高精度ADC模数转换器,实现了一个功能完整的多通道数据采集与Web监控系统。系统不仅支持传统的4通道单端电压测量,更实现了A0-A1差分电压测量功能,并通过现代化的Web界面实时展示数据变化趋势

项目难点及解决方案

        问题描述:在单次转换模式下,每次测量都需要重新配置MUX通道选择寄存器。频繁切换差分和单端模式可能导致数据读取错误

解决方案:采集流程中先读取差分数据、再读取单端数据,每次读取前库自动完成寄存器重新配置,避免手动操作寄存器的出错

一、系统接线部分

1.1 硬件清单

组件型号/规格数量备注
主控板零知ESP32-WROOM-321核心控制器
ADC模块ADS1115 16位1高精度模数转换
杜邦线公对公若干连接线
电位器10kΩ2模拟信号源
电源5V/2A1供电

1.2 接线方案表

        根据代码设计,接线配置如下:
ESP32引脚ADS1115引脚连接说明备注
GPIO21SDAI2C数据线模块内置上拉电阻
GPIO22SCLI2C时钟线模块内置上拉电阻
3.3VVDD电源正极电源5V供电,避免模块损坏
GNDGND电源地共地很重要
电位器1AIN0通道0输入差分正输入端
电位器2AIN1通道1输入差分负输入端
GNDAIN2通道2输入单端测量
-AIN3通道3输入单端测量

注意:GAIN_ONE模式输入电压必须在±4.096V范围内

1.3 接线示意图

        PS:旋转电位器和ADS1115 ADC模块都采用系统3.3V供电

1.4 实物连接图

二、安装与使用部分

2.1 开源平台-输入"ADS1115 多通道数据采集"并搜索-代码下载自动打开

2.2 连接-验证-上传

2.3 调试-串口监视器

三、代码讲解部分

代码文件结构

        主程序文件,实现 WiFi 连接、ADS1115 数据采集、WebServer 搭建;头文件,存储 Web 页面的 HTML/CSS/JavaScript 代码

3.1 初始化配置

// 增益设置: GAIN_ONE (+/- 4.096V) // 1 bit = 0.125mV const float multiplier = 0.000125; void setup() { Serial.begin(115200); // 1. 初始化 ADS1115 if (!ads.begin()) { Serial.println("无法初始化 ADS1115,请检查连线!"); while (1); } // 设置增益以匹配 3.3V 系统,同时保留一定的余量 ads.setGain(GAIN_ONE); // 2. 连接 WiFi WiFi.begin(ssid, password); Serial.print("正在连接 WiFi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("\nWiFi 已连接"); Serial.print("访问地址: http://"); Serial.println(WiFi.localIP()); // 3. 配置 Web 服务器路由 // 首页 server.on("/", HTTP_GET, []() { server.send_P(200, "text/html", index_html); }); // API 接口:返回 JSON 数据 server.on("/data", HTTP_GET, []() { String json = "{"; json += "\"diff_raw\":" + String(raw_diff) + ","; json += "\"diff_v\":" + String(volt_diff, 4) + ","; json += "\"v0\":" + String(volt_a0, 4) + ","; json += "\"v1\":" + String(volt_a1, 4) + ","; json += "\"v2\":" + String(volt_a2, 4); json += "}"; server.send(200, "application/json", json); }); server.begin(); Serial.println("HTTP 服务器已启动"); }
        GAIN_ONE增益倍数1,满量程±4.096V;multiplier每个LSB对应的电压值(0.125mV)

3.2 多模式数据采集

// --- 变量存储 --- int16_t raw_diff; // 差分原始值 int16_t raw_a0, raw_a1, raw_a2; // 单端原始值 float volt_diff, volt_a0, volt_a1, volt_a2; // 转换后的电压值 void loop() { server.handleClient(); // --- 关键步骤:切换模式读取数据 --- // 注意:频繁切换配置寄存器会消耗一点时间,但为了同时显示单端和差分是必须的。 // 1. 读取 A0-A1 差分值 (Differential) // 如果 A0 > A1,值为正;如果 A1 > A0,值为负 raw_diff = ads.readADC_Differential_0_1(); volt_diff = raw_diff * multiplier; // 2. 读取单端值 (Single Ended) 用于参考 raw_a0 = ads.readADC_SingleEnded(0); volt_a0 = raw_a0 * multiplier; raw_a1 = ads.readADC_SingleEnded(1); volt_a1 = raw_a1 * multiplier; raw_a2 = ads.readADC_SingleEnded(2); // 备用通道 volt_a2 = raw_a2 * multiplier; // 简单的串口调试 (可选) // Serial.printf("Diff: %.4f V, A0: %.4f V, A1: %.4f V\n", volt_diff, volt_a0, volt_a1); delay(5); // 短暂延时,避免 CPU 过载 }
        测量AIN0和AIN1之间的电压差、结果可正可负,代表相对极性、差分模式能抑制共模噪声,提高测量精度

3.3 Web数据接口

// --- 全局对象 --- WebServer server(80); // 3. 配置 Web 服务器路由 // 首页 server.on("/", HTTP_GET, []() { server.send_P(200, "text/html", index_html); }); // API 接口:返回 JSON 数据 server.on("/data", HTTP_GET, []() { String json = "{"; json += "\"diff_raw\":" + String(raw_diff) + ","; json += "\"diff_v\":" + String(volt_diff, 4) + ","; json += "\"v0\":" + String(volt_a0, 4) + ","; json += "\"v1\":" + String(volt_a1, 4) + ","; json += "\"v2\":" + String(volt_a2, 4); json += "}"; server.send(200, "application/json", json); }); server.begin();
        使用JSON格式便于前端解析、保留4位小数确保精度同时提供原始值和计算值

3.4 前端数据可视化

<script> // --- Chart.js 初始化配置 --- const ctx = document.getElementById('voltageChart').getContext('2d'); // 创建渐变填充 let gradient = ctx.createLinearGradient(0, 0, 0, 400); gradient.addColorStop(0, 'rgba(102, 252, 241, 0.4)'); // 顶部颜色 gradient.addColorStop(1, 'rgba(102, 252, 241, 0)'); // 底部透明 const voltageChart = new Chart(ctx, { type: 'line', data: { labels: [], // 时间轴标签 datasets: [{ label: 'Differential Voltage (A0 - A1)', data: [], borderColor: '#66fcf1', backgroundColor: gradient, borderWidth: 2, pointRadius: 0, // 隐藏数据点,使线条更平滑 fill: true, tension: 0.4 // 曲线平滑度 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { display: false }, // 隐藏X轴标签保持简洁 y: { grid: { color: '#333' }, ticks: { color: '#888' }, suggestedMin: -4.0, suggestedMax: 4.0 } }, plugins: { legend: { labels: { color: '#c5c6c7' } } }, animation: false // 禁用动画以提高实时性能 } }); // --- 数据获取与更新逻辑 --- const maxDataPoints = 100; // 图表保留的数据点数量 function updateDashboard() { fetch('/data') .then(response => response.json()) .then(data => { // 1. 更新卡片数值 document.getElementById('valDiff').innerText = data.diff_v.toFixed(4); document.getElementById('val0').innerText = data.v0.toFixed(4); document.getElementById('val1').innerText = data.v1.toFixed(4); document.getElementById('val2').innerText = data.v2.toFixed(4); // 2. 更新图表 // 获取当前时间戳作为简单的标签 const now = new Date().toLocaleTimeString(); // 添加新数据 voltageChart.data.labels.push(now); voltageChart.data.datasets[0].data.push(data.diff_v); // 如果数据点过多,移除最早的数据 if (voltageChart.data.labels.length > maxDataPoints) { voltageChart.data.labels.shift(); voltageChart.data.datasets[0].data.shift(); } voltageChart.update(); }) .catch(error => console.error('Error:', error)); } // 设置刷新频率 (100ms = 10Hz刷新率) setInterval(updateDashboard, 100); </script>

系统流程图

差分测量模式深度解析

// 读取A0-A1差分原始值,底层自动配置寄存器 raw_diff = ads.readADC_Differential_0_1(); // 转换为实际电压(有符号,支持正负电位差) volt_diff = raw_diff * multiplier;

ADS1115 的差分测量是将两个输入引脚(A0/A1)的电位差作为输入信号,而非相对于 GND 的单端信号,核心优势是抑制共模干扰

差分测量原理图

         当 A0 电压 > A1 电压时,raw_diff为正,volt_diff为正;当 A0 电压 < A1 电压时,raw_diff为负,volt_diff

 

 

差分量程与增益配置一致(GAIN_ONE 对应 ±4.096V),即 A0-A1 的电位差范围为 - 4.096V~+4.096V

四、项目结果演示

4.1 操作流程

        按照接线方案表完成 ESP32 与 ADS1115 的连接,A0/A1 接电位器(模拟差分信号),A2 接备用传感器,修改主程序SSID和PASSWORD为实际 WiFi 路由信息

上电运行

给 ESP32 上电,打开串口监视器,设置波特率为 115200,等待 WiFi 连接成功,记录打印的 “访问地址,如http://192.168.x.x

 

 

数据查看

打开电脑 / 手机浏览器,输入上述访问地址,即可看到实时电压数值和差分电压波形

信号调试 

调节电位器,观察 A0/A1 电压变化,以及差分电压的实时波形变化

4.2 视频演示

ESP32+ADS1115多通道采集:差分电压实时波形可视化

完整演示 ESP32 驱动 ADS1115 的多通道单端 / 差分采集流程,包含代码烧录、代码修改、WiFi 连接、Web 可视化全流程,直观展示差分电压随输入信号变化的实时波形,以及各通道电压的高精度显示效果

五、ADS1115技术讲解

 ADS1115 具有 一个输入多路复用器 (MUX),可实现双路差分输入或 四路单端输入测量。兼容 I 2C 的 16 位低功耗精密模数转换器 (ADC)

Multiplexer 复用器

ADS1115包含两个差分输入,AIN0和AIN1可以与AIN3进行差分测量,多路复用器由配置寄存器中的位MUX [2:0]配置

5.1 寄存器配置

        ADS1115 有 4 个寄存器,本项目核心用到配置寄存器(0x01) 和转换寄存器(0x00)

 转换寄存器(0x00)

        存储 ADC 转换后有符号的原始值,ESP32 读取该寄存器值后,乘以转换系数即可得到实际电压

配置寄存器(0x01)[15:0]

         16位配置寄存器用于控制工作模式、输入选择、数据速率、满量程范围和比较器模式

①MUX位详解(输入选择):

 

 

本项目设置MUX[2:0]位为000,使用差分通道AIN0和AIN1

②PGA位详解(增益设置):

 

 

本项目设置PGA[2:0]位为001,采用GAIN_ONE增益

5.2 I2C 通信协议

 ① I2C地址选择

        ADS1115有一个地址引脚 ADDR,用于配置器件的 I2C 地址。该引脚可连接至 GND、VDD、SDA 或 SCL,通过一个引脚即可选择四种不同的地址

  ② 向寄存器写入数据

        要访问 ADS111x 中的特定寄存器,主机必须首先向地址指针寄存器中的寄存器地址指针位 P [1:0] 写入适当的值。

 地址指针寄存器是在从机地址字节、低电平的读 / 写位以及从机成功应答之后直接写入,从机进行应答,主机发出停止条件或重复起始条件

 ③ 从寄存器读取数据

        从 ADS111x 读取数据时,先前写入位 P [1:0] 的值决定了要读取的寄存器。要更改读取的寄存器,必须向 P [1:0] 写入新值

 ④ 数据格式

        以二进制补码格式提供 16 位数据。正满量程(+FS)输入产生的输出代码为 7FFFh,负满量程(–FS)输入产生的输出代码为 8000h

对于超过满量程的信号,输出会钳位在这些代码上

电压计算原理

        ADS1115的输出代码与输入电压的关系为:电压 = (ADC读数 × 满量程电压) / (2¹⁵ - 1)

在GAIN_ONE模式下:满量程电压 = 4.096V、分辨率 = 4.096V / 32767 ≈ 0.125mV

六、常见问题解答(FAQ)

Q1:测量负电压的原理?

        A: ADS1115本身不能直接测量负电压(相对GND)。但通过以下方法间接测量:使用差分模式时V-接负电压,V+接GND、使用电平移位电路将负电压抬升到0-3.3V范围、使用双电源供电给ADS1115提供±2.5V电源

Q2:Web 页面能打开,但数值不更新 / 波形无变化?

        A:排查步骤:检查 ESP32 是否仍连接 WiFi、检查浏览器控制台(F12)是否有报错、确认代码中setInterval(updateDashboard, 100)未被注释,刷新频率正常

Q3: I2C地址冲突怎么办?

        A:ADS1115的I2C地址由ADDR引脚决定:默认ADDR接地0x48、ADDR接VDD地址为0x49、ADDR接SDA地址为0x4A、ADDR接SCL地址为0x4B。在代码Adafruit_ADS1115 ads(0x49); 中修改地址为0x49

 项目资源整合:

        ADS1115库文件:Adafruit_ADS1X15

        ADS1115数据手册:ADS111x datasheet

Read more

Flutter 三方库 flutter_adaptive_scaffold 的鸿蒙化适配指南 - 掌握一套代码适配全场景终端的自适应架构技术、助力鸿蒙应用构建从手机到平板及折叠屏的极致无缝交互体系

Flutter 三方库 flutter_adaptive_scaffold 的鸿蒙化适配指南 - 掌握一套代码适配全场景终端的自适应架构技术、助力鸿蒙应用构建从手机到平板及折叠屏的极致无缝交互体系

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 flutter_adaptive_scaffold 的鸿蒙化适配指南 - 掌握一套代码适配全场景终端的自适应架构技术、助力鸿蒙应用构建从手机到平板及折叠屏的极致无缝交互体系 前言 在 OpenHarmony 鸿蒙应用追求“万物互联、全场景覆盖”的伟大进程中,屏幕尺寸的多样性(从 6 英寸手机到 12 英寸平板,再到 2D/3D 模式切换的折叠屏)是每一位 UI 开发者必须正面迎接的挑战。如何在不为每种设备重写 UI 的前提下,实现导航栏自动从“底部”平滑流转到“侧边”?如何在宽屏模式下自动开启“双栏(Master-Detail)”布局?flutter_adaptive_scaffold 作为一个由 Flutter

By Ne0inhk
在 macOS 上通过 Docker 本地安装 OpenClaw 完整教程

在 macOS 上通过 Docker 本地安装 OpenClaw 完整教程

在 macOS 上通过 Docker 本地安装 OpenClaw 完整教程 什么是 OpenClaw?—— 你的本地 AI 智能体执行框架 OpenClaw 不仅仅是一个聊天机器人,而是一个功能强大的 AI 智能体执行框架。你可以把它想象成一个能自主思考、调用工具、并替你完成复杂任务的数字员工。 🧠 核心概念 * 智能体:OpenClaw 的核心大脑。它能理解你的自然语言指令,拆解任务,并决定调用哪些工具来执行。 * 网关:所有外部访问的入口。它负责处理 WebSocket 连接、管理设备配对、路由消息,是你与智能体交互的桥梁。 * 技能:智能体可调用的具体工具,比如访问文件、操作浏览器、发送消息、查询数据库等。你可以根据需要扩展技能库。 * 记忆:OpenClaw 可以存储对话历史和重要信息,实现长期记忆和上下文理解,让交互更连贯。 * 通道:连接外部聊天平台的渠道,如

By Ne0inhk
HarmonyOS6半年磨一剑 - RcIcon组件实战案例集与应用开发指南

HarmonyOS6半年磨一剑 - RcIcon组件实战案例集与应用开发指南

文章目录 * 前言 * 项目简介 * 核心特性 * 开源计划 * rchoui官网 * 文档概述 * 第一章: 基础用法实战 * 1.1 三种符号引用方式 * 1.2 应用场景 - 工具栏快速导航 * 第二章: 尺寸系统实战 * 2.1 响应式尺寸配置 * 2.2 应用场景 - 统一设计系统尺寸规范 * 第三章: 颜色系统实战 * 3.1 多彩色系配置 * 3.2 应用场景 - 状态指示系统 * 第四章: 双风格系统实战 * 4.1 线型与实底风格对比 * 4.2 应用场景 - 底部导航栏 * 第五章: 圆角系统实战 * 5.

By Ne0inhk
Flutter 组件 short_uuids 适配鸿蒙 HarmonyOS 实战:唯一标识微缩技术,构建高性能短 ID 生成与分布式索引架构

Flutter 组件 short_uuids 适配鸿蒙 HarmonyOS 实战:唯一标识微缩技术,构建高性能短 ID 生成与分布式索引架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 short_uuids 适配鸿蒙 HarmonyOS 实战:唯一标识微缩技术,构建高性能短 ID 生成与分布式索引架构 前言 在鸿蒙(OpenHarmony)生态迈向万物互联、涉及海量离线资源标识、蓝牙广播载荷(BLE Payload)及二维码数据极限压缩的背景下,如何生成既能保留 UUID 强随机性、又能极大缩减字符长度的唯一标识符,已成为优化存储与通讯效率的“空间必修课”。在鸿蒙设备这类强调分布式软总线传输与每一字节功耗敏感的环境下,如果应用依然直接传输长度达 36 字符的标准 UUID,由于由于有效载荷溢出,极易由于由于传输协议限制导致数据截断或多次分包带来的延迟。 我们需要一种能够实现高进制转换、支持双向编解码且具备低碰撞概率的短 ID 生成方案。 short_uuids 为 Flutter 开发者引入了将标准 UUID 转化为短格式字符串的高性能算法。它利用

By Ne0inhk