一、项目简介
本项目基于 ESP8266 WiFi 模块与 INA219 高精度电流/电压传感器,实现了一个可通过网页实时查看电压、电流、功率的监控系统。
系统在启动时会自动进行 硬件自检,确保 INA219 与 ESP8266 的 I2C 通信正常;如果检测失败,程序会停止运行并提示检查接线,从根源上避免“网页能开但数据全是 0”的假象。
主要功能:
- 硬件自检:启动时检测 INA219 是否正常工作。
- WiFi 自动连接:自检通过后自动连接到指定 WiFi。
- 网页实时监控:通过浏览器访问 ESP8266 的 IP 地址,每 0.5 秒刷新一次数据。
二、硬件连接
1. I2C 通信线路(ESP8266 ↔ INA219)
| ESP8266 引脚 | 连接到 | INA219 引脚 | 功能说明 |
|---|---|---|---|
| 3V3 | VCC | 传感器供电 | |
| GND | GND | 公共地线 | |
| D1 | SCL | I2C 时钟线 | |
| D2 | SDA | I2C 数据线 |
2. 主电源测量线路(通过 INA219 测量负载电流)
- 电源正极 → INA219 Vin+
- INA219 Vin- → 负载(如风扇)正极
- 负载负极 → 电源负极
三、必须共地的重要性(重点)
在电路测量中,共地(Common Ground)是指所有设备的地线(GND)必须连接在一起,形成同一个参考电位。
在本项目中:
- ESP8266 的 GND
- INA219 的 GND
- 被测电源的负极
必须全部连接在一起,形成一个统一的地线系统。
为什么必须共地?
-
统一参考电位
INA219 测量的是电压差,如果 ESP8266 与被测电源的地线不相连,它们的参考电位不同,测量结果会完全错误,甚至可能读到负值或漂移数据。 -
I2C 通信稳定
I2C 总线(SCL/SDA)是相对于地线传输信号的,如果两端地线不共用,信号电平会失真,导致通信失败。 -
避免悬浮地(Floating Ground)
如果不共地,ESP8266 和 INA219 之间的电位差可能很大,轻则数据错误,重则可能损坏芯片。
四、软件逻辑简述
-
启动 → 硬件自检
调用ina219.begin()检查是否能与 INA219 建立 I2C 通信,失败则停止运行并提示检查接线。 -
WiFi 连接
使用WiFi.begin(ssid, password)连接到指定网络,成功后打印 IP 地址。 -
Web 服务器
/路径返回 HTML 页面,显示电压、电流、功率。/data路径返回 JSON 数据,前端每 500ms 请求一次,实现实时刷新。
-
数据采样平滑
sampleAveraged()函数多次采样取平均值,减少瞬时波动。
五、使用步骤
- 正确接线(尤其是 GND 共地)
- 修改代码中的 WiFi 名称和密码
- 上传代码到 ESP8266
- 打开串口监视器,确认硬件自检通过并显示 IP 地址
- 在浏览器输入该 IP,即可实时查看数据
六、总结
本项目的核心不仅是代码和网页显示,更重要的是硬件接线的正确性。
尤其要记住:
被测电源的负极、ESP8266 的 GND、INA219 的 GND 必须共地
否则测量数据将不可信,甚至无法通信。
/*
* =================================================================================
* == ==
* == ESP8266 & INA219 最终版实时监控网页服务器 (内置硬件自检) ==
* == ==
* =================================================================================
*
* 本代码是包含了您需要的所有功能的最终版本:
* 1. 【硬件自检】: 在程序启动时,会首先检查与INA219的通信。如果失败,会报错并停止,
* 强制我们解决最根本的硬件连接问题。
* 2. 【WiFi连接】: 硬件自检通过后,会自动连接到您指定的WiFi网络。
* 3. 【网页服务器】: 提供一个可以通过IP地址访问的、每半秒自动刷新的监控网页。
*
* =================================================================================
* == 成功的唯一前提:正确接线 ==
* =================================================================================
*
* I2C通信线路 (这是成败的关键,请最后一次仔细检查):
* ----------------------------------------------------
* | ESP8266 引脚 | 连接到 | INA219 引脚 | 功能 |
* |--------------|----------|-------------|--------------|
* | 3V3 | -----> | VCC | 传感器供电 |
* | GND | -----> | GND | 公共地线 |
* | D1 | -----> | SCL | I2C 时钟线 |
* | D2 | -----> | SDA | I2C 数据线 |
* ----------------------------------------------------
*
* 主电源测量线路:
* - [电源 +] ---> [INA219 Vin+]
* - [INA219 Vin-] ---> [负载(风扇) +]
* - [负载(风扇) -] ---> [电源 -]
*
*/
// 引用所有必需的库
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <Wire.h>
#include <Adafruit_INA219.h>
// --- WiFi凭证 ---
const char* ssid = "yang1234";
const char* password = "y123456789";
// --- 创建所需的对象 ---
ESP8266WebServer server(80);
Adafruit_INA219 ina219;
// --- 全局变量 ---
float loadVoltage = 0, current_mA = 0, power_mW = 0;
/**
* @brief 进行n次测量并取平均值,使结果更平滑
*/
void sampleAveraged(uint8_t n = 5) {
float sum_v = 0, sum_c = 0, sum_p = 0;
for (uint8_t i = 0; i < n; i++) {
float busV = ina219.getBusVoltage_V();
float shunt_mV = ina219.getShuntVoltage_mV();
sum_v += busV + (shunt_mV / 1000.0);
sum_c += ina219.getCurrent_mA();
sum_p += ina219.getPower_mW();
delay(5);
}
loadVoltage = sum_v / n;
current_mA = sum_c / n;
power_mW = sum_p / n;
}
// =================================================
// == 程序初始化设置部分 ==
// =================================================
void setup() {
Serial.begin(115200);
delay(100);
Serial.println("\n\n===== 最终版监控程序启动 =====");
// =================================================================
// == 内置硬件自检 (最关键的一步) ==
// =================================================================
Serial.println("步骤 1: 正在进行硬件自检,尝试与INA219通信...");
if (!ina219.begin()) {
// 如果ina219.begin()返回false,说明硬件通信失败
Serial.println("\n!!! 自检失败: 致命硬件错误 !!!");
Serial.println("!!! 未能找到INA219芯片。网页将无法工作。");
Serial.println("!!! 这100%是物理连接问题,与代码无关。");
Serial.println("\n唯一的解决方案:");
Serial.println(" 1. 仔细检查 VCC, GND, SCL, SDA 的引脚是否插对、插紧。");
Serial.println(" 2. 【请立刻更换全部四根杜邦线再试!】这是最常见但最易被忽略的故障点。");
Serial.println("\n程序将在此停止运行,直到硬件问题被解决。");
while (1) { // 程序在此处无限循环,停止一切后续操作
delay(1000);
}
}
// 如果程序能运行到这里,说明硬件自检通过!
Serial.println(">>> 自检成功!硬件通信已建立。");
ina219.setCalibration_32V_2A();
Serial.println("INA219 初始化成功。");
// --- 步骤 2: WiFi 连接 ---
Serial.println("\n步骤 2: 正在连接到WiFi网络...");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.printf("网络名称: %s\n", ssid);
while (WiFi.status() != WL_CONNECTED) { delay(400); Serial.print("."); }
Serial.printf("\n>>> WiFi连接成功!IP地址: %s\n", WiFi.localIP().toString().c_str());
// --- 步骤 3: Web 服务器配置 ---
server.on("/", [](){
String html = R"rawliteral(
<!doctype html><html><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>ESP8266 INA219</title>
<style>body{font-family:Arial,sans-serif;text-align:center;margin:0;background:#f0f2f5} h2{color:#333} .card{display:inline-block;padding:20px;margin:10px;background:#fff;border-radius:8px;box-shadow:0 2px 5px rgba(0,0,0,0.1)} .val{font-size:2.5em;font-weight:bold}</style>
</head><body>
<h2>ESP8266 & INA219 实时监控</h2>
<div class="card"><h3>负载电压</h3><span class="val" id="v">--</span> V</div>
<div class="card"><h3>电流</h3><span class="val" id="c">--</span> mA</div>
<div class="card"><h3>功率</h3><span class="val" id="p">--</span> mW</div>
<script>
setInterval(() => {
fetch('/data').then(response => response.json()).then(data => {
document.getElementById('v').textContent = data.voltage.toFixed(2);
document.getElementById('c').textContent = data.current.toFixed(1);
document.getElementById('p').textContent = data.power.toFixed(0);
});
}, 500);
</script></body></html>
)rawliteral";
server.send(200, "text/html", html);
});
server.on("/data", [](){
sampleAveraged(5);
String json = "{";
json += "\"voltage\":" + String(loadVoltage) + ",";
json += "\"current\":" + String(current_mA) + ",";
json += "\"power\":" + String(power_mW);
json += "}";
server.send(200, "application/json", json);
});
server.begin();
Serial.println(">>> Web服务器已启动。您现在可以通过IP地址访问监控页面了。");
Serial.println("========================================\n");
}
// =================================================
// == 主循环 (持续运行) ==
// =================================================
void loop() {
server.handleClient(); // 持续处理网页客户端的请求
}

评论区(0 条)
发表评论⏳ 加载编辑器…