diff --git a/data/logic.js b/data/logic.js index e774409..4d554b4 100644 --- a/data/logic.js +++ b/data/logic.js @@ -7,7 +7,7 @@ window.addEventListener('DOMContentLoaded', (event) => { fetch(apiUrl) .then(response => response.json()) .then(data => { - document.getElementById('voltage').textContent = roundToTwo(data.voltage)+ ' V' || 'N/A'; + document.getElementById('voltage').textContent = roundToTwo(data.bus_voltage)+ ' V' || 'N/A'; document.getElementById('current').textContent = roundToTwo(data.current)+ ' mA' || 'N/A'; }) .catch(error => { @@ -19,6 +19,49 @@ window.addEventListener('DOMContentLoaded', (event) => { setInterval(fetchData, 5000); // fetch every 5 seconds }); +window.addEventListener('DOMContentLoaded', (event) => { + // URL of your API + const apiUrl = '/telemetry'; + + function fetchData() { + // Fetching data from the API + fetch(apiUrl) + .then(response => response.json()) + .then(data => { + document.getElementById('uptime').textContent = roundToTwo(data.uptime_seconds)+ ' s' || 'N/A'; + document.getElementById('heap').textContent = roundToTwo(data.heap_percent)+ ' %' || 'N/A'; + }) + .catch(error => { + console.error("There was an error fetching data from the API", error); + }); + } + + fetchData(); // fetch immediately on page load + setInterval(fetchData, 5000); // fetch every 5 seconds +}); + +window.addEventListener('DOMContentLoaded', (event) => { + // URL of your API + const apiUrl = '/water_data'; + + function fetchData() { + // Fetching data from the API + fetch(apiUrl) + .then(response => response.json()) + .then(data => { + document.getElementById('level').textContent = roundToTwo(data.water_height)+ ' cm' || 'N/A'; + document.getElementById('liters').textContent = roundToTwo(data.liters)+ ' l' || 'N/A'; + document.getElementById('percentage').textContent = roundToTwo(data.percentage)+ ' %' || 'N/A'; + }) + .catch(error => { + console.error("There was an error fetching data from the API", error); + }); + } + + fetchData(); // fetch immediately on page load + setInterval(fetchData, 5000); // fetch every 5 seconds +}); + window.addEventListener('DOMContentLoaded', (event) => { const apiUrl = '/network_info'; diff --git a/data/settings.html b/data/settings.html index 6bc8904..89d0377 100644 --- a/data/settings.html +++ b/data/settings.html @@ -20,39 +20,39 @@ - -
- Settings -

- - -

-

- - -

-

- - -

-

- - -

- -

- -

-
+
+
+ Settings +

+ + +

+

+ + +

+

+ + +

+

+ + +

+

+ +

+
+
WiFi Settings -

+ +

diff --git a/data/status.html b/data/status.html index 9a1ceb3..35b3be2 100644 --- a/data/status.html +++ b/data/status.html @@ -42,6 +42,29 @@ + +

+
+

Water information

+
+ + + + + + + + + + + + + + + + +
Waterlevel: WAITING
Water volumen: WAITING
Percentage: WAITING
+
@@ -69,15 +92,11 @@ Uptime: - 132d + XXX - FW version: - 0.2 - - - Time/Date: - 1.1.202022 + Heap usage: + XXX diff --git a/readme.md b/readme.md index 56fa415..7c6b204 100644 --- a/readme.md +++ b/readme.md @@ -8,4 +8,15 @@ Config fields: - ssid -- wifi_password \ No newline at end of file +- wifi_password + +- range +- level_min +- level_max +- liters + + +#define level_sensor_range_key "range" +#define water_level_min_key "level_min" +#define water_level_max_key "level_max" +#define liters_key "liters" \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 909955a..ecee195 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,7 @@ #include "INA226.h" #include "Wire.h" + #include #define LED_1 4 @@ -26,14 +27,17 @@ // Define keys to prevent typos #define ssid_key "ssid" #define wifi_password_key "wifi_password" +#define level_sensor_range_key "range" +#define water_level_min_key "level_min" +#define water_level_max_key "level_max" +#define liters_key "liters" + +#define RESISTOR_VALUE 4 extern "C" int rom_phy_get_vdd33(); // Calibration variables float zero_value = 0.03; // Measured shunt voltage with nothing connected, used to fix measuring offset -float max_water_level_cm = 200; -float min_water_level_cm = 0; -float sensor_range = 2.0; bool voltage_high = false; bool voltage_low = false; @@ -43,12 +47,21 @@ bool current_low = false; uint8_t failed_connection_attempts = 0; struct SensorData { - int percentage; - float voltage; - float current; - float water_height; + float bus_voltage; + float shunt_voltage; + float shunt_current; }; +struct WaterData{ + // Water level in cm + float level; + // Water volume in liters + float liters; + // Percentage + float percentage; +}; + + struct NetworkData { String ip_address; bool link; @@ -65,11 +78,18 @@ NetworkData wifi_data; NetworkData ethernet_data; DeviceTelemetry telemetry; -SensorData current_data = SensorData { -1, -1, -1, -1 }; +SensorData shunt_data; +WaterData water_data; int64_t mac_address = ESP.getEfuseMac(); +//#define INA226 + +// #ifdef INA226 INA226 ina_sensor(0x40); +// #else +// INA233 ina_sensor(); +// #endif Preferences prefs; @@ -152,7 +172,7 @@ void display_task(void* parameter) while (true) { if (!is_error()) { // We have no error, refresh status display and wait half a second - display_percentage(current_data.percentage); + display_percentage(water_data.percentage); } else { Log.verbose("Error detected"); // We have an error, display error code for 3 seconds and then water level for 3 seconds @@ -166,7 +186,7 @@ void display_task(void* parameter) display_error_code(4); } delay(3000); - display_percentage(current_data.percentage); + display_percentage(water_data.percentage); } } } @@ -243,33 +263,60 @@ void collect_internal_telemetry_task(void* parameter) void read_sensor_task(void* parameter) { while (true) { + // Get Values from sensor float bus_voltage = ina_sensor.getBusVoltage(); float shunt_voltage = ina_sensor.getShuntVoltage_mV() - zero_value; - float shunt_current = shunt_voltage / 4; + float shunt_current = shunt_voltage / RESISTOR_VALUE; + + // Get values from storage + float sensor_range = prefs.getFloat(level_sensor_range_key, 200); + float max_water_level = prefs.getFloat(water_level_max_key, sensor_range); + float min_water_level = prefs.getFloat(water_level_min_key, 0); + float max_liters = prefs.getFloat(liters_key, 10000.); + + float mA_per_cm = (20. - 4.) / (sensor_range); - float mA_per_cm = (20 - 4) / (sensor_range * 100); - - float min_water_level_mA_over_zero = (min_water_level_cm * mA_per_cm); - float max_water_level_mA_over_zero = (max_water_level_cm * mA_per_cm); + // Get mA over 0cm/4mA for max/min water level + float min_water_level_mA_over_zero = (min_water_level * mA_per_cm); + float max_water_level_mA_over_zero = (max_water_level * mA_per_cm); + // Levels which represent raw sensor value, with 4mA added float min_water_level_mA = 4 + min_water_level_mA_over_zero; float max_water_level_mA = 4 + max_water_level_mA_over_zero; - // Over Zero always revers to zero water level + Log.verbose("max_water_level_mA: %F", max_water_level_mA); + Log.verbose("min_water_level_mA_over_zero: %F", min_water_level_mA_over_zero); + + // Current over the 0 level of the water float shunt_current_over_zero = shunt_current - min_water_level_mA; - int percentage = round((shunt_current_over_zero / max_water_level_mA_over_zero) * 100); + // cm over zero water level + float cm_over_zero = shunt_current_over_zero / mA_per_cm; + + // Raw unrounded percentage in decimal + float percentage_raw = (shunt_current_over_zero / (max_water_level_mA_over_zero - min_water_level_mA_over_zero)); + float percentage_rounded = round(percentage_raw*100*100)/100; + + // Tank volume in liters + float liters_raw = max_liters * percentage_raw; + int liters = round(liters_raw); current_low = shunt_current < 3.8; current_high = shunt_current > 20.2; voltage_low = bus_voltage < 23; voltage_high = bus_voltage > 25; - Log.verbose("Bus current: %F", bus_voltage); Log.verbose("Shunt current: %F", shunt_current); Log.verbose("Shunt voltage: %F", shunt_voltage); - Log.verbose("Value percentage: %F", percentage); + Log.verbose("Bus voltage: %F", bus_voltage); + Log.verbose("cm_over_zero: %F", cm_over_zero); - current_data = SensorData { percentage, bus_voltage, shunt_current, shunt_current_over_zero }; + shunt_data.bus_voltage = bus_voltage; + shunt_data.shunt_voltage = shunt_voltage; + shunt_data.shunt_current = shunt_current; + + water_data.level = cm_over_zero; + water_data.liters = liters; + water_data.percentage = percentage_rounded; delay(20000); } @@ -344,12 +391,52 @@ void setup() request->send(SPIFFS, "/settings.html", "text/html", false); // TODO add proper return templating }); + server.on("/update_sensor_settings", HTTP_POST, [](AsyncWebServerRequest* request) { + int params = request->params(); + + if (request->hasParam(level_sensor_range_key, true) && request->hasParam(water_level_min_key, true) && request->hasParam(water_level_max_key, true) && request->hasParam(liters_key, true)) { + Log.verbose("Updating Sensor config"); + AsyncWebParameter* range_param = request->getParam(level_sensor_range_key, true); + AsyncWebParameter* level_min_param = request->getParam(water_level_min_key, true); + AsyncWebParameter* level_max_param = request->getParam(water_level_max_key, true); + AsyncWebParameter* liters_param = request->getParam(liters_key, true); + + prefs.putFloat(level_sensor_range_key, range_param->value().toFloat()); + prefs.putFloat(water_level_min_key, level_min_param->value().toFloat()); + prefs.putFloat(water_level_max_key, level_max_param->value().toFloat()); + prefs.putFloat(liters_key, liters_param->value().toFloat()); + } else { + Log.verbose("!!!! FAIL lo"); + for (int i = 0; i < params; i++) { + AsyncWebParameter* p = request->getParam(i); + if (p->isFile()) { // p->isPost() is also true + Log.verbose("POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } else if (p->isPost()) { + Log.verbose("POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } else { + Log.verbose("GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); + } + } + request->send(400, "text/plain", "Missing parameters"); // TODO add proper error messages + } + request->send(SPIFFS, "/settings.html", "text/html", false); // TODO add proper return templating + }); + server.on("/sensor_data", HTTP_GET, [](AsyncWebServerRequest* request) { StaticJsonDocument<128> doc; - doc["percentage"] = current_data.percentage; - doc["voltage"] = current_data.voltage; - doc["current"] = current_data.current; - doc["water_height"] = current_data.water_height; + doc["bus_voltage"] = shunt_data.bus_voltage; + doc["shunt_voltage"] = shunt_data.shunt_voltage; + doc["current"] = shunt_data.shunt_current; + + String output; + serializeJson(doc, output); + request->send(200, "application/json", output); }); + + server.on("/water_data", HTTP_GET, [](AsyncWebServerRequest* request) { + StaticJsonDocument<128> doc; + doc["percentage"] = water_data.percentage; + doc["water_height"] = water_data.level; + doc["liters"] = water_data.liters; String output; serializeJson(doc, output);