Skip to content

Commit 07be145

Browse files
authored
Merge pull request #116 from SenaxInc/copilot/add-calibration-learning-system
Add calibration learning system for 4-20mA and voltage ratiometric sensors
2 parents 2a21c18 + c6f0a88 commit 07be145

File tree

3 files changed

+1645
-160
lines changed

3 files changed

+1645
-160
lines changed

TankAlarm-092025-Server-Hologram/TankAlarm-092025-Server-Hologram.ino

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,13 +1255,14 @@ void sendHttpResponse(EthernetClient &client, String path) {
12551255
} else if (path == "/emails") {
12561256
sendEmailManagementPage(client);
12571257
} else if (path == "/calibration") {
1258-
// Calibration page removed for simplification - send proper HTTP response
1258+
// Calibration learning system is available in the BluesOpta server version
12591259
client.println("HTTP/1.1 200 OK");
12601260
client.println("Content-Type: text/html");
12611261
client.println("Connection: close");
12621262
client.println();
1263-
client.println("<html><body><h1>Calibration Feature Removed</h1>");
1264-
client.println("<p>The calibration feature has been removed for simplification.</p>");
1263+
client.println("<html><body><h1>Calibration Learning System</h1>");
1264+
client.println("<p>The calibration learning system is available in the TankAlarm-112025-Server-BluesOpta version.</p>");
1265+
client.println("<p>This feature allows operators to enter manual tank level readings and automatically improves sensor accuracy over time using linear regression.</p>");
12651266
client.println("<p><a href='/'>Back to Dashboard</a></p></body></html>");
12661267
} else {
12671268
send404Page(client);

TankAlarm-112025-Client-BluesOpta/TankAlarm-112025-Client-BluesOpta.ino

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ struct ClientConfig {
283283

284284
struct TankRuntime {
285285
float currentInches;
286+
float currentSensorMa; // Raw sensor reading in milliamps (for 4-20mA sensors)
286287
float lastReportedInches;
287288
float lastDailySentInches;
288289
bool highAlarmLatched;
@@ -1556,13 +1557,17 @@ static float readTankSensor(uint8_t idx) {
15561557
// Use explicit bounds check for current loop channel
15571558
int16_t channel = (cfg.currentLoopChannel >= 0 && cfg.currentLoopChannel < 8) ? cfg.currentLoopChannel : 0;
15581559
if (cfg.maxValue < 0.1f) {
1560+
gTankState[idx].currentSensorMa = 0.0f;
15591561
return 0.0f;
15601562
}
15611563
float milliamps = readCurrentLoopMilliamps(channel);
15621564
if (milliamps < 0.0f) {
15631565
return gTankState[idx].currentInches; // keep previous on failure
15641566
}
15651567

1568+
// Store raw mA reading for telemetry
1569+
gTankState[idx].currentSensorMa = milliamps;
1570+
15661571
// Handle different 4-20mA sensor types
15671572
float levelInches;
15681573
if (cfg.currentLoopType == CURRENT_LOOP_ULTRASONIC) {
@@ -1850,11 +1855,14 @@ static void sendTelemetry(uint8_t idx, const char *reason, bool syncNow) {
18501855
bool activated = (state.currentInches > DIGITAL_SWITCH_THRESHOLD);
18511856
doc["activated"] = activated; // Boolean state: true = switch activated
18521857
doc["levelInches"] = state.currentInches; // 1.0 or 0.0
1853-
doc["percent"] = activated ? 100.0f : 0.0f; // 100% when activated, 0% when not
1858+
} else if (cfg.sensorType == SENSOR_CURRENT_LOOP) {
1859+
doc["sensorType"] = "currentLoop";
1860+
doc["maxValue"] = cfg.maxValue;
1861+
doc["levelInches"] = state.currentInches;
1862+
doc["sensorMa"] = state.currentSensorMa; // Raw 4-20mA reading
18541863
} else {
18551864
doc["maxValue"] = cfg.maxValue;
18561865
doc["levelInches"] = state.currentInches;
1857-
doc["percent"] = (cfg.maxValue > 0.1f) ? (state.currentInches / cfg.maxValue * 100.0f) : 0.0f;
18581866
}
18591867
doc["reason"] = reason;
18601868
doc["time"] = currentEpoch();
@@ -2147,7 +2155,10 @@ static bool appendDailyTank(DynamicJsonDocument &doc, JsonArray &array, uint8_t
21472155
t["label"] = cfg.name;
21482156
t["tank"] = cfg.tankNumber;
21492157
t["levelInches"] = state.currentInches;
2150-
t["percent"] = (cfg.maxValue > 0.1f) ? (state.currentInches / cfg.maxValue * 100.0f) : 0.0f;
2158+
// Include raw sensor mA for current loop sensors
2159+
if (cfg.sensorType == SENSOR_CURRENT_LOOP && state.currentSensorMa >= 4.0f) {
2160+
t["sensorMa"] = state.currentSensorMa;
2161+
}
21512162
t["high"] = cfg.highAlarmThreshold;
21522163
t["low"] = cfg.lowAlarmThreshold;
21532164

0 commit comments

Comments
 (0)