Add support for multiple sensors and credit popup
This commit is contained in:
parent
1925493a7e
commit
e9be1cd43e
11
README.md
11
README.md
|
@ -1,3 +1,12 @@
|
||||||
# therminator
|
# therminator
|
||||||
|
|
||||||
ESP8266 + MAX31855 thermocouple thermometer with web interface
|
### a modular ESP8266/ESP32 + MAX31855 based logging thermometer
|
||||||
|
|
||||||
|
therminator is a logging thermometer, based on the ESP8266/ESP32 microcontrollers and the MAX31855 thermocouple to digital converter.
|
||||||
|
|
||||||
|
### features:
|
||||||
|
|
||||||
|
- support for up to 6 (ESP8266) or 8 (ESP32) sensors
|
||||||
|
- live temperature charts
|
||||||
|
- data recording capabilities for writing logged data to CSV files
|
||||||
|
- timed recording (recording stops after specified time passes)
|
BIN
data/favicon.ico
Normal file
BIN
data/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
|
@ -4,10 +4,30 @@
|
||||||
<head>
|
<head>
|
||||||
<title>therminator</title>
|
<title>therminator</title>
|
||||||
<link rel="stylesheet" type="text/css" href="/style.css" />
|
<link rel="stylesheet" type="text/css" href="/style.css" />
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
<h1>/* therminator */</h1>
|
<div id="lightbox">
|
||||||
|
<div id="credits">
|
||||||
|
<span id="closebtn" onclick="hideCredits()">[X]</span>
|
||||||
|
<img src="favicon.ico" />
|
||||||
|
<h1>/* therminator */</h1>
|
||||||
|
<h3>a modular ESP8266/ESP32+MAX31855 logging thermometer</h3>
|
||||||
|
<br />
|
||||||
|
<p>
|
||||||
|
licensed under the MIT license copyright (c) 2023
|
||||||
|
<a href="https://huskee.gay">huskee</a>
|
||||||
|
</p>
|
||||||
|
<br />
|
||||||
|
<p>
|
||||||
|
huge thanks to azisi from
|
||||||
|
<a href="https://hackerspace.gr">hackerspace.gr</a> for the idea ❤️
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 style="user-select: none" onclick="showCredits()">/* therminator */</h1>
|
||||||
<p>last sensor update: <span id="time"></span></p>
|
<p>last sensor update: <span id="time"></span></p>
|
||||||
<div id="du">
|
<div id="du">
|
||||||
<p>current data update interval (ms): <span id="updInt"></span></p>
|
<p>current data update interval (ms): <span id="updInt"></span></p>
|
||||||
|
@ -47,7 +67,7 @@
|
||||||
Sorry, your browser does not support inline SVG.
|
Sorry, your browser does not support inline SVG.
|
||||||
</svg>
|
</svg>
|
||||||
<p>Recording CSV data to <span id="filename"></span></p></span
|
<p>Recording CSV data to <span id="filename"></span></p></span
|
||||||
><span id="timeLeft"></span>
|
><span id="timeLeft">Time left: <span id="timeLeftCtr"></span></span>
|
||||||
</div>
|
</div>
|
||||||
<div id="timedCheck">
|
<div id="timedCheck">
|
||||||
<input type="checkbox" id="timedRec" /><label for="timedRec"
|
<input type="checkbox" id="timedRec" /><label for="timedRec"
|
||||||
|
@ -73,6 +93,48 @@
|
||||||
<canvas id="chartB"></canvas>
|
<canvas id="chartB"></canvas>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="chart-container">
|
||||||
|
<h2>Channel C <span id="error-tempC"></span></h2>
|
||||||
|
<label for="labelC">label: </label
|
||||||
|
><input type="text" value="tempC" id="labelC" />
|
||||||
|
<canvas id="chartC"></canvas>
|
||||||
|
</td>
|
||||||
|
<td class="chart-container">
|
||||||
|
<h2>Channel D <span id="error-tempD"></span></h2>
|
||||||
|
<label for="labelD">label: </label
|
||||||
|
><input type="text" value="tempD" id="labelD" />
|
||||||
|
<canvas id="chartD"></canvas>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="chart-container">
|
||||||
|
<h2>Channel E <span id="error-tempE"></span></h2>
|
||||||
|
<label for="labelE">label: </label
|
||||||
|
><input type="text" value="tempE" id="labelE" />
|
||||||
|
<canvas id="chartE"></canvas>
|
||||||
|
</td>
|
||||||
|
<td class="chart-container">
|
||||||
|
<h2>Channel F <span id="error-tempF"></span></h2>
|
||||||
|
<label for="labelF">label: </label
|
||||||
|
><input type="text" value="tempF" id="labelF" />
|
||||||
|
<canvas id="chartF"></canvas>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="chanGH">
|
||||||
|
<td class="chart-container">
|
||||||
|
<h2>Channel G <span id="error-tempG"></span></h2>
|
||||||
|
<label for="labelG">label: </label
|
||||||
|
><input type="text" value="tempG" id="labelG" />
|
||||||
|
<canvas id="chartG"></canvas>
|
||||||
|
</td>
|
||||||
|
<td class="chart-container">
|
||||||
|
<h2>Channel H <span id="error-tempH"></span></h2>
|
||||||
|
<label for="labelH">label: </label
|
||||||
|
><input type="text" value="tempH" id="labelH" />
|
||||||
|
<canvas id="chartH"></canvas>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<script src="script.js"></script>
|
<script src="script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
238
data/script.js
238
data/script.js
|
@ -1,7 +1,11 @@
|
||||||
|
let isESP32;
|
||||||
fetch("/isESP32")
|
fetch("/isESP32")
|
||||||
.then((res) => res.text())
|
.then((res) => res.text())
|
||||||
.then((textResponse) => {
|
.then((textResponse) => {
|
||||||
let isESP32 = textResponse;
|
isESP32 = textResponse;
|
||||||
|
if (isESP32 == 0) {
|
||||||
|
document.querySelector("#chanGH").style.display = "none";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
fetch("/int")
|
fetch("/int")
|
||||||
.then((res) => res.text())
|
.then((res) => res.text())
|
||||||
|
@ -9,42 +13,23 @@ fetch("/int")
|
||||||
document.querySelector("#updInt").innerText = textResponse;
|
document.querySelector("#updInt").innerText = textResponse;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let lightbox = document.querySelector("#lightbox");
|
||||||
const canvasA = document.querySelector("#chartA");
|
const canvasA = document.querySelector("#chartA");
|
||||||
const canvasB = document.querySelector("#chartB");
|
const canvasB = document.querySelector("#chartB");
|
||||||
|
const canvasC = document.querySelector("#chartC");
|
||||||
|
const canvasD = document.querySelector("#chartD");
|
||||||
|
const canvasE = document.querySelector("#chartE");
|
||||||
|
const canvasF = document.querySelector("#chartF");
|
||||||
|
const canvasG = document.querySelector("#chartG");
|
||||||
|
const canvasH = document.querySelector("#chartH");
|
||||||
|
|
||||||
const chartUpdateInt = document.querySelector("#chartUpd").value;
|
const chartUpdateInt = document.querySelector("#chartUpd").value;
|
||||||
document.querySelector("#stopRec").disabled = true;
|
document.querySelector("#stopRec").disabled = true;
|
||||||
let data;
|
let data;
|
||||||
let record = 0;
|
let record = 0;
|
||||||
let filename;
|
let filename;
|
||||||
let csvData;
|
let csvData = [];
|
||||||
let labelA, labelB;
|
let labelA, labelB, labelC, labelD, labelE, labelF, labelG, labelH;
|
||||||
const chartAdata = {
|
|
||||||
data: {
|
|
||||||
labels: [],
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: "Channel A temperature",
|
|
||||||
backgroundColor: "red",
|
|
||||||
borderColor: "red",
|
|
||||||
data: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const chartBdata = {
|
|
||||||
data: {
|
|
||||||
labels: [],
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: "Channel B temperature",
|
|
||||||
backgroundColor: "blue",
|
|
||||||
borderColor: "blue",
|
|
||||||
data: [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
animation: false,
|
animation: false,
|
||||||
|
@ -127,6 +112,100 @@ const chartB = new Chart(canvasB, {
|
||||||
options: options,
|
options: options,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const chartC = new Chart(canvasC, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: [],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Channel C temperature",
|
||||||
|
backgroundColor: "red",
|
||||||
|
borderColor: "red",
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
});
|
||||||
|
|
||||||
|
const chartD = new Chart(canvasD, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: [],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Channel D temperature",
|
||||||
|
backgroundColor: "blue",
|
||||||
|
borderColor: "blue",
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
});
|
||||||
|
const chartE = new Chart(canvasE, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: [],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Channel E temperature",
|
||||||
|
backgroundColor: "red",
|
||||||
|
borderColor: "red",
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
});
|
||||||
|
|
||||||
|
const chartF = new Chart(canvasF, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: [],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Channel F temperature",
|
||||||
|
backgroundColor: "blue",
|
||||||
|
borderColor: "blue",
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
});
|
||||||
|
const chartG = new Chart(canvasG, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: [],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Channel G temperature",
|
||||||
|
backgroundColor: "red",
|
||||||
|
borderColor: "red",
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
});
|
||||||
|
|
||||||
|
const chartH = new Chart(canvasH, {
|
||||||
|
type: "line",
|
||||||
|
data: {
|
||||||
|
labels: [],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "Channel H temperature",
|
||||||
|
backgroundColor: "blue",
|
||||||
|
borderColor: "blue",
|
||||||
|
data: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
options: options,
|
||||||
|
});
|
||||||
|
|
||||||
var gateway = `ws://${window.location.hostname}/ws`;
|
var gateway = `ws://${window.location.hostname}/ws`;
|
||||||
var websocket;
|
var websocket;
|
||||||
// Init web socket when the page loads
|
// Init web socket when the page loads
|
||||||
|
@ -217,8 +296,51 @@ setInterval(function () {
|
||||||
} else {
|
} else {
|
||||||
document.querySelector("#error-tempB").innerText = "";
|
document.querySelector("#error-tempB").innerText = "";
|
||||||
}
|
}
|
||||||
|
if (isNaN(data["tempC"])) {
|
||||||
|
document.querySelector("#error-tempC").innerHTML =
|
||||||
|
"<h3>" + data["tempC"] + "</h3>";
|
||||||
|
} else {
|
||||||
|
document.querySelector("#error-tempC").innerText = "";
|
||||||
|
}
|
||||||
|
if (isNaN(data["tempD"])) {
|
||||||
|
document.querySelector("#error-tempD").innerHTML =
|
||||||
|
"<h3>" + data["tempD"] + "</h3>";
|
||||||
|
} else {
|
||||||
|
document.querySelector("#error-tempD").innerText = "";
|
||||||
|
}
|
||||||
|
if (isNaN(data["tempE"])) {
|
||||||
|
document.querySelector("#error-tempE").innerHTML =
|
||||||
|
"<h3>" + data["tempE"] + "</h3>";
|
||||||
|
} else {
|
||||||
|
document.querySelector("#error-tempE").innerText = "";
|
||||||
|
}
|
||||||
|
if (isNaN(data["tempF"])) {
|
||||||
|
document.querySelector("#error-tempF").innerHTML =
|
||||||
|
"<h3>" + data["tempF"] + "</h3>";
|
||||||
|
} else {
|
||||||
|
document.querySelector("#error-tempF").innerText = "";
|
||||||
|
}
|
||||||
|
if (isNaN(data["tempG"])) {
|
||||||
|
document.querySelector("#error-tempG").innerHTML =
|
||||||
|
"<h3>" + data["tempG"] + "</h3>";
|
||||||
|
} else {
|
||||||
|
document.querySelector("#error-tempG").innerText = "";
|
||||||
|
}
|
||||||
|
if (isNaN(data["tempH"])) {
|
||||||
|
document.querySelector("#error-tempH").innerHTML =
|
||||||
|
"<h3>" + data["tempH"] + "</h3>";
|
||||||
|
} else {
|
||||||
|
document.querySelector("#error-tempH").innerText = "";
|
||||||
|
}
|
||||||
|
|
||||||
addData(chartA, data["time"], data["tempA"]);
|
addData(chartA, data["time"], data["tempA"]);
|
||||||
addData(chartB, data["time"], data["tempB"]);
|
addData(chartB, data["time"], data["tempB"]);
|
||||||
|
addData(chartC, data["time"], data["tempC"]);
|
||||||
|
addData(chartD, data["time"], data["tempD"]);
|
||||||
|
addData(chartE, data["time"], data["tempE"]);
|
||||||
|
addData(chartF, data["time"], data["tempF"]);
|
||||||
|
addData(chartG, data["time"], data["tempG"]);
|
||||||
|
addData(chartH, data["time"], data["tempH"]);
|
||||||
}, chartUpdateInt);
|
}, chartUpdateInt);
|
||||||
|
|
||||||
function escapeValue(value) {
|
function escapeValue(value) {
|
||||||
|
@ -269,7 +391,49 @@ function startRecording() {
|
||||||
document.querySelector("#filename").innerText = filename;
|
document.querySelector("#filename").innerText = filename;
|
||||||
labelA = document.querySelector("#labelA").value;
|
labelA = document.querySelector("#labelA").value;
|
||||||
labelB = document.querySelector("#labelB").value;
|
labelB = document.querySelector("#labelB").value;
|
||||||
csvData = ['time,"' + labelA + '","' + labelB + '"'];
|
labelC = document.querySelector("#labelC").value;
|
||||||
|
labelD = document.querySelector("#labelD").value;
|
||||||
|
labelE = document.querySelector("#labelE").value;
|
||||||
|
labelF = document.querySelector("#labelF").value;
|
||||||
|
labelG = document.querySelector("#labelG").value;
|
||||||
|
labelH = document.querySelector("#labelH").value;
|
||||||
|
if (isESP32 == 1) {
|
||||||
|
csvData = [
|
||||||
|
'time,"' +
|
||||||
|
labelA +
|
||||||
|
'","' +
|
||||||
|
labelB +
|
||||||
|
'","' +
|
||||||
|
labelC +
|
||||||
|
'","' +
|
||||||
|
labelD +
|
||||||
|
'","' +
|
||||||
|
labelE +
|
||||||
|
'","' +
|
||||||
|
labelF +
|
||||||
|
'","' +
|
||||||
|
labelG +
|
||||||
|
'","' +
|
||||||
|
labelH +
|
||||||
|
'"',
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
csvData = [
|
||||||
|
'time,"' +
|
||||||
|
labelA +
|
||||||
|
'","' +
|
||||||
|
labelB +
|
||||||
|
'","' +
|
||||||
|
labelC +
|
||||||
|
'","' +
|
||||||
|
labelD +
|
||||||
|
'","' +
|
||||||
|
labelE +
|
||||||
|
'","' +
|
||||||
|
labelF +
|
||||||
|
'"',
|
||||||
|
];
|
||||||
|
}
|
||||||
record = 1;
|
record = 1;
|
||||||
document.querySelector("#startRec").disabled = true;
|
document.querySelector("#startRec").disabled = true;
|
||||||
document.querySelector("#stopRec").disabled = false;
|
document.querySelector("#stopRec").disabled = false;
|
||||||
|
@ -284,7 +448,8 @@ function startRecording() {
|
||||||
}
|
}
|
||||||
timer = timer * 60000;
|
timer = timer * 60000;
|
||||||
let timeleft = timer / 1000;
|
let timeleft = timer / 1000;
|
||||||
let disp = document.querySelector("#timeLeft");
|
let disp = document.querySelector("#timeLeftCtr");
|
||||||
|
document.querySelector("#timeLeft").style.display = "inherit";
|
||||||
startTimer(timeleft, disp);
|
startTimer(timeleft, disp);
|
||||||
setTimeout(stopRecording, timer);
|
setTimeout(stopRecording, timer);
|
||||||
}
|
}
|
||||||
|
@ -360,3 +525,12 @@ document.querySelector("#timedRec").onchange = function () {
|
||||||
document.querySelector("#timedSettings").style.display = "none";
|
document.querySelector("#timedSettings").style.display = "none";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function showCredits() {
|
||||||
|
lightbox.style.visibility = "visible";
|
||||||
|
lightbox.style.opacity = "1"
|
||||||
|
}
|
||||||
|
function hideCredits() {
|
||||||
|
lightbox.style.visibility = "hidden";
|
||||||
|
lightbox.style.opacity = "0"
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ body {
|
||||||
background-color: rgb(50, 50, 50);
|
background-color: rgb(50, 50, 50);
|
||||||
color: white;
|
color: white;
|
||||||
padding: 1rem 2rem;
|
padding: 1rem 2rem;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
#du,
|
#du,
|
||||||
#cu {
|
#cu {
|
||||||
|
@ -42,7 +43,8 @@ button[disabled] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#record, #recInfo {
|
#record,
|
||||||
|
#recInfo {
|
||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
grid-template-columns: auto 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
grid-gap: 10px;
|
grid-gap: 10px;
|
||||||
|
@ -62,7 +64,13 @@ button[disabled] {
|
||||||
padding: 0 9.5rem;
|
padding: 0 9.5rem;
|
||||||
}
|
}
|
||||||
#error-tempA,
|
#error-tempA,
|
||||||
#error-tempB {
|
#error-tempB,
|
||||||
|
#error-tempC,
|
||||||
|
#error-tempD,
|
||||||
|
#error-tempE,
|
||||||
|
#error-tempF,
|
||||||
|
#error-tempG,
|
||||||
|
#error-tempH {
|
||||||
color: red !important;
|
color: red !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,9 +82,45 @@ button[disabled] {
|
||||||
}
|
}
|
||||||
@keyframes blink {
|
@keyframes blink {
|
||||||
50% {
|
50% {
|
||||||
opacity: 0.0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.blinking {
|
.blinking {
|
||||||
animation: blink 1s step-start 0s infinite;
|
animation: blink 1s step-start 0s infinite;
|
||||||
}
|
}
|
||||||
|
#lightbox {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 999;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
#lightbox #credits {
|
||||||
|
user-select: none;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
object-fit: cover;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: rgb(50, 50, 50);
|
||||||
|
border: 3px solid black;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#closebtn {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#timeLeft {
|
||||||
|
display: none;
|
||||||
|
}
|
93
src/main.cpp
93
src/main.cpp
|
@ -2,9 +2,9 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <Arduino_JSON.h>
|
#include <Arduino_JSON.h>
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#else
|
#else
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <ESPAsyncWiFiManager.h>
|
#include <ESPAsyncWiFiManager.h>
|
||||||
|
@ -14,16 +14,33 @@
|
||||||
|
|
||||||
// sensor chip select pin definitions
|
// sensor chip select pin definitions
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#define CS_A 22
|
#define CS_A 22
|
||||||
#define CS_B 21
|
#define CS_B 21
|
||||||
|
#define CS_C 17
|
||||||
|
#define CS_D 16
|
||||||
|
#define CS_E 27
|
||||||
|
#define CS_F 14
|
||||||
|
#define CS_G 12
|
||||||
|
#define CS_H 13
|
||||||
#else
|
#else
|
||||||
#define CS_A D2
|
#define CS_A D0
|
||||||
#define CS_B D3
|
#define CS_B D1
|
||||||
|
#define CS_C D2
|
||||||
|
#define CS_D D3
|
||||||
|
#define CS_E D4
|
||||||
|
#define CS_F D7
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
Adafruit_MAX31855 thermocoupleA(CS_A);
|
Adafruit_MAX31855 thermocoupleA(CS_A);
|
||||||
Adafruit_MAX31855 thermocoupleB(CS_B);
|
Adafruit_MAX31855 thermocoupleB(CS_B);
|
||||||
|
Adafruit_MAX31855 thermocoupleC(CS_C);
|
||||||
|
Adafruit_MAX31855 thermocoupleD(CS_D);
|
||||||
|
Adafruit_MAX31855 thermocoupleE(CS_E);
|
||||||
|
Adafruit_MAX31855 thermocoupleF(CS_F);
|
||||||
|
#ifdef ESP32
|
||||||
|
Adafruit_MAX31855 thermocoupleG(CS_G);
|
||||||
|
Adafruit_MAX31855 thermocoupleH(CS_H);
|
||||||
|
#endif
|
||||||
|
|
||||||
AsyncWebServer server(80);
|
AsyncWebServer server(80);
|
||||||
AsyncWebSocket ws("/ws");
|
AsyncWebSocket ws("/ws");
|
||||||
|
@ -61,6 +78,14 @@ String getSensorReadings() {
|
||||||
readings["time"] = String(lastTime);
|
readings["time"] = String(lastTime);
|
||||||
readings["tempA"] = checkSensor(thermocoupleA);
|
readings["tempA"] = checkSensor(thermocoupleA);
|
||||||
readings["tempB"] = checkSensor(thermocoupleB);
|
readings["tempB"] = checkSensor(thermocoupleB);
|
||||||
|
readings["tempC"] = checkSensor(thermocoupleC);
|
||||||
|
readings["tempD"] = checkSensor(thermocoupleD);
|
||||||
|
readings["tempE"] = checkSensor(thermocoupleE);
|
||||||
|
readings["tempF"] = checkSensor(thermocoupleF);
|
||||||
|
#ifdef ESP32
|
||||||
|
readings["tempG"] = checkSensor(thermocoupleG);
|
||||||
|
readings["tempH"] = checkSensor(thermocoupleH);
|
||||||
|
#endif
|
||||||
String jsonString = JSON.stringify(readings);
|
String jsonString = JSON.stringify(readings);
|
||||||
return jsonString;
|
return jsonString;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +106,7 @@ void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
|
||||||
Serial.printf("%s\n", sensorReadings.c_str());
|
Serial.printf("%s\n", sensorReadings.c_str());
|
||||||
notifyClients(sensorReadings);
|
notifyClients(sensorReadings);
|
||||||
}
|
}
|
||||||
// check if message is an update interval change
|
// check if message is an update interval change
|
||||||
if (message.startsWith("u")) {
|
if (message.startsWith("u")) {
|
||||||
// if it is, strip the first character, convert to int and update timerDelay variable
|
// if it is, strip the first character, convert to int and update timerDelay variable
|
||||||
String uVal = (message.substring(message.indexOf("u") + 1, message.length()));
|
String uVal = (message.substring(message.indexOf("u") + 1, message.length()));
|
||||||
|
@ -117,12 +142,12 @@ void initSerial() {
|
||||||
Serial.print("serial init\n");
|
Serial.print("serial init\n");
|
||||||
}
|
}
|
||||||
void initSPI() {
|
void initSPI() {
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
SPIClass hspi(HSPI);
|
SPIClass hspi(HSPI);
|
||||||
hspi.begin();
|
hspi.begin();
|
||||||
#else
|
#else
|
||||||
SPI.begin();
|
SPI.begin();
|
||||||
#endif
|
#endif
|
||||||
Serial.printf("SPI init\n");
|
Serial.printf("SPI init\n");
|
||||||
Serial.printf("using pins:\nPOCI: %d\tCLK: %d\nCS_A: %d\tCS_B: %d\n", MISO, SCK, CS_A, CS_B);
|
Serial.printf("using pins:\nPOCI: %d\tCLK: %d\nCS_A: %d\tCS_B: %d\n", MISO, SCK, CS_A, CS_B);
|
||||||
}
|
}
|
||||||
|
@ -130,12 +155,12 @@ void initLittleFS() {
|
||||||
LittleFS.begin();
|
LittleFS.begin();
|
||||||
Serial.printf("LittleFS init\n");
|
Serial.printf("LittleFS init\n");
|
||||||
}
|
}
|
||||||
void initSensor() {
|
void initSensor(Adafruit_MAX31855 &sensor, const char *id) {
|
||||||
if (!thermocoupleA.begin() | !thermocoupleB.begin()) {
|
if (!sensor.begin()) {
|
||||||
Serial.printf("sensor init error\n");
|
Serial.printf("sensor %s init error\n", id);
|
||||||
while (true) delay(10);
|
while (true) delay(10);
|
||||||
}
|
}
|
||||||
Serial.printf("sensor init\n");
|
Serial.printf("sensor %s init\n", id);
|
||||||
}
|
}
|
||||||
void initWiFi() {
|
void initWiFi() {
|
||||||
WiFi.mode(WIFI_AP_STA);
|
WiFi.mode(WIFI_AP_STA);
|
||||||
|
@ -154,21 +179,24 @@ void initWebServer() {
|
||||||
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
request->send(LittleFS, "/index.html", "text/html");
|
request->send(LittleFS, "/index.html", "text/html");
|
||||||
});
|
});
|
||||||
|
server.on("/about", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
|
request->send(LittleFS, "/about.html", "text/html");
|
||||||
|
});
|
||||||
server.onNotFound([](AsyncWebServerRequest *request) {
|
server.onNotFound([](AsyncWebServerRequest *request) {
|
||||||
request->send(404, "text/plain", "404 Not Found");
|
request->send(404, "text/plain", "404 Not Found");
|
||||||
});
|
});
|
||||||
server.on("/int", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/int", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
request->send_P(200, "text/plain", String(timerDelay).c_str());
|
request->send_P(200, "text/plain", String(timerDelay).c_str());
|
||||||
});
|
});
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
server.on("/isESP32", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/isESP32", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
request->send(200, "text/plain", String(true));
|
request->send(200, "text/plain", String(true));
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
server.on("/isESP32", HTTP_GET, [](AsyncWebServerRequest *request) {
|
server.on("/isESP32", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||||
request->send(200, "text/plain", String(false));
|
request->send(200, "text/plain", String(false));
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
server.serveStatic("/", LittleFS, "/");
|
server.serveStatic("/", LittleFS, "/");
|
||||||
server.begin();
|
server.begin();
|
||||||
Serial.printf("webserver init\n");
|
Serial.printf("webserver init\n");
|
||||||
|
@ -178,7 +206,16 @@ void setup() {
|
||||||
initSerial();
|
initSerial();
|
||||||
initSPI();
|
initSPI();
|
||||||
initLittleFS();
|
initLittleFS();
|
||||||
initSensor();
|
initSensor(thermocoupleA, "A");
|
||||||
|
initSensor(thermocoupleB, "B");
|
||||||
|
initSensor(thermocoupleC, "C");
|
||||||
|
initSensor(thermocoupleD, "D");
|
||||||
|
initSensor(thermocoupleE, "E");
|
||||||
|
initSensor(thermocoupleF, "F");
|
||||||
|
#ifdef ESP32
|
||||||
|
initSensor(thermocoupleG, "G");
|
||||||
|
initSensor(thermocoupleH, "H");
|
||||||
|
#endif
|
||||||
initWiFi();
|
initWiFi();
|
||||||
initWebSocket();
|
initWebSocket();
|
||||||
initWebServer();
|
initWebServer();
|
||||||
|
|
Loading…
Reference in a new issue