This commit is contained in:
27
data/gauge.js
Normal file
27
data/gauge.js
Normal file
File diff suppressed because one or more lines are too long
@@ -82,10 +82,59 @@ window.addEventListener('DOMContentLoaded', (event) => {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
fetchData(); // fetch immediately on page load
|
||||
setInterval(fetchData, 5000); // fetch every 5 seconds
|
||||
});
|
||||
|
||||
function roundToTwo(num) {
|
||||
return Math.round(num*100)/100;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('load', function () {
|
||||
var gauge = new RadialGauge({
|
||||
renderTo: 'main_gauge',
|
||||
width: 300,
|
||||
height: 300,
|
||||
units: "l",
|
||||
minValue: 0,
|
||||
maxValue: 220,
|
||||
majorTicks: [
|
||||
"0",
|
||||
"20",
|
||||
"40",
|
||||
"60",
|
||||
"80",
|
||||
"100",
|
||||
"120",
|
||||
"140",
|
||||
"160",
|
||||
"180",
|
||||
"200",
|
||||
"220"
|
||||
],
|
||||
minorTicks: 2,
|
||||
strokeTicks: true,
|
||||
highlights: [
|
||||
{
|
||||
"from": 160,
|
||||
"to": 220,
|
||||
"color": "rgba(200, 50, 50, .75)"
|
||||
}
|
||||
],
|
||||
colorPlate: "#fff",
|
||||
borderShadowWidth: 0,
|
||||
borders: false,
|
||||
needleType: "arrow",
|
||||
needleWidth: 2,
|
||||
needleCircleSize: 7,
|
||||
needleCircleOuter: true,
|
||||
needleCircleInner: false,
|
||||
animationDuration: 1500,
|
||||
animationRule: "linear"
|
||||
}).draw();
|
||||
})
|
||||
|
||||
|
||||
// document.body.appendChild(gauge.options.renderTo);
|
||||
@@ -25,22 +25,22 @@
|
||||
<legend>Settings</legend>
|
||||
<p>
|
||||
<label for="range">Sensor Range in cm</label>
|
||||
<input id="range" name="range" type="number" placeholder="200">
|
||||
<input id="range" name="sensor_range" type="number" placeholder="200" value="%sensor_range%">
|
||||
</p>
|
||||
<p>
|
||||
<label for="level_max">Water max height in cm</label>
|
||||
<input id="level_max" name="level_max" type="number">
|
||||
<input id="level_max" name="water_level_max" type="number" value="%water_level_min%">
|
||||
</p>
|
||||
<p>
|
||||
<label for="level_min">Water min height in cm</label>
|
||||
<input id="level_min" name="level_min" type="number">
|
||||
<input id="level_min" name="water_level_min" type="number" value="%water_level_max%">
|
||||
</p>
|
||||
<p>
|
||||
<label for="liters">Volume in liters</label>
|
||||
<input id="liters" name="liters" type="number">
|
||||
<input id="liters" name="water_volume" type="number" value="%water_volume%">
|
||||
</p>
|
||||
<p>
|
||||
<button class="button primary" style="width: 100%;">Submit</button>
|
||||
<button class="button primary" style="width: 100%%;">Submit</button>
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
@@ -55,15 +55,15 @@
|
||||
|
||||
<p>
|
||||
<label for="ssid">SSID</label>
|
||||
<input id="ssid" name="ssid" type="text">
|
||||
<input id="ssid" name="ssid" type="text" value="%sensor_range%">
|
||||
</p>
|
||||
<p>
|
||||
<label for="wifi_password">Password</label>
|
||||
<input id="wifi_password" name="wifi_password" type="password">
|
||||
<input id="wifi_password" name="wifi_password" type="password" value="%sensor_range%">
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<button class="button primary" style="width: 100%;">Submit</button>
|
||||
<button class="button primary" style="width: 100%%;">Submit</button>
|
||||
</p>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="/chota.css">
|
||||
|
||||
<script src="/gauge.js"></script>
|
||||
<script src="/logic.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -70,13 +73,7 @@
|
||||
|
||||
<div class="col-12 col-6-lg">
|
||||
|
||||
<div class="outer-wrapper">
|
||||
<div class="column-wrapper">
|
||||
<div class="column"></div>
|
||||
</div>
|
||||
<div class="percentage">25%</div>
|
||||
<div class="value">2500 / 10000</div>
|
||||
</div>
|
||||
<canvas data-type="radial-gauge" id="main_gauge"></canvas>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
18
dev/Waterlevel/Update Sensor Settings.bru
Normal file
18
dev/Waterlevel/Update Sensor Settings.bru
Normal file
@@ -0,0 +1,18 @@
|
||||
meta {
|
||||
name: Update Sensor Settings
|
||||
type: http
|
||||
seq: 2
|
||||
}
|
||||
|
||||
post {
|
||||
url: http://192.168.5.181/update_sensor_settings
|
||||
body: multipartForm
|
||||
auth: none
|
||||
}
|
||||
|
||||
body:multipart-form {
|
||||
sensor_range: 200
|
||||
water_level_max: 190
|
||||
water_level_min: 10
|
||||
water_volume: 1000
|
||||
}
|
||||
9
dev/Waterlevel/bruno.json
Normal file
9
dev/Waterlevel/bruno.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"version": "1",
|
||||
"name": "Waterlevel",
|
||||
"type": "collection",
|
||||
"ignore": [
|
||||
"node_modules",
|
||||
".git"
|
||||
]
|
||||
}
|
||||
9
src/global_data/defines.h
Normal file
9
src/global_data/defines.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Define keys to prevent typos
|
||||
#define ssid_key "ssid"
|
||||
#define wifi_password_key "wifi_password"
|
||||
#define level_sensor_range_key "sensor_range"
|
||||
#define water_level_min_key "water_level_min"
|
||||
#define water_level_max_key "water_level_max"
|
||||
#define water_volume_key "water_volume"
|
||||
|
||||
#define RESISTOR_VALUE 4
|
||||
10
src/global_data/global_data.cpp
Normal file
10
src/global_data/global_data.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "global_data.h"
|
||||
|
||||
NetworkData wifi_data;
|
||||
NetworkData ethernet_data;
|
||||
DeviceTelemetry telemetry;
|
||||
|
||||
SensorData shunt_data;
|
||||
WaterData water_data;
|
||||
|
||||
ActiveErrors active_errors = { false, false, false, false, false, false };
|
||||
38
src/global_data/global_data.h
Normal file
38
src/global_data/global_data.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
struct SensorData {
|
||||
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;
|
||||
float rssi;
|
||||
String network_name;
|
||||
};
|
||||
|
||||
struct DeviceTelemetry {
|
||||
float heap_used_percent;
|
||||
int uptime_seconds;
|
||||
};
|
||||
|
||||
struct ActiveErrors {
|
||||
bool voltage_low;
|
||||
bool voltage_high;
|
||||
bool current_low;
|
||||
bool current_high;
|
||||
bool level_low;
|
||||
bool level_high;
|
||||
};
|
||||
274
src/main.cpp
274
src/main.cpp
@@ -12,11 +12,16 @@
|
||||
#include <ArduinoOTA.h>
|
||||
|
||||
#include "INA226.h"
|
||||
#include "Wire.h"
|
||||
#include "INA233.h"
|
||||
|
||||
#include "global_data/defines.h"
|
||||
|
||||
#include "networking/networking.h"
|
||||
|
||||
|
||||
#include <Preferences.h>
|
||||
#include "global_data/global_data.h"
|
||||
#include "sensor/sensor.h"
|
||||
|
||||
#define LED_1 4
|
||||
#define LED_2 2
|
||||
@@ -25,73 +30,17 @@
|
||||
#define LED_5 12
|
||||
#define LED_RED 14
|
||||
|
||||
// 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
|
||||
|
||||
bool voltage_high = false;
|
||||
bool voltage_low = false;
|
||||
bool current_high = false;
|
||||
bool current_low = false;
|
||||
extern NetworkData wifi_data;
|
||||
extern NetworkData ethernet_data;
|
||||
extern DeviceTelemetry telemetry;
|
||||
|
||||
uint8_t failed_connection_attempts = 0;
|
||||
extern SensorData shunt_data;
|
||||
extern WaterData water_data;
|
||||
|
||||
struct SensorData {
|
||||
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;
|
||||
float rssi;
|
||||
String network_name;
|
||||
};
|
||||
|
||||
struct DeviceTelemetry {
|
||||
float heap_used_percent;
|
||||
int uptime_seconds;
|
||||
};
|
||||
|
||||
NetworkData wifi_data;
|
||||
NetworkData ethernet_data;
|
||||
DeviceTelemetry telemetry;
|
||||
|
||||
SensorData shunt_data;
|
||||
WaterData water_data;
|
||||
|
||||
int64_t mac_address = ESP.getEfuseMac();
|
||||
|
||||
|
||||
//#define USE_INA226
|
||||
|
||||
#ifdef USE_INA226
|
||||
INA226 ina_sensor(0x40);
|
||||
#else
|
||||
INA233 ina_sensor(0x40);
|
||||
#endif
|
||||
extern ActiveErrors active_errors;
|
||||
|
||||
Preferences prefs;
|
||||
|
||||
@@ -159,7 +108,7 @@ void display_error_code(byte err_code)
|
||||
|
||||
bool is_error()
|
||||
{
|
||||
return voltage_high || voltage_low || current_high || current_low;
|
||||
return active_errors.voltage_high || active_errors.voltage_low || active_errors.current_high || active_errors.current_low;
|
||||
}
|
||||
|
||||
void printSuffix(Print* _logOutput, int logLevel)
|
||||
@@ -186,16 +135,16 @@ void display_task(void* parameter)
|
||||
Log.verbose("Error detected");
|
||||
|
||||
// We have an error, display error code for 3 seconds and then water level for 3 seconds
|
||||
if (voltage_low) {
|
||||
if (active_errors.voltage_low) {
|
||||
display_error_code(1);
|
||||
delay(3000);
|
||||
} else if (voltage_high) {
|
||||
} else if (active_errors.voltage_high) {
|
||||
display_error_code(2);
|
||||
delay(3000);
|
||||
} else if (current_low) {
|
||||
} else if (active_errors.current_low) {
|
||||
display_error_code(3);
|
||||
delay(3000);
|
||||
} else if (current_high) {
|
||||
} else if (active_errors.current_high) {
|
||||
display_error_code(4);
|
||||
delay(3000);
|
||||
} else {
|
||||
@@ -206,63 +155,6 @@ void display_task(void* parameter)
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_task(void* parameter)
|
||||
{
|
||||
Log.verbose("Starting WiFi Task");
|
||||
while (true) {
|
||||
if (prefs.getString(ssid_key, "") == "" || failed_connection_attempts > 5) {
|
||||
wifi_data.link = false;
|
||||
if (failed_connection_attempts > 5) {
|
||||
Log.verbose("Failed to connecto to currently saved SSID, starting SoftAP");
|
||||
} else {
|
||||
Log.verbose("No SSID saved, starting SoftAP");
|
||||
}
|
||||
|
||||
String ap_ssid = "Watermeter-" + String(mac_address);
|
||||
WiFi.softAP(ap_ssid, "");
|
||||
|
||||
Log.verbose("[WIFI_TASK] Waiting for SSID now...");
|
||||
|
||||
String old_ssid = prefs.getString(ssid_key, "xxx");
|
||||
while (prefs.getString(ssid_key, "") == "" || prefs.getString(ssid_key, "") == old_ssid) {
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
failed_connection_attempts = 0;
|
||||
} else {
|
||||
if (WiFi.isConnected() && WiFi.SSID() == prefs.getString(ssid_key, "")) {
|
||||
failed_connection_attempts = 0;
|
||||
wifi_data.rssi = WiFi.RSSI();
|
||||
wifi_data.link = true;
|
||||
wifi_data.network_name = WiFi.SSID();
|
||||
wifi_data.ip_address = WiFi.localIP().toString();
|
||||
|
||||
Log.verbose("RSSI: %F, IP Address, %p, SSID: %s", float(WiFi.RSSI()), WiFi.localIP(), prefs.getString(ssid_key, "NOSSID"));
|
||||
delay(5000);
|
||||
} else {
|
||||
Log.verbose("Connecting to %s using password %s", prefs.getString(ssid_key, ""), prefs.getString(wifi_password_key, ""));
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(prefs.getString(ssid_key, ""), prefs.getString(wifi_password_key, ""));
|
||||
failed_connection_attempts++;
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ethernet_task(void* parameter)
|
||||
{
|
||||
Log.verbose("Connecting Ethernet");
|
||||
ETH.begin(0, 17, 23, 18);
|
||||
ETH.setHostname("watermeter");
|
||||
while (true) {
|
||||
ethernet_data.link = ETH.linkUp();
|
||||
ethernet_data.rssi = ETH.linkSpeed();
|
||||
ethernet_data.ip_address = ETH.localIP().toString();
|
||||
delay(60 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
void collect_internal_telemetry_task(void* parameter)
|
||||
{
|
||||
while (true) {
|
||||
@@ -275,70 +167,24 @@ void collect_internal_telemetry_task(void* parameter)
|
||||
}
|
||||
}
|
||||
|
||||
void read_sensor_task(void* parameter)
|
||||
|
||||
|
||||
String processor(const String& var)
|
||||
{
|
||||
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 / 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);
|
||||
|
||||
// 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;
|
||||
|
||||
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;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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("Shunt current: %F", shunt_current);
|
||||
Log.verbose("Shunt voltage: %F", shunt_voltage);
|
||||
Log.verbose("Bus voltage: %F", bus_voltage);
|
||||
Log.verbose("cm_over_zero: %F", cm_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);
|
||||
}
|
||||
if (var == level_sensor_range_key) {
|
||||
return String(prefs.getFloat(level_sensor_range_key, -1));
|
||||
} else if (var == water_level_min_key) {
|
||||
return String(prefs.getFloat(water_level_min_key, -1));
|
||||
} else if (var == water_level_max_key) {
|
||||
return String(prefs.getFloat(water_level_max_key, -1));
|
||||
} else if (var == water_volume_key) {
|
||||
return String(prefs.getFloat(water_volume_key, -1));
|
||||
}
|
||||
|
||||
return String("Test");
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
prefs.begin("waterlevel", false);
|
||||
@@ -358,6 +204,7 @@ void setup()
|
||||
display_error_code(31);
|
||||
delay(500);
|
||||
display_error_code(17);
|
||||
init_sensor();
|
||||
|
||||
Log.verbose("Beginning SPIFFS");
|
||||
SPIFFS.begin(true);
|
||||
@@ -365,26 +212,15 @@ void setup()
|
||||
display_error_code(19);
|
||||
|
||||
Log.verbose("Begin INA");
|
||||
ina_sensor.begin(33, 32);
|
||||
display_error_code(20);
|
||||
#ifdef USE_INA226
|
||||
ina_sensor.setMaxCurrentShunt(0.02, 4, false);
|
||||
ina_sensor.setBusVoltageConversionTime(7);
|
||||
ina_sensor.setShuntVoltageConversionTime(7);
|
||||
ina_sensor.setAverage(4);
|
||||
#else
|
||||
ina_sensor.setShuntVoltageConversionTime(conversion_time_8244uS);
|
||||
ina_sensor.setBusVoltageConversionTime(conversion_time_8244uS);
|
||||
ina_sensor.setAveragingMode(averages_128);
|
||||
#endif
|
||||
|
||||
|
||||
display_error_code(22);
|
||||
|
||||
/////////////////////////////// ROUTES ///////////////////////////////
|
||||
Log.verbose("Route Setup");
|
||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/status.html", "text/html", false); });
|
||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/status.html", "text/html", false, processor); });
|
||||
|
||||
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/settings.html", "text/html", false); });
|
||||
server.on("/settings", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/settings.html", "text/html", false, processor); });
|
||||
|
||||
server.on("/export", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/data_export.html", "text/html", false); });
|
||||
|
||||
@@ -393,13 +229,15 @@ void setup()
|
||||
server.on("/update_wifi_credentials", HTTP_POST, [](AsyncWebServerRequest* request) {
|
||||
int params = request->params();
|
||||
|
||||
// For settings SSID
|
||||
if (request->hasParam(ssid_key, true) && request->hasParam(wifi_password_key, true)) {
|
||||
Log.verbose("Updating SSID config");
|
||||
AsyncWebParameter* ssid_param = request->getParam(ssid_key, true);
|
||||
AsyncWebParameter* password_param = request->getParam(wifi_password_key, true);
|
||||
prefs.putString(ssid_key, ssid_param->value().c_str());
|
||||
prefs.putString(wifi_password_key, password_param->value().c_str());
|
||||
} else {
|
||||
|
||||
}else {
|
||||
for (int i = 0; i < params; i++) {
|
||||
AsyncWebParameter* p = request->getParam(i);
|
||||
if (p->isFile()) { // p->isPost() is also true
|
||||
@@ -418,17 +256,37 @@ void setup()
|
||||
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)) {
|
||||
if (request->hasParam(level_sensor_range_key, true) && request->hasParam(water_level_min_key, true) && request->hasParam(water_level_max_key, true) && request->hasParam(water_volume_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);
|
||||
AsyncWebParameter* liters_param = request->getParam(water_volume_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());
|
||||
String range_str = range_param->value();
|
||||
String level_min_str = level_min_param->value();
|
||||
String level_max_str = level_max_param->value();
|
||||
String liters_str = liters_param->value();
|
||||
|
||||
float range_float = range_str.toFloat();
|
||||
float level_min_float = level_min_str.toFloat();
|
||||
float level_max_float = level_max_str.toFloat();
|
||||
float liters_float = liters_str.toFloat();
|
||||
|
||||
const char* paramCStr = range_str.c_str();
|
||||
char* endPtr;
|
||||
|
||||
// Convert the C string to a float using strtod
|
||||
float value = strtod(paramCStr, &endPtr);
|
||||
|
||||
Log.verbose("range_float:%D:", range_float);
|
||||
|
||||
prefs.putFloat(level_sensor_range_key, range_float);
|
||||
prefs.putFloat(water_level_min_key, level_min_float);
|
||||
prefs.putFloat(water_level_max_key, level_max_float);
|
||||
prefs.putFloat(water_volume_key, liters_float);
|
||||
|
||||
Log.verbose("range_float_after:%D:", prefs.getFloat(level_sensor_range_key, -1.0));
|
||||
} else {
|
||||
Log.verbose("!!!! FAIL lo");
|
||||
for (int i = 0; i < params; i++) {
|
||||
@@ -492,6 +350,8 @@ void setup()
|
||||
});
|
||||
|
||||
server.on("/chota.css", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/chota.css", "text/css", false); });
|
||||
server.on("/gauge.js", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/gauge.js", "application/javascript", false); });
|
||||
|
||||
|
||||
display_error_code(23);
|
||||
|
||||
|
||||
70
src/networking/networking.cpp
Normal file
70
src/networking/networking.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <ArduinoLog.h>
|
||||
#include <ETH.h>
|
||||
#include <WiFi.h>
|
||||
#include "../global_data/defines.h"
|
||||
#include "../global_data/global_data.h"
|
||||
#include <Preferences.h>
|
||||
|
||||
int64_t mac_address = ESP.getEfuseMac();
|
||||
uint8_t failed_connection_attempts = 0;
|
||||
|
||||
extern NetworkData wifi_data;
|
||||
extern NetworkData ethernet_data;
|
||||
extern Preferences prefs;
|
||||
|
||||
void wifi_task(void* parameter)
|
||||
{
|
||||
Log.verbose("Starting WiFi Task");
|
||||
while (true) {
|
||||
if (prefs.getString(ssid_key, "") == "" || failed_connection_attempts > 5) {
|
||||
wifi_data.link = false;
|
||||
if (failed_connection_attempts > 5) {
|
||||
Log.verbose("Failed to connecto to currently saved SSID, starting SoftAP");
|
||||
} else {
|
||||
Log.verbose("No SSID saved, starting SoftAP");
|
||||
}
|
||||
|
||||
String ap_ssid = "Watermeter-" + String(mac_address);
|
||||
WiFi.softAP(ap_ssid, "");
|
||||
|
||||
Log.verbose("[WIFI_TASK] Waiting for SSID now...");
|
||||
|
||||
String old_ssid = prefs.getString(ssid_key, "xxx");
|
||||
while (prefs.getString(ssid_key, "") == "" || prefs.getString(ssid_key, "") == old_ssid) {
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
failed_connection_attempts = 0;
|
||||
} else {
|
||||
if (WiFi.isConnected() && WiFi.SSID() == prefs.getString(ssid_key, "")) {
|
||||
failed_connection_attempts = 0;
|
||||
wifi_data.rssi = WiFi.RSSI();
|
||||
wifi_data.link = true;
|
||||
wifi_data.network_name = WiFi.SSID();
|
||||
wifi_data.ip_address = WiFi.localIP().toString();
|
||||
|
||||
Log.verbose("RSSI: %F, IP Address, %p, SSID: %s", float(WiFi.RSSI()), WiFi.localIP(), prefs.getString(ssid_key, "NOSSID"));
|
||||
delay(5000);
|
||||
} else {
|
||||
Log.verbose("Connecting to %s using password %s", prefs.getString(ssid_key, ""), prefs.getString(wifi_password_key, ""));
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(prefs.getString(ssid_key, ""), prefs.getString(wifi_password_key, ""));
|
||||
failed_connection_attempts++;
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ethernet_task(void* parameter)
|
||||
{
|
||||
Log.verbose("Connecting Ethernet");
|
||||
ETH.begin(0, 17, 23, 18);
|
||||
ETH.setHostname("watermeter");
|
||||
while (true) {
|
||||
ethernet_data.link = ETH.linkUp();
|
||||
ethernet_data.rssi = ETH.linkSpeed();
|
||||
ethernet_data.ip_address = ETH.localIP().toString();
|
||||
delay(60 * 1000);
|
||||
}
|
||||
}
|
||||
2
src/networking/networking.h
Normal file
2
src/networking/networking.h
Normal file
@@ -0,0 +1,2 @@
|
||||
void wifi_task(void*);
|
||||
void ethernet_task(void*);
|
||||
99
src/sensor/sensor.cpp
Normal file
99
src/sensor/sensor.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "../global_data/defines.h"
|
||||
#include <INA233.h>
|
||||
#include <Preferences.h>
|
||||
#include <ArduinoLog.h>
|
||||
#include <global_data/global_data.h>
|
||||
#include "Wire.h"
|
||||
|
||||
|
||||
#ifdef USE_INA226s
|
||||
INA226 ina_sensor(0x40);
|
||||
#else
|
||||
INA233 ina_sensor(0x40);
|
||||
#endif
|
||||
|
||||
extern Preferences prefs;
|
||||
extern WaterData water_data;
|
||||
extern ActiveErrors active_errors;
|
||||
extern SensorData shunt_data;
|
||||
|
||||
// Calibration variables
|
||||
float zero_value = 0.03; // Measured shunt voltage with nothing connected, used to fix measuring offset
|
||||
|
||||
void init_sensor(){
|
||||
ina_sensor.begin(33, 32);
|
||||
#ifdef USE_INA226
|
||||
ina_sensor.setMaxCurrentShunt(0.02, 4, false);
|
||||
ina_sensor.setBusVoltageConversionTime(7);
|
||||
ina_sensor.setShuntVoltageConversionTime(7);
|
||||
ina_sensor.setAverage(4);
|
||||
#else
|
||||
ina_sensor.setShuntVoltageConversionTime(conversion_time_8244uS);
|
||||
ina_sensor.setBusVoltageConversionTime(conversion_time_8244uS);
|
||||
ina_sensor.setAveragingMode(averages_128);
|
||||
#endif
|
||||
}
|
||||
|
||||
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 / 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(water_volume_key, 10000.);
|
||||
|
||||
float mA_per_cm = (20. - 4.) / (sensor_range);
|
||||
|
||||
// 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;
|
||||
|
||||
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;
|
||||
|
||||
// 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);
|
||||
|
||||
// Tank volume in liters
|
||||
float liters_raw = max_liters * percentage_raw;
|
||||
int liters = round(liters_raw);
|
||||
|
||||
active_errors.current_low = shunt_current < 3.8;
|
||||
active_errors.current_high = shunt_current > 20.2;
|
||||
active_errors.voltage_low = bus_voltage < 23;
|
||||
active_errors.voltage_high = bus_voltage > 25;
|
||||
Log.verbose("Shunt current: %F", shunt_current);
|
||||
Log.verbose("Shunt voltage: %F", shunt_voltage);
|
||||
Log.verbose("Bus voltage: %F", bus_voltage);
|
||||
Log.verbose("cm_over_zero: %F", cm_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);
|
||||
}
|
||||
}
|
||||
2
src/sensor/sensor.h
Normal file
2
src/sensor/sensor.h
Normal file
@@ -0,0 +1,2 @@
|
||||
void read_sensor_task(void*);
|
||||
void init_sensor();
|
||||
Reference in New Issue
Block a user