跳到主要内容C++大前端算法
基于 ESP32 的 ADS1115 多通道数据采集与 Web 监控系统
基于 ESP32 与 ADS1115 构建多通道数据采集系统,支持单端及差分电压测量。通过 Web 服务器实现数据实时传输与 Chart.js 可视化展示。详解硬件接线、I2C 通信协议、寄存器配置及代码逻辑,并提供常见问题排查指南。重点解决差分模式下寄存器配置切换问题,结合 Chart.js 实现波形可视化。涵盖硬件接线、代码逻辑、I2C 协议及常见问题排查。
草莓泡芙14 浏览 基于 ESP32 的 ADS1115 多通道数据采集系统
本项目基于 ESP32-WROOM-32 主控板,结合 TI ADS1115 16 位高精度 ADC 模数转换器,实现了一个功能完整的多通道数据采集与 Web 监控系统。系统不仅支持传统的 4 通道单端电压测量,更实现了 A0-A1 差分电压测量功能,并通过现代化的 Web 界面实时展示数据变化趋势。
项目难点及解决方案
问题描述: 在单次转换模式下,每次测量都需要重新配置 MUX 通道选择寄存器。频繁切换差分和单端模式可能导致数据读取错误。
解决方案: 采集流程中先读取差分数据、再读取单端数据,每次读取前库自动完成寄存器重新配置,避免手动操作寄存器的出错。
一、系统接线部分
1.1 硬件清单
| 组件 | 型号/规格 | 数量 | 备注 |
|---|
| 主控板 | ESP32-WROOM-32 | 1 | 核心控制器 |
| ADC 模块 | ADS1115 16 位 | 1 | 高精度模数转换 |
| 杜邦线 | 公对公 | 若干 | 连接线 |
| 电位器 | 10kΩ | 2 | 模拟信号源 |
| 电源 | 5V/2A | 1 | 供电 |
1.2 接线方案表
根据代码设计,接线配置如下:
| ESP32 引脚 | ADS1115 引脚 | 连接说明 | 备注 |
|---|
| GPIO21 | SDA | I2C 数据线 | 模块内置上拉电阻 |
| GPIO22 | SCL | I2C 时钟线 | 模块内置上拉电阻 |
| 3.3V | VDD | 电源正极 | 电源 5V 供电,避免模块损坏 |
| GND | GND | 电源地 | 共地很重要 |
| 电位器 1 | AIN0 | 通道 0 输入 | 差分正输入端 |
| 电位器 2 | AIN1 | 通道 1 输入 | 差分负输入端 |
| GND | AIN2 | 通道 2 输入 | 单端测量 |
| - | AIN3 | 通道 3 输入 | 单端测量 |
注意:GAIN_ONE 模式输入电压必须在±4.096V 范围内
1.3 接线示意图
![图片]
PS:旋转电位器和 ADS1115 ADC 模块都采用系统 3.3V 供电
1.4 实物连接图
![图片]
二、安装与使用部分
2.1 导入代码
2.2 连接与上传
2.3 调试串口监视器
三、代码讲解部分
代码文件结构
主程序文件,实现 WiFi 连接、ADS1115 数据采集、WebServer 搭建;头文件,存储 Web 页面的 HTML/CSS/JavaScript 代码。
3.1 初始化配置
const float multiplier = 0.000125;
void setup() {
Serial.begin(115200);
if (!ads.begin()) {
Serial.println("无法初始化 ADS1115,请检查连线!");
while (1);
}
ads.setGain(GAIN_ONE);
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());
server.on("/", HTTP_GET, []() {
server.send_P(200, "text/html", index_html);
});
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();
raw_diff = ads.readADC_Differential_0_1();
volt_diff = raw_diff * multiplier;
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;
delay(5);
}
测量 AIN0 和 AIN1 之间的电压差、结果可正可负,代表相对极性、差分模式能抑制共模噪声,提高测量精度。
3.3 Web 数据接口
WebServer server(80);
server.on("/", HTTP_GET, []() {
server.send_P(200, "text/html", index_html);
});
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>
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 },
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 => {
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);
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));
}
setInterval(updateDashboard, 100);
</script>
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 路由信息。
打开电脑 / 手机浏览器,输入上述访问地址,即可看到实时电压数值和差分电压波形。
调节电位器,观察 A0/A1 电压变化,以及差分电压的实时波形变化。
4.2 视频演示
ESP32+ADS1115 多通道采集:差分电压实时波形可视化
完整演示 ESP32 驱动 ADS1115 的多通道单端 / 差分采集流程,包含代码烧录、代码修改、WiFi 连接、Web 可视化全流程,直观展示差分电压随输入信号变化的实时波形,以及各通道电压的高精度显示效果。
五、ADS1115 技术讲解
ADS1115 具有一个输入多路复用器 (MUX),可实现双路差分输入或四路单端输入测量。兼容 I2C 的 16 位低功耗精密模数转换器 (ADC)。
ADS1115 包含两个差分输入,AIN0 和 AIN1 可以与 AIN3 进行差分测量,多路复用器由配置寄存器中的位 MUX [2:0] 配置。
5.1 寄存器配置
ADS1115 有 4 个寄存器,本项目核心用到配置寄存器(0x01)和转换寄存器(0x00)。
存储 ADC 转换后有符号的原始值,ESP32 读取该寄存器值后,乘以转换系数即可得到实际电压。
16 位配置寄存器用于控制工作模式、输入选择、数据速率、满量程范围和比较器模式。
本项目设置 MUX[2:0] 位为 000,使用差分通道 AIN0 和 AIN1。
本项目设置 PGA[2:0] 位为 001,采用 GAIN_ONE 增益。
5.2 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 页面能打开,但数值不更新 / 波形无变化?
- 检查 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。
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online