-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
289 lines (262 loc) · 15.6 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
<!DOCTYPE html>
<html lang="en" dir="ltr"><head>
<meta charset="utf-8">
<title>HVAC Diagnostics Tool</title>
<script src="neataptic.js"></script>
<script src="common.js"></script>
<script src="data.js"></script>
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Compiled and minified JavaScript -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="cola.min.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script src="https://rawgit.com/wagenaartje/neataptic/master/graph/graph.js"></script>
<link rel="stylesheet" type="text/css" href="https://rawgit.com/wagenaartje/neataptic/master/graph/graph.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="index.css">
</head>
<body>
<nav>
<div class="nav-wrapper indigo darken-4">
<a href="" class="brand-logo center" style="width: 100%"><span class="material-icons notranslate">
build
</span> HVAC-Diagnostics.com</a>
</div>
</nav>
<div class="container">
<h5>Data-driven HVAC Diagnostic Tool</h5>
<section class="card">
<div class="row">
<form class="col s12" onsubmit="testForm();return false;">
<div class="row">
<div class="input-field col s12">
<input type="number" step="any" placeholder="Condenser ambient temp." required="" id="ambient" value="92">
<label for="ambient" class="active">Ambient Temperature</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<input type="number" step="any" placeholder="Low-side Line Temp - Low Sat temp." required="" id="sh" value="35">
<label for="sh" class="active">Superheat</label>
</div>
<div class="input-field col s6">
<input type="number" step="any" placeholder="High Sat temp. - High-side Line Temp" required="" id="sc" value="15">
<label for="sc" class="active">Subcool</label>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<input type="number" step="any" required="" id="lt" value="29.25" placeholder="based on low-side pressure">
<label for="lt" class="active">Low saturation temp.</label>
</div>
<div class="input-field col s6">
<input type="number" step="any" required="" id="ht" value="110.7" placeholder="based on high-side pressure">
<label for="ht" class="active">High saturation temp.</label>
</div>
</div><div class="row">
<div class="input-field col s6">
<input type="number" step="any" placeholder="As shown on nameplate" id="da" value="">
<label for="da" class="active">Design amperage</label>
</div>
<div class="input-field col s6">
<input type="number" step="any" placeholder="(leave blank if can't be measured)" id="aa" value="">
<label for="a" class="active">Measured amperage</label>
</div>
</div>
<button class="btn grey" type="button" onclick="$('input').val('');M.updateTextFields();return true;">Reset</button>
<button class="btn btn-floating" style="background: #26a69a !important;border-radius: 2px;width: auto;height: 36px;line-height: 36px;padding: 0 16px;" type="submit">Diagnose</button>
</form>
</div>
</section>
<div id="modal1" class="modal" tabindex="0">
<div class="modal-content">
<h5>Diagnosis</h5>
<div id="results">
</div>
</div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green btn-flat">Close</a>
</div>
</div>
<br>
<div id="console" style="display: none"><span style="color: grey">`localStorage` support found, cached=19.071</span>, <button type="button" onclick="delete localStorage.dataVer;location.reload();">Delete cached network</button><br><span style="color: green">Loaded.</span><br></div>
<script src="index.js"></script>
<script type="text/javascript">
function testForm() {
let da = parseFloat(document.getElementById('da').value);
let aa = parseFloat(document.getElementById('aa').value);
let amp;
let predictamp = activate(parseFloat(document.getElementById('ambient').value),
parseFloat(document.getElementById('sh').value),
parseFloat(document.getElementById('sc').value),
parseFloat(document.getElementById('lt').value),
parseFloat(document.getElementById('ht').value), networkToPredictAmp)[0];
if (!da || !aa) {
amp = predictamp;
} else
amp = aa / da;
let results = activate(parseFloat(document.getElementById('ambient').value),
parseFloat(document.getElementById('sh').value),
parseFloat(document.getElementById('sc').value),
parseFloat(document.getElementById('lt').value),
parseFloat(document.getElementById('ht').value),
amp);
// Charge prediction ===
let chargePredictionHTML = '';
if (results[0] >= 20) {
let predictCharge = activateChargeNetwork(parseFloat(document.getElementById('ambient').value),
parseFloat(document.getElementById('sh').value),
parseFloat(document.getElementById('sc').value),
parseFloat(document.getElementById('lt').value),
parseFloat(document.getElementById('ht').value),
amp);
chargePredictionHTML = `, total charge?<form onsubmit="this.innerHTML += '<br>'+this.children[0].value+' : '+Math.round(this.children[0].value * activateChargeNetwork(parseFloat(document.getElementById('ambient').value),
parseFloat(document.getElementById('sh').value),
parseFloat(document.getElementById('sc').value),
parseFloat(document.getElementById('lt').value),
parseFloat(document.getElementById('ht').value),
${amp}, parseFloat(this.children[0].value)) / 10) / 10 + 'lbs';return false;"><input type="number" step="0.01"><button type="submit" style="display: none;"></button></form>`;
}
let problem = 'font-weight: bold; color: red;';
let warning = 'font-weight: normal; color: orange; opacity: 0.8';
let good = 'font-weight: 200; color: green; opacity: 0.6';
let xp = ``;
let html = `
<span style="${(!da || !aa) && predictamp > 0.9 ? problem : (!da || !aa) && predictamp > 0.7 ? warning : (!da || !aa) ? good : ''}">Predicted Amp ratio: ${Math.round(predictamp * 100) / 100}</span>
<span style="${(da && aa) && amp > 0.9 ? problem : (da && aa) && amp > 0.7 ? warning : (da && aa) ? good : ''}">${!da || !aa ? '' : 'Actual ratio: ' + Math.round(amp * 100) / 100}<br /></span>
`;
if (((!da || !aa) && predictamp > 0.9) || ((da && aa) && amp > 0.9)) { // red
xp += '<p>The amperage ratio is very high. Check condenser coil cleanliness. Recommend replacing compressor.</p>';
} else if (((!da || !aa) && predictamp > 0.7) || ((da && aa) && amp > 0.7)) { // warning
xp += '<p>The amperage ratio is high. If condenser coil is dirty, rinse with pressured water. </p>';
} else if ((!da || !aa) || (da && aa)) { // good
xp += '<p>The amperage ratio is normal.</p>';
}
let problems = [];
problems.push([results[0], `<span style="${results[0] >= 60 ? problem : results[0] >= 20 ? warning : good};">Undercharge: ${results[0]}%${chargePredictionHTML}</span><br />`]);
problems.push([results[1], `<span style="${results[1] >= 60 ? problem : results[1] >= 20 ? warning : good};">Overcharge: ${results[1]}%</span><br />`]);
problems.push([results[2], `<span style="${results[2] >= 60 ? problem : results[2] >= 20 ? warning : good};">Low Indoor Flow: ${results[2]}%</span><br />`]);
problems.push([results[3], `<span style="${results[3] >= 60 ? problem : results[3] >= 20 ? warning : good};">Dirty coil: ${results[3]}%</span><br />`]);
problems.push([results[4], `<span style="${results[4] >= 60 ? problem : results[4] >= 20 ? warning : good};">Restriction: ${results[4]}%</span><br />`]);
problems.push([results[5], `<span style="${results[5] >= 60 ? problem : results[5] >= 20 ? warning : good};">TXV Stuck Open: ${results[5]}%</span><br />`]);
if (results[4] >= 60) {
xp += '<p>Check TXV and filter drier restriction.</p>';
} else if (results[4] >= 20) {
xp += '<p>Check proper indoor air flow, TXV bulb location and filter drier restriction.</p>';
}
if (results[0] >= 60) {
xp += '<p>Unit is undercharged. Add refrigerant until subcool is normal and retest.</p>';
} else if (results[0] >= 20) {
xp += '<p>Unit might be undercharged. Add refrigerant until subcool is normal and retest..</p>';
}
if (results[1] >= 60) {
xp += '<p>Unit is heavily overcharged. Recover freon and retest.</p>';
} else if (results[1] >= 20) {
xp += '<p>Unit might be slightly overcharged.</p>';
}
if (results[3] >= 60) {
xp += '<p>Poor subcool performance. Check condenser coil cleanliness. Recommend replacing condenser unit</p>';
} else if (results[3] >= 20) {
xp += '<p>Check condenser coil cleanliness.</p>';
}
problems.sort((a, b) => (b[0] - a[0])).filter(x => x[0] >= 20).forEach(x => {
html += x[1];
});
if (problems.sort((a, b) => (b[0] - a[0])).filter(x => x[0] >= 20).length == 0) {
xp += '<p>Unit is running normal.</p>'
} else if (problems.sort((a, b) => (b[0] - a[0])).filter(x => x[0] >= 60).length == 0) {
xp += '<p>Unit is running okay.</p>'
}
document.getElementById('results').innerHTML = html + xp;
$('.modal').modal('open');
return false;
}
$(function () {
$('.modal').modal();
$('svg').attr('width', $('.container').width())
if (drawGraph)
drawGraph(network.graph($('.container').width(), 500), '.draw');
else
$('svg').remove();
})
</script>
<!-- <svg class="draw" height=500> -->
<div class="markdown-preview" data-use-github-style="data-use-github-style">
<p><b>Update (2020): This site will no longer be maintained.</b></p>
<p>Contacts: [email protected], <a target="_blank" href="https://github.com/SitanHuang/">Github Profile</a></p>
<p></p>
<h3 id="why-use-it">Why use it?</h3>
<p>Accurate fault diagnosing reduces cost and increases profit. Troubleshooting HVAC systems requires not only a thorough understanding of the HVAC system, but also relies heavily on the experiences of the technician. This is an easy-to-use diagnostic helper that gives the probabilities of each fault based on your inputs.</p>
<p>At our company, the tool is especially useful to new recruits. Rather than consulting senior techs for difficult cases, our apprentices can access this tool on their phone and give accurate diagnoses.</p>
<p><b>This is a system in development and requires more data collection for more accurate results.</b></p>
<h3 id="how-does-it-work">How does it work?</h3>
<p>A Neural Network learns from real life diagnoses that our senior technicians collected. Each data entry contains field measurements as well as the appropriate fix applied to that system. If an applied fix puts the system back to normal, we can reasonably deduce that the fault of the system based on the fix.</p>
<p>For example:</p>
<table>
<thead>
<tr class="header">
<th>Fix</th>
<th align="left">Fault</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Added refrigerant</td>
<td align="left">System undercharged</td>
</tr>
<tr class="even">
<td>Replaced air filters</td>
<td align="left">Low indoor flow</td>
</tr>
<tr class="odd">
<td>Cleaned coil</td>
<td align="left">Dirty coil</td>
</tr>
<tr class="even">
<td>Replaced filter drier</td>
<td align="left">Restriction</td>
</tr>
<tr class="odd">
<td>…</td>
<td align="left">…</td>
</tr>
</tbody>
</table>
<p>There may be cases of multiple fixes applied. These cases are especially valuable since they allow my neural network to learn to find multiple faults in one diagnosis.</p>
<h3 id="the-architecture">The Architecture</h3>
<p>All neural networks in this tool are feed-forward network.</p>
<p>The main network yields probabilities of each fault from ambient temperature, saturation temperatures, line temperatures and amperage ratio. </p>
<p>In case amperage cannot be measured, the amperage network predicts the amperage ratio from all other inputs. The network is trained with data containing actual measured amperage ratio and relevant field measurements from which the amperage ratio may be predicted.</p>
<p>In case of refrigerant undercharge, the network predicts the amount of refrigerant needed. The network is trained with data containing temperature and pressure measurements as well as the actual weight of refrigerant added.</p>
</div>
<br><br>
</div>
<footer class="page-footer indigo darken-4">
<div class="container">
<div class="row">
<div class="col l6 s12">
<h5 class="white-text">Sitan Huang</h5>
<p class="grey-text text-lighten-4">
Technician at <a target="_blank" href="http://bruceac.com" class="grey-text text-lighten-3">BruceAC LLC.</a>
</p>
</div>
<div class="col l4 offset-l2 s12">
<h5 class="white-text">Links</h5>
<ul>
<li>- <a target="_blank" class="grey-text text-lighten-3" href="mailto:[email protected]">[email protected]</a></li>
<li>- <a target="_blank" class="grey-text text-lighten-3" href="https://github.com/SitanHuang">Github</a></li>
<li>- <a target="_blank" class="grey-text text-lighten-3" href="https://www.youtube.com/channel/UC7mJCXvtX8yU5LU0UH-ZpTA">Youtube Channel</a></li>
</ul>
</div>
</div>
</div>
<div class="footer-copyright">
<div class="container">
© 2020 Sitan Huang
</div>
</div>
</footer>
</body></html>