This commit is contained in:
2025-01-21 17:31:53 +08:00
parent 992b0e8498
commit eec83b3539
2 changed files with 175 additions and 82 deletions

View File

@ -80,59 +80,70 @@ bool BH1750::begin(Mode mode, byte addr, TwoWire* i2c) {
* @param mode Measurement mode * @param mode Measurement mode
*/ */
bool BH1750::configure(Mode mode) { bool BH1750::configure(Mode mode) {
// default transmission result to a value out of normal range
byte ack = 5;
int retries = 3;
// default transmission result to a value out of normal range // Check measurement mode is valid
byte ack = 5; switch (mode) {
case BH1750::CONTINUOUS_HIGH_RES_MODE:
case BH1750::CONTINUOUS_HIGH_RES_MODE_2:
case BH1750::CONTINUOUS_LOW_RES_MODE:
case BH1750::ONE_TIME_HIGH_RES_MODE:
case BH1750::ONE_TIME_HIGH_RES_MODE_2:
case BH1750::ONE_TIME_LOW_RES_MODE:
// Check measurement mode is valid while (retries > 0) {
switch (mode) { // Send mode to sensor
I2C->beginTransmission(BH1750_I2CADDR);
__wire_write((uint8_t)mode);
ack = I2C->endTransmission();
case BH1750::CONTINUOUS_HIGH_RES_MODE: if (ack == 0) {
case BH1750::CONTINUOUS_HIGH_RES_MODE_2: break;
case BH1750::CONTINUOUS_LOW_RES_MODE: }
case BH1750::ONE_TIME_HIGH_RES_MODE:
case BH1750::ONE_TIME_HIGH_RES_MODE_2:
case BH1750::ONE_TIME_LOW_RES_MODE:
// Send mode to sensor retries--;
I2C->beginTransmission(BH1750_I2CADDR); _delay_ms(100); // Wait before retrying
__wire_write((uint8_t)mode); }
ack = I2C->endTransmission();
// Wait a few moments to wake up // Wait a few moments to wake up
_delay_ms(10); _delay_ms(10);
break; break;
default: default:
// Invalid measurement mode // Invalid measurement mode
Serial.println(F("[BH1750] ERROR: Invalid mode")); Serial.println(F("[BH1750] ERROR: Invalid mode"));
break; return false;
} }
// Check result code // Check result code
switch (ack) { if (ack == 0) {
case 0: BH1750_MODE = mode;
BH1750_MODE = mode; lastReadTimestamp = millis();
lastReadTimestamp = millis(); return true;
return true; }
case 1: // too long for transmit buffer
Serial.println(F("[BH1750] ERROR: too long for transmit buffer"));
break;
case 2: // received NACK on transmit of address
Serial.println(F("[BH1750] ERROR: received NACK on transmit of address"));
break;
case 3: // received NACK on transmit of data
Serial.println(F("[BH1750] ERROR: received NACK on transmit of data"));
break;
case 4: // other error
Serial.println(F("[BH1750] ERROR: other error"));
break;
default:
Serial.println(F("[BH1750] ERROR: undefined error"));
break;
}
return false; // Print error message based on the result code
switch (ack) {
case 1: // too long for transmit buffer
Serial.println(F("[BH1750] ERROR: too long for transmit buffer"));
break;
case 2: // received NACK on transmit of address
Serial.println(F("[BH1750] ERROR: received NACK on transmit of address"));
break;
case 3: // received NACK on transmit of data
Serial.println(F("[BH1750] ERROR: received NACK on transmit of data"));
break;
case 4: // other error
Serial.println(F("[BH1750] ERROR: other error"));
break;
default:
Serial.println(F("[BH1750] ERROR: undefined error"));
break;
}
return false;
} }
/** /**
@ -299,20 +310,20 @@ void bh1750_init(BH1750& sensorA, BH1750& sensorB, int sdaA, int sclA, int sdaB,
sensorB.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &Wire1); sensorB.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &Wire1);
} }
float getLightLevel(BH1750& sensor, const char* sensorName) { // float getLightLevel(BH1750& sensor, const char* sensorName) {
if (sensor.measurementReady()) { // if (sensor.measurementReady()) {
float lightLevel = sensor.readLightLevel(); // float lightLevel = sensor.readLightLevel();
if (lightLevel >= 0) { // if (lightLevel >= 0) {
return lightLevel; // 正常返回光照强度 // return lightLevel; // 正常返回光照强度
} // }
} // }
//return -2.0; // //return -2.0;
} // }
void printLightLevels(BH1750& sensorA, BH1750& sensorB) { // void printLightLevels(BH1750& sensorA, BH1750& sensorB) {
float lightA = getLightLevel(sensorA, "Sensor A"); // float lightA = getLightLevel(sensorA, "Sensor A");
float lightB = getLightLevel(sensorB, "Sensor B"); // float lightB = getLightLevel(sensorB, "Sensor B");
// 打印光照强度信息 // // 打印光照强度信息
Serial.printf("A: %.0f lux :: B: %.0f lux\n", lightA, lightB); // Serial.printf("A: %.0f lux :: B: %.0f lux\n", lightA, lightB);
} // }

View File

@ -8,6 +8,15 @@
#include <Arduino.h> #include <Arduino.h>
#include "MCP45HVX1.h" #include "MCP45HVX1.h"
#include "INA226.h" #include "INA226.h"
#include <Ticker.h>
// 灯泡计时器相关变量
unsigned long activeDuration = 0; // 累计使用时长(秒)
unsigned long lastMillis = 0; // 上次更新计时时间
bool isActive = false; // 是否正在计时
// Ticker 用于定时检查电流状态
Ticker currentCheckTicker;
// MCP45HVX1 数字电位器 // MCP45HVX1 数字电位器
MCP45HVX1 digiPot(0x3F); MCP45HVX1 digiPot(0x3F);
@ -20,7 +29,7 @@ AsyncWebServer server(80);
const char* ssid = "SERVIRST-CT"; const char* ssid = "SERVIRST-CT";
const char* password = "servirst8888"; const char* password = "servirst8888";
// BH1750 // DS18B20 温度传感器
#define ONE_WIRE_BUS 8 #define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS); OneWire oneWire(ONE_WIRE_BUS);
DS18B20 sensor(&oneWire); DS18B20 sensor(&oneWire);
@ -34,7 +43,6 @@ BH1750 bh1750_b;
#define TJC_RX_Pin 41 #define TJC_RX_Pin 41
// HTML 页面内容 // HTML 页面内容
const char index_html[] PROGMEM = R"rawliteral( const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html> <!DOCTYPE html>
@ -43,7 +51,12 @@ const char index_html[] PROGMEM = R"rawliteral(
<title>ESP32 Data Display</title> <title>ESP32 Data Display</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<script> <script>
async function fetchData() { async function fetchData()
{
const durationResponse = await fetch('/duration');
const durationText = await durationResponse.text();
document.getElementById('activeDuration').innerText = durationText;
const tempResponse = await fetch('/temperature'); const tempResponse = await fetch('/temperature');
const tempText = await tempResponse.text(); const tempText = await tempResponse.text();
document.getElementById('temperature').innerText = tempText; document.getElementById('temperature').innerText = tempText;
@ -77,7 +90,8 @@ const char index_html[] PROGMEM = R"rawliteral(
document.getElementById('power').innerText = powerText; document.getElementById('power').innerText = powerText;
} }
async function setWiper() { async function setWiper()
{
const wiperValue = document.getElementById('wiperValue').value; const wiperValue = document.getElementById('wiperValue').value;
const response = await fetch('/setWiper', { const response = await fetch('/setWiper', {
method: 'POST', method: 'POST',
@ -91,11 +105,23 @@ const char index_html[] PROGMEM = R"rawliteral(
} }
} }
async function resetDuration()
{
const response = await fetch('/resetDuration', { method: 'POST' });
if (response.ok) {
alert('使');
} else {
alert('');
}
}
setInterval(fetchData, 1000); setInterval(fetchData, 1000);
</script> </script>
</head> </head>
<body onload="fetchData()"> <body onload="fetchData()">
<h1></h1> <h1></h1>
<p>使: <span id="activeDuration">...</span></p>
<button onclick="resetDuration()"></button>
<p>: <span id="temperature">...</span> °C</p> <p>: <span id="temperature">...</span> °C</p>
<p>A: <span id="lightA">...</span> lx</p> <p>A: <span id="lightA">...</span> lx</p>
<p>B: <span id="lightB">...</span> lx</p> <p>B: <span id="lightB">...</span> lx</p>
@ -113,7 +139,41 @@ const char index_html[] PROGMEM = R"rawliteral(
// 清空累计使用时长
void resetActiveDuration() {
activeDuration = 0;
}
// 检查电流并更新计时状态
void checkCurrent() {
float current = INA.getCurrent_mA();
if (current > 1000.0) {
if (!isActive) {
// 开始计时
isActive = true;
lastMillis = millis();
}
} else {
if (isActive) {
// 停止计时并累加
activeDuration += (millis() - lastMillis) / 1000;
isActive = false;
}
}
// 如果正在计时,实时更新计时
if (isActive) {
activeDuration += (millis() - lastMillis) / 1000;
lastMillis = millis();
}
}
// 将秒数格式化为小时和分钟
String formatDuration(unsigned long seconds) {
unsigned long hours = seconds / 3600;
unsigned long minutes = (seconds % 3600) / 60;
return String(hours) + " 小时 " + String(minutes) + " 分钟";
}
// 初始化Web // 初始化Web
void WebServer_Init(const char* ssid, const char* password) void WebServer_Init(const char* ssid, const char* password)
@ -124,7 +184,7 @@ void WebServer_Init(const char* ssid, const char* password)
delay(1000); delay(1000);
Serial.println("Connecting to WiFi..."); Serial.println("Connecting to WiFi...");
} }
Serial.println("Connected to WiFi"); Serial.print("Address: ");
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
// 根路径的页面 // 根路径的页面
@ -185,6 +245,17 @@ void WebServer_Init(const char* ssid, const char* password)
request->send(200, "text/plain", power); request->send(200, "text/plain", power);
}); });
// 获取累计时长接口
server.on("/duration", HTTP_GET, [](AsyncWebServerRequest *request) {
request->send(200, "text/plain", formatDuration(activeDuration));
});
// 清空累计时长接口
server.on("/resetDuration", HTTP_POST, [](AsyncWebServerRequest *request) {
resetActiveDuration();
request->send(200, "text/plain", "Duration reset");
});
// 接收设置Wiper的请求 // 接收设置Wiper的请求
server.on("/setWiper", HTTP_POST, [](AsyncWebServerRequest *request) { server.on("/setWiper", HTTP_POST, [](AsyncWebServerRequest *request) {
if (request->hasParam("value", true)) { if (request->hasParam("value", true)) {
@ -201,10 +272,20 @@ void WebServer_Init(const char* ssid, const char* password)
} }
// 陶晶池串口屏显示二维码
void TCJ_ShowQR(void)
{
char addr[64];
IPAddress ip = WiFi.localIP();
sprintf(addr, "qr0.txt=\"http://%d.%d.%d.%d/\"\xff\xff\xff", ip[0], ip[1], ip[2], ip[3]);
TJC.print(addr);
}
//陶晶池串口屏发送 //陶晶池串口屏发送
void TJC_Show(void) void TJC_Show(void)
{ {
char str[128]; char str[128];
sprintf(str, "t0.txt=\"%.2f\"\xff\xff\xff", sensor.getTempC());//用sprintf来格式化字符串给t0的txt属性赋值 sprintf(str, "t0.txt=\"%.2f\"\xff\xff\xff", sensor.getTempC());//用sprintf来格式化字符串给t0的txt属性赋值
TJC.print(str); //把字符串发送出去 TJC.print(str); //把字符串发送出去
@ -228,7 +309,6 @@ void TJC_Show(void)
} }
void setup(void) void setup(void)
{ {
Serial.begin(115200); Serial.begin(115200);
@ -242,23 +322,26 @@ void setup(void)
// INA226 初始化 // INA226 初始化
INA.setMaxCurrentShunt(10, 0.002); // 设置最大电流和分流电阻 INA.setMaxCurrentShunt(10, 0.002); // 设置最大电流和分流电阻
//sensor.begin();
// BH1750 初始化
//bh1750_init(bh1750_a, bh1750_b, 36, 35, 21, 20); //1750初始化。sda, scl
//Wire.begin(36,35);
Wire1.begin(21, 20);
bh1750_a.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &Wire);
bh1750_b.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &Wire1);
//WebServer 初始化
WebServer_Init(ssid, password);
// 启动定时器,每秒检查电流状态
currentCheckTicker.attach(1, checkCurrent);
// 串口屏初始化 // 串口屏初始化
TJC.begin(115200, SERIAL_8N1, TJC_RX_Pin, TJC_TX_Pin); TJC.begin(115200, SERIAL_8N1, TJC_RX_Pin, TJC_TX_Pin);
while (TJC.read() >= 0); //因为串口屏开机会发送88 ff ff ff,所以要清空串口缓冲区 while (TJC.read() >= 0); //因为串口屏开机会发送88 ff ff ff,所以要清空串口缓冲区
TJC.print("page main\xff\xff\xff"); //发送命令让屏幕跳转到main页面 TJC.print("page main\xff\xff\xff"); //发送命令让屏幕跳转到main页面
//sensor.begin(); TCJ_ShowQR();
// BH1750 初始化
bh1750_init(bh1750_a, bh1750_b, 36, 35, 21, 20); //1750初始化。sda, scl
// Wire.begin(36,35);
// Wire1.begin(21, 20);
// bh1750_a.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &Wire);
// bh1750_b.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &Wire1);
//WebServer 初始化
WebServer_Init(ssid, password);
} }
@ -274,11 +357,11 @@ void loop(void)
// MCP45HVX1 操作 // MCP45HVX1 操作
//digiPot.writeWiper(127); // 随机设置 Wiper 值,random(0, 256) //digiPot.writeWiper(127); // 随机设置 Wiper 值,random(0, 256)
//delay(500); //delay(500);
Serial.print("Current Wiper Value: "); Serial.print("Current Wiper Value: ");
Serial.println(digiPot.readWiper()); Serial.println(digiPot.readWiper());
// INA226 数据读取 // INA226 数据读取
Serial.println("\nBUS\tSHUNT\tCURRENT\tPOWER"); Serial.println("\nBUS\tSHUNT\tCURRENT\tPOWER");
Serial.print(INA.getBusVoltage(), 3); Serial.print(INA.getBusVoltage(), 3);
Serial.print("\t"); Serial.print("\t");
Serial.print(INA.getShuntVoltage_mV(), 3); Serial.print(INA.getShuntVoltage_mV(), 3);
@ -289,7 +372,6 @@ void loop(void)
Serial.println(); Serial.println();
TJC_Show(); //串口屏 TJC_Show(); //串口屏
delay(1000); delay(1000);