diff --git a/src/DS18B20.h b/src/DS18B20.h index 89cd0ab..372dfae 100644 --- a/src/DS18B20.h +++ b/src/DS18B20.h @@ -1,3 +1,6 @@ +#ifndef DS18B20_H +#define DS18B20_H + #include "OneWire.h" @@ -58,6 +61,6 @@ private: float _offset; }; - +#endif // DS18B20_H // -- END OF FILE -- diff --git a/src/RunTime.cpp b/src/RunTime.cpp new file mode 100644 index 0000000..ec02d1b --- /dev/null +++ b/src/RunTime.cpp @@ -0,0 +1,54 @@ +#include "RunTime.h" +#include + +RunTime runtime; + +extern INA226 INA; + +RunTime::RunTime() : activeDuration(0), lastMillis(0), isActive(false) {} + +void RunTime::begin() { + preferences.begin("timing", false); + activeDuration = preferences.getULong("activeDuration", 0); // 从 NVS 加载数据 +} + +void RunTime::checkCurrent() { + float current = INA.getBusVoltage(); + if (current > 10.0) { + if (!isActive) { + // 开始计时 + isActive = true; + lastMillis = millis(); + } + } else { + if (isActive) { + // 停止计时并累加 + activeDuration += (millis() - lastMillis) / 1000; + isActive = false; + preferences.putULong("activeDuration", activeDuration); // 保存到 NVS + } + } + + // 如果正在计时,实时更新计时 + if (isActive) { + activeDuration += (millis() - lastMillis) / 1000; + lastMillis = millis(); + preferences.putULong("activeDuration", activeDuration); // 保存到 NVS + } +} + +void RunTime::resetActiveDuration() { + activeDuration = 0; + preferences.putULong("activeDuration", activeDuration); // 保存到 NVS +} + +unsigned long RunTime::getActiveDuration() const { + return activeDuration; +} + +String RunTime::formatDuration(unsigned long seconds) const { + unsigned long hours = seconds / 3600; + unsigned long minutes = (seconds % 3600) / 60; + unsigned long secondsRemain = seconds % 60; + return String(hours) + ":" + String(minutes)+ ":" + String(secondsRemain); +} \ No newline at end of file diff --git a/src/RunTime.h b/src/RunTime.h new file mode 100644 index 0000000..21e0ee3 --- /dev/null +++ b/src/RunTime.h @@ -0,0 +1,26 @@ +#ifndef RUNTIME_H +#define RUNTIME_H + +#include "INA226.h" +#include + +class RunTime { +public: + RunTime(); + void begin(); + void checkCurrent(); + void resetActiveDuration(); + unsigned long getActiveDuration() const; + String formatDuration(unsigned long seconds) const; + +private: + Preferences preferences; + unsigned long activeDuration; // 累计使用时长(秒) + unsigned long lastMillis; // 上次更新计时时间 + bool isActive; // 是否正在计时 + +}; + +//extern Runtime runtime; + +#endif \ No newline at end of file diff --git a/src/TJC_Show.cpp b/src/TJC_Show.cpp index e69de29..abbe491 100644 --- a/src/TJC_Show.cpp +++ b/src/TJC_Show.cpp @@ -0,0 +1,53 @@ +#include "TJC_Show.h" + + +extern RunTime runtime; + +TJC_Show::TJC_Show(HardwareSerial& serial, DS18B20& sensor, BH1750& bh1750_a, BH1750& bh1750_b, MCP45HVX1& digiPot, INA226& INA) + : _serial(serial), _sensor(sensor), _bh1750_a(bh1750_a), _bh1750_b(bh1750_b), _digiPot(digiPot), _INA(INA) {} + + +// 陶晶池串口屏初始化 +void TJC_Show::TJC_Show_Init() +{ + _serial.begin(115200, SERIAL_8N1, TJC_RX_Pin, TJC_TX_Pin); + while (_serial.read() >= 0); // 清空串口缓冲区 + _serial.print("page main\xff\xff\xff"); // 跳转到 main 页面 +} + +// 陶晶池串口屏显示二维码 +void TJC_Show::showQR() +{ + 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]); + _serial.print(addr); +} + +//陶晶池串口屏发送 +void TJC_Show::showINFO(unsigned long activeDuration) { + char str[128]; + + sprintf(str, "t0.txt=\"%.2f\"\xff\xff\xff", _sensor.getTempC()); + _serial.print(str); + + sprintf(str, "t1.txt=\"%.f\"\xff\xff\xff", _bh1750_a.readLightLevel()); + _serial.print(str); + sprintf(str, "t2.txt=\"%.f\"\xff\xff\xff", _bh1750_b.readLightLevel()); + _serial.print(str); + + sprintf(str, "t14.txt=\"%s\"\xff\xff\xff", runtime.formatDuration(runtime.getActiveDuration())); + _serial.print(str); + + sprintf(str, "t8.txt=\"%d\"\xff\xff\xff", _digiPot.readWiper()); + _serial.print(str); + + sprintf(str, "t9.txt=\"%.3f\"\xff\xff\xff", _INA.getBusVoltage(), 3); + _serial.print(str); + sprintf(str, "t10.txt=\"%.3f\"\xff\xff\xff", _INA.getShuntVoltage_mV(), 3); + _serial.print(str); + sprintf(str, "t11.txt=\"%.3f\"\xff\xff\xff", _INA.getCurrent_mA(), 3); + _serial.print(str); + sprintf(str, "t12.txt=\"%.3f\"\xff\xff\xff", _INA.getPower_mW(), 3); + _serial.print(str); +} \ No newline at end of file diff --git a/src/TJC_Show.h b/src/TJC_Show.h index e69de29..1db1637 100644 --- a/src/TJC_Show.h +++ b/src/TJC_Show.h @@ -0,0 +1,33 @@ +#ifndef TJC_SHOW_H +#define TJC_SHOW_H + +#include +#include "BH1750.h" +#include "DS18B20.h" +#include "MCP45HVX1.h" +#include "INA226.h" +#include +#include "RunTime.h" + +//陶晶池串口屏 +#define TJC Serial1 +#define TJC_TX_Pin 42 +#define TJC_RX_Pin 41 + +class TJC_Show { +public: + TJC_Show(HardwareSerial& serial, DS18B20& sensor, BH1750& bh1750_a, BH1750& bh1750_b, MCP45HVX1& digiPot, INA226& INA); + void TJC_Show_Init(); + void showQR(); + void showINFO(unsigned long activeDuration); + +private: + HardwareSerial& _serial; + DS18B20& _sensor; + BH1750& _bh1750_a; + BH1750& _bh1750_b; + MCP45HVX1& _digiPot; + INA226& _INA; +}; + +#endif // TJC_SHOW_H \ No newline at end of file diff --git a/src/WebServer.cpp b/src/WebServer.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/WebServer.h b/src/WebServer.h new file mode 100644 index 0000000..e69de29 diff --git a/src/main.cpp b/src/main.cpp index bd78129..d8791d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,14 +10,10 @@ #include "INA226.h" #include #include // 用于存储非易失性数据 +#include "TJC_Show.h" +#include "RunTime.h" -Preferences preferences; - -// 灯泡计时器 -unsigned long activeDuration = 0; // 累计使用时长(秒) -unsigned long lastMillis = 0; // 上次更新计时时间 -bool isActive = false; // 是否正在计时 // Ticker 用于定时检查电流状态 Ticker currentCheckTicker; @@ -26,7 +22,7 @@ Ticker currentCheckTicker; MCP45HVX1 digiPot(0x3E); // INA226 电流监控器 -INA226 INA(0x40); +INA226 INA(0x40); AsyncWebServer server(80); @@ -36,16 +32,11 @@ const char* password = "servirst8888"; // DS18B20 温度传感器 #define ONE_WIRE_BUS 8 OneWire oneWire(ONE_WIRE_BUS); -DS18B20 sensor(&oneWire); +DS18B20 ds18b20(&oneWire); BH1750 bh1750_a; BH1750 bh1750_b; -//陶晶池串口屏 -#define TJC Serial1 -#define TJC_TX_Pin 42 -#define TJC_RX_Pin 41 - // 风扇控制引脚 #define FAN_PIN1 15 @@ -54,6 +45,10 @@ BH1750 bh1750_b; // 蜂鸣器引脚 #define BUZZER_PIN 17 +extern RunTime runtime; +int activeDuration; + +Preferences prefs; // HTML 页面内容 const char index_html[] PROGMEM = R"rawliteral( @@ -150,46 +145,6 @@ const char index_html[] PROGMEM = R"rawliteral( )rawliteral"; - -// 清空累计使用时长 -void resetActiveDuration() { - activeDuration = 0; - preferences.putULong("activeDuration", activeDuration); // 保存到 NVS -} - -// 检查电流并更新计时状态 -void checkCurrent() { - float current = INA.getCurrent_mA(); - if (current > 100.0) { - if (!isActive) { - // 开始计时 - isActive = true; - lastMillis = millis(); - } - } else { - if (isActive) { - // 停止计时并累加 - activeDuration += (millis() - lastMillis) / 1000; - isActive = false; - preferences.putULong("activeDuration", activeDuration); // 保存到 NVS - } - } - - // 如果正在计时,实时更新计时 - if (isActive) { - activeDuration += (millis() - lastMillis) / 1000; - lastMillis = millis(); - preferences.putULong("activeDuration", activeDuration); // 保存到 NVS - } -} - -// 将秒数格式化为小时和分钟 -String formatDuration(unsigned long seconds) { - unsigned long hours = seconds / 3600; - unsigned long minutes = (seconds % 3600) / 60; - return String(hours) + " : " + String(minutes); -} - // 初始化Web void WebServer_Init(const char* ssid, const char* password) { @@ -211,7 +166,7 @@ void WebServer_Init(const char* ssid, const char* password) // 温度接口 server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request) { - String temp = String(sensor.getTempC()); + String temp = String(ds18b20.getTempC()); request->send(200, "text/plain", temp); }); @@ -262,12 +217,12 @@ void WebServer_Init(const char* ssid, const char* password) // 获取累计时长接口 server.on("/duration", HTTP_GET, [](AsyncWebServerRequest *request) { - request->send(200, "text/plain", formatDuration(activeDuration)); + request->send(200, "text/plain", runtime.formatDuration(runtime.getActiveDuration())); }); // 清空累计时长接口 server.on("/resetDuration", HTTP_POST, [](AsyncWebServerRequest *request) { - resetActiveDuration(); + runtime.resetActiveDuration(); request->send(200, "text/plain", "Duration reset"); }); @@ -287,48 +242,9 @@ 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) -{ - char str[128]; - - sprintf(str, "t0.txt=\"%.2f\"\xff\xff\xff", sensor.getTempC());//用sprintf来格式化字符串,给t0的txt属性赋值 - TJC.print(str); //把字符串发送出去 - - sprintf(str, "t1.txt=\"%.f\"\xff\xff\xff", bh1750_a.readLightLevel()); - TJC.print(str); - sprintf(str, "t2.txt=\"%.f\"\xff\xff\xff", bh1750_b.readLightLevel()); - TJC.print(str); - - sprintf(str, "t14.txt=\"%s\"\xff\xff\xff", formatDuration(activeDuration)); - TJC.print(str); - - sprintf(str, "t8.txt=\"%d\"\xff\xff\xff", digiPot.readWiper()); - TJC.print(str); - - sprintf(str, "t9.txt=\"%.3f\"\xff\xff\xff", INA.getBusVoltage(), 3); - TJC.print(str); - sprintf(str, "t10.txt=\"%.3f\"\xff\xff\xff", INA.getShuntVoltage_mV(), 3); - TJC.print(str); - sprintf(str, "t11.txt=\"%.3f\"\xff\xff\xff", INA.getCurrent_mA(), 3); - TJC.print(str); - sprintf(str, "t12.txt=\"%.3f\"\xff\xff\xff", INA.getPower_mW(), 3); - TJC.print(str); - -} - // 风扇控制 void FansControl(void) { - if (sensor.getTempC() > 25) { + if (ds18b20.getTempC() > 25) { digitalWrite(FAN_PIN1, HIGH); digitalWrite(FAN_PIN2, HIGH); } else { @@ -337,36 +253,37 @@ void FansControl(void) { } } -// 蜂鸣器报警 +// 蜂鸣器 void Buzzer(void) { - if (sensor.getTempC() > 50) { - tone(BUZZER_PIN, 1000, 1000); + if (ds18b20.getTempC() > 20) { + digitalWrite(BUZZER_PIN, HIGH); + //tone(BUZZER_PIN, 1000, 1000); } else { - noTone(BUZZER_PIN); + digitalWrite(BUZZER_PIN, LOW); + //noTone(BUZZER_PIN); } } +TJC_Show tjcShow(TJC, ds18b20, bh1750_a, bh1750_b, digiPot, INA); + void setup(void) { - Serial.begin(115200); - - // 初始化 NVS 存储 - preferences.begin("timing", false); - activeDuration = preferences.getULong("activeDuration", 0); // 从 NVS 加载数据 - - // 启动定时器,每秒检查电流状态 - currentCheckTicker.attach(1, checkCurrent); + Serial.begin(115200); // 初始化 I2C 总线 Wire.begin(5, 4); // SDA SCL + // INA226 初始化 + INA.setMaxCurrentShunt(10.0, 0.005); // 设置最大电流和分流电阻 + // MCP45HVX1 初始化 digiPot.begin(5, 4); - // INA226 初始化 - INA.setMaxCurrentShunt(10.0, 0.005); // 设置最大电流和分流电阻 + // 启动定时器,每秒检查电流状态 + //currentCheckTicker.attach(1, checkCurrent); + currentCheckTicker.attach(1, []() { runtime.checkCurrent(); }); //sensor.begin(); // BH1750 初始化 @@ -379,18 +296,19 @@ void setup(void) //WebServer 初始化 WebServer_Init(ssid, password); - // 串口屏初始化 - TJC.begin(115200, SERIAL_8N1, TJC_RX_Pin, TJC_TX_Pin); - while (TJC.read() >= 0); //因为串口屏开机会发送88 ff ff ff,所以要清空串口缓冲区 - TJC.print("page main\xff\xff\xff"); //发送命令让屏幕跳转到main页面 + // 初始化 runtime NVS + runtime.begin(); - TCJ_ShowQR(); + // 串口屏初始化 + tjcShow.TJC_Show_Init(); + + tjcShow.showQR(); } void loop(void) {// put your main code here, to run repeatedly: - sensor.printTemperature(); //ds18b20温度 + ds18b20.printTemperature(); //ds18b20温度 //printLightLevels(bh1750_a, bh1750_b); //bh1750照度 Serial.printf("A: %.0f lux :: B: %.0f lux \n", @@ -399,7 +317,7 @@ void loop(void) // MCP45HVX1 操作 //digiPot.writeWiper(127); // 随机设置 Wiper 值,random(0, 256) - //delay(500); + Serial.print("Current Wiper Value: "); Serial.println(digiPot.readWiper()); @@ -415,7 +333,11 @@ void loop(void) Serial.println(); - TJC_Show(); //串口屏 + tjcShow.showINFO(activeDuration); //串口屏 + + + FansControl(); + Buzzer(); delay(1000); }