dasdas
All checks were successful
Test compiling project / test (push) Successful in 1m44s

This commit is contained in:
2023-10-08 01:43:41 +02:00
parent dd136784e6
commit 496e7833f8
5 changed files with 220 additions and 60 deletions

View File

@@ -7,7 +7,7 @@ window.addEventListener('DOMContentLoaded', (event) => {
fetch(apiUrl) fetch(apiUrl)
.then(response => response.json()) .then(response => response.json())
.then(data => { .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'; document.getElementById('current').textContent = roundToTwo(data.current)+ ' mA' || 'N/A';
}) })
.catch(error => { .catch(error => {
@@ -19,6 +19,49 @@ window.addEventListener('DOMContentLoaded', (event) => {
setInterval(fetchData, 5000); // fetch every 5 seconds 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) => { window.addEventListener('DOMContentLoaded', (event) => {
const apiUrl = '/network_info'; const apiUrl = '/network_info';

View File

@@ -20,38 +20,38 @@
</div> </div>
</nav> </nav>
<form action="/update_sensor_settings" method="post">
<fieldset id="form-settings"> <fieldset id="form-settings">
<legend>Settings</legend> <legend>Settings</legend>
<p> <p>
<label for="input__text">Sensor max height (e.g. 4m)</label> <label for="range">Sensor Range in cm</label>
<input id="input__text" type="number" placeholder="Text Input"> <input id="range" name="range" type="number" placeholder="200">
</p> </p>
<p> <p>
<label for="input__password">Water max height</label> <label for="level_max">Water max height in cm</label>
<input id="input__password" type="number"> <input id="level_max" name="level_max" type="number">
</p> </p>
<p> <p>
<label for="input__webaddress">Water min height</label> <label for="level_min">Water min height in cm</label>
<input id="input__webaddress" type="number"> <input id="level_min" name="level_min" type="number">
</p> </p>
<p> <p>
<label for="input__emailaddress">Email Address</label> <label for="liters">Volume in liters</label>
<input id="input__emailaddress" type="number"> <input id="liters" name="liters" type="number">
</p> </p>
<p> <p>
<button class="button primary" style="width: 100%;">Submit</button> <button class="button primary" style="width: 100%;">Submit</button>
</p> </p>
</fieldset> </fieldset>
</form>
<form action="/update_wifi_credentials" method="post"> <form action="/update_wifi_credentials" method="post">
<fieldset id="form-settings"> <fieldset id="form-settings">
<legend>WiFi Settings</legend> <legend>WiFi Settings</legend>
<p> <!-- <p>
<input type="checkbox" id="enable" name="enable" value="true"> <input type="checkbox" id="enable" name="enable" value="true">
<label for="enable"> Enable WiFi</label><br> <label for="enable"> Enable WiFi</label><br>
</p> </p> -->
<p> <p>
<label for="ssid">SSID</label> <label for="ssid">SSID</label>

View File

@@ -42,6 +42,29 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<!--Sensor card-->
<div class="card">
<header>
<h4>Water information</h4>
</header>
<table class="tg">
<thead></thead>
<tbody>
<tr>
<td>Waterlevel: </td>
<td id="level">WAITING</td>
</tr>
<tr>
<td>Water volumen: </td>
<td id="liters">WAITING</td>
</tr>
<tr>
<td>Percentage: </td>
<td id="percentage">WAITING</td>
</tr>
</tbody>
</table>
</div>
</div> </div>
@@ -69,15 +92,11 @@
<tbody> <tbody>
<tr> <tr>
<td>Uptime: </td> <td>Uptime: </td>
<td>132d</td> <td id="uptime">XXX</td>
</tr> </tr>
<tr> <tr>
<td>FW version: </td> <td>Heap usage: </td>
<td>0.2</td> <td id="heap">XXX</td>
</tr>
<tr>
<td>Time/Date: </td>
<td>1.1.202022</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@@ -9,3 +9,14 @@
Config fields: Config fields:
- ssid - ssid
- wifi_password - 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"

View File

@@ -14,6 +14,7 @@
#include "INA226.h" #include "INA226.h"
#include "Wire.h" #include "Wire.h"
#include <Preferences.h> #include <Preferences.h>
#define LED_1 4 #define LED_1 4
@@ -26,14 +27,17 @@
// Define keys to prevent typos // Define keys to prevent typos
#define ssid_key "ssid" #define ssid_key "ssid"
#define wifi_password_key "wifi_password" #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(); extern "C" int rom_phy_get_vdd33();
// Calibration variables // Calibration variables
float zero_value = 0.03; // Measured shunt voltage with nothing connected, used to fix measuring offset 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_high = false;
bool voltage_low = false; bool voltage_low = false;
@@ -43,12 +47,21 @@ bool current_low = false;
uint8_t failed_connection_attempts = 0; uint8_t failed_connection_attempts = 0;
struct SensorData { struct SensorData {
int percentage; float bus_voltage;
float voltage; float shunt_voltage;
float current; float shunt_current;
float water_height;
}; };
struct WaterData{
// Water level in cm
float level;
// Water volume in liters
float liters;
// Percentage
float percentage;
};
struct NetworkData { struct NetworkData {
String ip_address; String ip_address;
bool link; bool link;
@@ -65,11 +78,18 @@ NetworkData wifi_data;
NetworkData ethernet_data; NetworkData ethernet_data;
DeviceTelemetry telemetry; DeviceTelemetry telemetry;
SensorData current_data = SensorData { -1, -1, -1, -1 }; SensorData shunt_data;
WaterData water_data;
int64_t mac_address = ESP.getEfuseMac(); int64_t mac_address = ESP.getEfuseMac();
//#define INA226
// #ifdef INA226
INA226 ina_sensor(0x40); INA226 ina_sensor(0x40);
// #else
// INA233 ina_sensor();
// #endif
Preferences prefs; Preferences prefs;
@@ -152,7 +172,7 @@ void display_task(void* parameter)
while (true) { while (true) {
if (!is_error()) { if (!is_error()) {
// We have no error, refresh status display and wait half a second // We have no error, refresh status display and wait half a second
display_percentage(current_data.percentage); display_percentage(water_data.percentage);
} else { } else {
Log.verbose("Error detected"); Log.verbose("Error detected");
// We have an error, display error code for 3 seconds and then water level for 3 seconds // 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); display_error_code(4);
} }
delay(3000); 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) void read_sensor_task(void* parameter)
{ {
while (true) { while (true) {
// Get Values from sensor
float bus_voltage = ina_sensor.getBusVoltage(); float bus_voltage = ina_sensor.getBusVoltage();
float shunt_voltage = ina_sensor.getShuntVoltage_mV() - zero_value; float shunt_voltage = ina_sensor.getShuntVoltage_mV() - zero_value;
float shunt_current = shunt_voltage / 4; float shunt_current = shunt_voltage / RESISTOR_VALUE;
float mA_per_cm = (20 - 4) / (sensor_range * 100); // 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 min_water_level_mA_over_zero = (min_water_level_cm * mA_per_cm); float mA_per_cm = (20. - 4.) / (sensor_range);
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 min_water_level_mA = 4 + min_water_level_mA_over_zero;
float max_water_level_mA = 4 + max_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; 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_low = shunt_current < 3.8;
current_high = shunt_current > 20.2; current_high = shunt_current > 20.2;
voltage_low = bus_voltage < 23; voltage_low = bus_voltage < 23;
voltage_high = bus_voltage > 25; voltage_high = bus_voltage > 25;
Log.verbose("Bus current: %F", bus_voltage);
Log.verbose("Shunt current: %F", shunt_current); Log.verbose("Shunt current: %F", shunt_current);
Log.verbose("Shunt voltage: %F", shunt_voltage); 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); delay(20000);
} }
@@ -344,12 +391,52 @@ void setup()
request->send(SPIFFS, "/settings.html", "text/html", false); // TODO add proper return templating 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) { server.on("/sensor_data", HTTP_GET, [](AsyncWebServerRequest* request) {
StaticJsonDocument<128> doc; StaticJsonDocument<128> doc;
doc["percentage"] = current_data.percentage; doc["bus_voltage"] = shunt_data.bus_voltage;
doc["voltage"] = current_data.voltage; doc["shunt_voltage"] = shunt_data.shunt_voltage;
doc["current"] = current_data.current; doc["current"] = shunt_data.shunt_current;
doc["water_height"] = current_data.water_height;
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; String output;
serializeJson(doc, output); serializeJson(doc, output);