Skip to content

Commit 2be8161

Browse files
committed
incremental updates
1 parent 75ab52d commit 2be8161

File tree

1 file changed

+116
-82
lines changed

1 file changed

+116
-82
lines changed

still3.ino

Lines changed: 116 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
* - Time-based pump control for better low-end performance.
1212
* - Web UI to set target temperature, PID tunings, and pump mode (Off/Auto/Manual).
1313
* - Web server runs in a dedicated FreeRTOS task for improved responsiveness.
14+
* - Efficient web updates: full history on load, single-point updates thereafter.
1415
* - Reads from DS18B20 temperature sensors and an HX711 pressure sensor.
1516
* - Compensates for known pressure sensor drift.
1617
* - Stores sensor data in memory.
@@ -132,6 +133,7 @@ void handlePumpModeControl();
132133
void handleGetPumpMode();
133134
void handleManualPumpControl();
134135
void handleDataJson();
136+
void handleDataUpdate();
135137
void handleDownloadCsv();
136138
void handleNotFound();
137139
String getSensorAddressString(DeviceAddress deviceAddress);
@@ -426,6 +428,7 @@ void setupWebServer() {
426428
server.on("/pump/mode/get", HTTP_GET, handleGetPumpMode);
427429
server.on("/pump/manual", HTTP_POST, handleManualPumpControl);
428430
server.on("/data.json", HTTP_GET, handleDataJson);
431+
server.on("/data/update", HTTP_GET, handleDataUpdate);
429432
server.on("/download.csv", HTTP_GET, handleDownloadCsv);
430433
server.onNotFound(handleNotFound);
431434

@@ -546,93 +549,106 @@ void handleRoot() {
546549
</div>
547550
<script>
548551
let myChart; // Variable to hold the chart instance
552+
const MAX_CHART_POINTS = 3000;
549553
550-
const fetchData = () => {
551-
return fetch('/data.json').then(response => response.json());
554+
const initialChartLoad = () => {
555+
fetch('/data.json')
556+
.then(response => response.json())
557+
.then(data => createChart(data))
558+
.catch(error => console.error('Initial chart load error:', error));
552559
};
553560
554-
const createOrUpdateChart = () => {
555-
fetchData().then(data => {
556-
const ctx = document.getElementById('tempChart').getContext('2d');
557-
558-
const labels = data.map(d => {
559-
const date = new Date(d.time * 1000);
560-
return date.toLocaleTimeString();
561-
});
561+
const updateChart = () => {
562+
fetch('/data/update')
563+
.then(response => response.json())
564+
.then(point => {
565+
if (!myChart || !point.time) return; // Don't update if chart not ready or no new data
566+
567+
const newLabel = new Date(point.time * 1000).toLocaleTimeString();
568+
myChart.data.labels.push(newLabel);
569+
myChart.data.datasets[0].data.push(point.temp1);
570+
myChart.data.datasets[1].data.push(point.temp2);
571+
myChart.data.datasets[2].data.push(point.pumpPower);
572+
myChart.data.datasets[3].data.push(point.pressure);
573+
574+
// Remove oldest data point if we're over the max
575+
if (myChart.data.labels.length > MAX_CHART_POINTS) {
576+
myChart.data.labels.shift();
577+
myChart.data.datasets.forEach((dataset) => {
578+
dataset.data.shift();
579+
});
580+
}
562581
563-
if (myChart) {
564-
// If chart exists, update data and redraw
565-
myChart.data.labels = labels;
566-
myChart.data.datasets[0].data = data.map(d => d.temp1);
567-
myChart.data.datasets[1].data = data.map(d => d.temp2);
568-
myChart.data.datasets[2].data = data.map(d => d.pumpPower);
569-
myChart.data.datasets[3].data = data.map(d => d.pressure);
570-
myChart.update();
571-
} else {
572-
// If chart doesn't exist, create it
573-
myChart = new Chart(ctx, {
574-
type: 'line',
575-
data: {
576-
labels: labels,
577-
datasets: [{
578-
label: 'Sensor 1 (°C)',
579-
data: data.map(d => d.temp1),
580-
borderColor: 'rgba(255, 99, 132, 1)',
581-
yAxisID: 'y-temp',
582-
fill: false
583-
}, {
584-
label: 'Sensor 2 (°C)',
585-
data: data.map(d => d.temp2),
586-
borderColor: 'rgba(54, 162, 235, 1)',
587-
yAxisID: 'y-temp',
588-
fill: false
589-
}, {
590-
label: 'Pump Power (%)',
591-
data: data.map(d => d.pumpPower),
592-
borderColor: 'rgba(75, 192, 192, 1)',
593-
backgroundColor: 'rgba(75, 192, 192, 0.2)',
594-
yAxisID: 'y-power',
595-
fill: true
596-
}, {
597-
label: 'Pressure',
598-
data: data.map(d => d.pressure),
599-
borderColor: 'rgba(255, 159, 64, 1)',
600-
yAxisID: 'y-pressure',
601-
fill: false
602-
}]
582+
myChart.update();
583+
})
584+
.catch(error => console.error('Chart update error:', error));
585+
};
586+
587+
const createChart = (data) => {
588+
const ctx = document.getElementById('tempChart').getContext('2d');
589+
const labels = data.map(d => new Date(d.time * 1000).toLocaleTimeString());
590+
591+
myChart = new Chart(ctx, {
592+
type: 'line',
593+
data: {
594+
labels: labels,
595+
datasets: [{
596+
label: 'Sensor 1 (°C)',
597+
data: data.map(d => d.temp1),
598+
borderColor: 'rgba(255, 99, 132, 1)',
599+
yAxisID: 'y-temp',
600+
fill: false
601+
}, {
602+
label: 'Sensor 2 (°C)',
603+
data: data.map(d => d.temp2),
604+
borderColor: 'rgba(54, 162, 235, 1)',
605+
yAxisID: 'y-temp',
606+
fill: false
607+
}, {
608+
label: 'Pump Power (%)',
609+
data: data.map(d => d.pumpPower),
610+
borderColor: 'rgba(75, 192, 192, 1)',
611+
backgroundColor: 'rgba(75, 192, 192, 0.2)',
612+
yAxisID: 'y-power',
613+
fill: true
614+
}, {
615+
label: 'Pressure',
616+
data: data.map(d => d.pressure),
617+
borderColor: 'rgba(255, 159, 64, 1)',
618+
yAxisID: 'y-pressure',
619+
fill: false
620+
}]
621+
},
622+
options: {
623+
responsive: true,
624+
maintainAspectRatio: false,
625+
scales: {
626+
x: { display: true, title: { display: true, text: 'Time' } },
627+
'y-temp': {
628+
type: 'linear',
629+
display: true,
630+
position: 'left',
631+
title: { display: true, text: 'Temperature (°C)' }
603632
},
604-
options: {
605-
responsive: true,
606-
maintainAspectRatio: false,
607-
scales: {
608-
x: { display: true, title: { display: true, text: 'Time' } },
609-
'y-temp': {
610-
type: 'linear',
611-
display: true,
612-
position: 'left',
613-
title: { display: true, text: 'Temperature (°C)' }
614-
},
615-
'y-power': {
616-
type: 'linear',
617-
display: true,
618-
position: 'right',
619-
min: 0,
620-
max: 100,
621-
title: { display: true, text: 'Pump Power (%)' },
622-
grid: { drawOnChartArea: false }
623-
},
624-
'y-pressure': {
625-
type: 'linear',
626-
display: true,
627-
position: 'right',
628-
title: { display: true, text: 'Pressure' },
629-
grid: { drawOnChartArea: false }
630-
}
631-
}
633+
'y-power': {
634+
type: 'linear',
635+
display: true,
636+
position: 'right',
637+
min: 0,
638+
max: 100,
639+
title: { display: true, text: 'Pump Power (%)' },
640+
grid: { drawOnChartArea: false }
641+
},
642+
'y-pressure': {
643+
type: 'linear',
644+
display: true,
645+
position: 'right',
646+
title: { display: true, text: 'Pressure' },
647+
grid: { drawOnChartArea: false }
632648
}
633-
});
649+
}
634650
}
635-
}).catch(error => console.error('Chart update error:', error));
651+
});
636652
};
637653
638654
// --- Control Logic ---
@@ -711,8 +727,8 @@ void handleRoot() {
711727
fetchAndUpdatePidInputs();
712728
fetchAndUpdatePumpMode();
713729
setpointInput.value = 78.2; // Set default temp target on page load
714-
createOrUpdateChart();
715-
setInterval(createOrUpdateChart, 5000);
730+
initialChartLoad();
731+
setInterval(updateChart, 5000);
716732
});
717733
</script>
718734
</body>
@@ -846,6 +862,24 @@ void handleDataJson() {
846862
server.sendContent(""); // End of stream
847863
}
848864

865+
/**
866+
* @brief Serves the latest data point as a JSON object.
867+
*/
868+
void handleDataUpdate() {
869+
if (readingCount > 0) {
870+
String json_item = "{";
871+
json_item += "\"time\":" + String(data[readingCount - 1].time);
872+
json_item += ",\"temp1\":" + String(data[readingCount - 1].temp1);
873+
json_item += ",\"temp2\":" + String(data[readingCount - 1].temp2);
874+
json_item += ",\"pumpPower\":" + String(data[readingCount - 1].pumpPower);
875+
json_item += ",\"pressure\":" + String(data[readingCount - 1].pressure);
876+
json_item += "}";
877+
server.send(200, "application/json", json_item);
878+
} else {
879+
server.send(200, "application/json", "{}"); // Send empty object if no data yet
880+
}
881+
}
882+
849883
/**
850884
* @brief Handles the request to download data as a CSV file by streaming it.
851885
*/

0 commit comments

Comments
 (0)