Compare commits

..

No commits in common. "basicweb" and "main" have entirely different histories.

9 changed files with 2384 additions and 674 deletions

View File

@ -104,19 +104,3 @@ For ease of adaption, connection, and prototyping I've decided to use Cat 5 ethe
2 | pause | 5000 2 | pause | 5000
3 | igniter_start | 420000 3 | igniter_start | 420000
4 | blower_stop | 600000 4 | blower_stop | 600000
# Startup Procedure
1. Manually toggle the "I" Igniter switch ON
2. Wait 60 seconds
3. Manually toggle the "E" Exhaust switch ON
4. Using the Hestia Web Portal, set Feed Rate to 2
5. Enable the Auger
6. Wait up to three minutes for pellets to ignite
7. Manually toggle the "I" Ingniter switch OFF
8. Monitor fire and adjust feed rates as necessary
# Timings
* 60-90 seconds igniter preheat
* 120-180 seconds for pellet ignition
* 4 minutes from ignition to PoF Close
* 7:30 minutes total

45
main.js
View File

@ -9,15 +9,9 @@ portal.start();
dbfn.run(`UPDATE timestamps SET value = ${Date.now()} WHERE key = 'process_start'`).catch(err => console.error(`Error setting process start time: ${err}`)); dbfn.run(`UPDATE timestamps SET value = ${Date.now()} WHERE key = 'process_start'`).catch(err => console.error(`Error setting process start time: ${err}`));
// Initialization, which then calls main()
fn.commands.refreshConfig().then(res => { fn.commands.refreshConfig().then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res.status}`); if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res.status}`);
config = res.config; config = res.config;
const shutdownNextCycleQuery = "UPDATE status SET value = 0 WHERE key = 'shutdown_next_cycle'";
dbfn.run(shutdownNextCycleQuery).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res.status}`);
console.log(`[${(Date.now() - config.timestamps.procStart) / 1000}] I: Shutdown flag reset.`);
}).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`));
// Setup for use with the Pi's GPIO pins // Setup for use with the Pi's GPIO pins
switch (process.env.ONPI) { switch (process.env.ONPI) {
case 'true': case 'true':
@ -53,45 +47,6 @@ fn.commands.refreshConfig().then(res => {
}); });
function main(gpio) { function main(gpio) {
// Set the Igniter
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: IGN: [${config.status.igniter}] | EXH: [${config.status.exhaust}] | AUG: [${config.status.auger}]`);
switch (config.status.igniter) {
case '0':
fn.igniter.off(gpio).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
});
break;
case '1':
fn.igniter.on(gpio).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
});
break;
default:
fn.igniter.off(gpio).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
});
break;
}
// Set the Exhaust
switch (config.status.exhaust) {
case '0':
fn.exhaust.off(gpio).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
});
break;
case '1':
fn.exhaust.on(gpio).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
});
break;
default:
fn.exhaust.off(gpio).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
});
break;
}
// If the auger is enabled // If the auger is enabled
if (config.status.auger == 1) { if (config.status.auger == 1) {
// Run a cycle of the auger // Run a cycle of the auger

View File

@ -7,20 +7,15 @@
* Add actual data into the responses * Add actual data into the responses
*/ */
// Modules
const express = require('express'); const express = require('express');
const http = require('http'); const http = require('http');
const fs = require('fs');
const fn = require('./functions.js').functions; const fn = require('./functions.js').functions;
const { dbfn } = require('./functions.js');
// Grab the current configuration settings from the database to display
var config; var config;
fn.commands.refreshConfig().then(newConfig => { fn.commands.refreshConfig().then(newConfig => {
config = newConfig.config; config = newConfig.config;
}); });
const { dbfn } = require('./functions.js');
// Create the server
const app = express(); const app = express();
const server = http.createServer(app); const server = http.createServer(app);
app.use(express.urlencoded()); app.use(express.urlencoded());
@ -34,70 +29,28 @@ app.set('view engine', 'html');
// A normal load of the root page // A normal load of the root page
app.get('/', (req, res) => { app.get('/', (req, res) => {
// Render the page, passing the config along for the front end to use // if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${JSON.stringify(config)}`);
res.render('index', { config: JSON.stringify(config) }); res.render('index', { config: JSON.stringify(config) });
}); });
// A POST form submission to the root page // A POST form submission to the root page
app.post('/', (req, response) => { app.post('/', (req, response) => {
if (req.body.augerOn != undefined) { if (req.body.start != undefined) {
fn.commands.augerOn(); fn.commands.startup();
fn.commands.refreshConfig().then(res => { fn.commands.refreshConfig().then(res => {
config = res.config; config = res.config;
response.render('index', { config: JSON.stringify(config) }); response.render('index', { config: JSON.stringify(config) });
return; return;
}); });
return;
} }
if (req.body.augerOff != undefined) { if (req.body.shutdown != undefined) {
fn.commands.augerOff(); fn.commands.shutdown();
fn.commands.refreshConfig().then(res => { fn.commands.refreshConfig().then(res => {
config = res.config; config = res.config;
response.render('index', { config: JSON.stringify(config) }); response.render('index', { config: JSON.stringify(config) });
return; return;
}); });
return;
} }
if (req.body.igniterOn != undefined) {
fn.commands.igniterOn();
fn.commands.refreshConfig().then(res => {
config = res.config;
response.render('index', { config: JSON.stringify(config) });
return;
});
return;
}
if (req.body.igniterOff != undefined) {
fn.commands.igniterOff();
fn.commands.refreshConfig().then(res => {
config = res.config;
response.render('index', { config: JSON.stringify(config) });
return;
});
return;
}
if (req.body.exhaustOn != undefined) {
fn.commands.exhaustOn();
fn.commands.refreshConfig().then(res => {
config = res.config;
response.render('index', { config: JSON.stringify(config) });
return;
});
return;
}
if (req.body.exhaustOff != undefined) {
fn.commands.exhaustOff();
fn.commands.refreshConfig().then(res => {
config = res.config;
response.render('index', { config: JSON.stringify(config) });
return;
});
return;
}
if (req.body.reload != undefined) { if (req.body.reload != undefined) {
const updateAugerOffIntervalQuery = `UPDATE intervals SET value = '${2000 - req.body.feedRate}' WHERE key = 'auger_off'`; const updateAugerOffIntervalQuery = `UPDATE intervals SET value = '${2000 - req.body.feedRate}' WHERE key = 'auger_off'`;
const updateAugerOnIntervalQuery = `UPDATE intervals SET value = '${req.body.feedRate}' WHERE key = 'auger_on'`; const updateAugerOnIntervalQuery = `UPDATE intervals SET value = '${req.body.feedRate}' WHERE key = 'auger_on'`;
@ -112,24 +65,15 @@ app.post('/', (req, response) => {
}); });
}).catch(err => console.log(`E: ${err}`)); }).catch(err => console.log(`E: ${err}`));
}).catch(err => console.log(`E: ${err}`)); }).catch(err => console.log(`E: ${err}`));
return;
} }
if (req.body.quit != undefined) { if (req.body.quit != undefined) {
fs.appendFile('quit', ".", err => { fn.commands.quit();
if (err) console.error(err);
});
fn.commands.refreshConfig().then(res => { fn.commands.refreshConfig().then(res => {
config = res.config; config = res.config;
response.render('index', { config: JSON.stringify(config) }); response.render('index', { config: JSON.stringify(config) });
return; return;
}); });
return;
} }
fn.commands.refreshConfig().then(res => {
config = res.config;
response.render('index', { config: JSON.stringify(config) });
return;
});
}); });
module.exports = { module.exports = {

View File

@ -127,8 +127,8 @@ const createIntervalsTableQuery = "CREATE TABLE IF NOT EXISTS intervals (key var
dbfn.run(createIntervalsTableQuery).then(res => { dbfn.run(createIntervalsTableQuery).then(res => {
console.log(res.status); console.log(res.status);
const intervalsEntries = { const intervalsEntries = {
auger_on: 500, auger_on: 600,
auger_off: 1500, auger_off: 1400,
pause: 5000, pause: 5000,
igniter_start: 420000, igniter_start: 420000,
blower_stop: 600000 blower_stop: 600000

View File

@ -2,9 +2,6 @@
// TODO: Move these to config // TODO: Move these to config
// Physical Pin numbers for GPIO // Physical Pin numbers for GPIO
const augerPin = 7; // Pin for controlling the relay for the pellet auger motor. const augerPin = 7; // Pin for controlling the relay for the pellet auger motor.
const igniterPin = 13;
const exhaustPin = 15;
const pofPin = 16;
// Require the package for pulling version numbers // Require the package for pulling version numbers
const package = require('../package.json'); const package = require('../package.json');
@ -87,83 +84,9 @@ const functions = {
}); });
}, },
}, },
igniter: {
// Gets called once the Igniter Pin has been setup by rpi-gpio
ready(err) {
if (err) throw err;
console.log('Igniter GPIO Ready');
return;
},
// Turns the Igniter on (Pin 7 high)
on(gpio) {
return new Promise((resolve) => {
if (process.env.ONPI == 'true') {
gpio.write(igniterPin, true, function (err) {
if (err) throw err;
resolve('Igniter turned on.');
});
} else {
resolve('Simulated Igniter turned on.');
}
});
},
// Turns the Igniter off (pin 7 low)
off(gpio) {
return new Promise((resolve) => {
if (process.env.ONPI == 'true') {
gpio.write(igniterPin, false, function (err) {
if (err) throw err;
resolve('Igniter turned off.');
});
} else {
resolve('Simulated Igniter turned off.');
}
});
}
},
exhaust: {
// Gets called once the Exhaust Pin has been setup by rpi-gpio
ready(err) {
if (err) throw err;
console.log('Exhaust GPIO Ready');
return;
},
// Turns the Exhaust on (Pin 7 high)
on(gpio) {
return new Promise((resolve) => {
if (process.env.ONPI == 'true') {
gpio.write(exhaustPin, true, function (err) {
if (err) throw err;
resolve('Exhaust turned on.');
});
} else {
resolve('Simulated Exhaust turned on.');
}
});
},
// Turns the Exhaust off (pin 7 low)
off(gpio) {
return new Promise((resolve) => {
if (process.env.ONPI == 'true') {
gpio.write(exhaustPin, false, function (err) {
if (err) throw err;
resolve('Exhaust turned off.');
});
} else {
resolve('Simulated Exhaust turned off.');
}
});
}
},
commands: { commands: {
// Prepare the stove for starting // Prepare the stove for starting
augerOn() { // FKA startup() startup() {
// Basic startup just enables the auger // Basic startup just enables the auger
const enableAugerQuery = "UPDATE status SET value = 1 WHERE key = 'auger'"; const enableAugerQuery = "UPDATE status SET value = 1 WHERE key = 'auger'";
dbfn.run(enableAugerQuery).then(res => { dbfn.run(enableAugerQuery).then(res => {
@ -171,7 +94,7 @@ const functions = {
return; return;
}).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`)); }).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`));
}, },
augerOff() { // FKA shutdown() shutdown() {
// Basic shutdown only needs to disable the auger // Basic shutdown only needs to disable the auger
const disableAugerQuery = "UPDATE status SET value = 0 WHERE key = 'auger'"; const disableAugerQuery = "UPDATE status SET value = 0 WHERE key = 'auger'";
dbfn.run(disableAugerQuery).then(res => { dbfn.run(disableAugerQuery).then(res => {
@ -180,36 +103,6 @@ const functions = {
return; return;
}).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`)); }).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`));
}, },
igniterOn() {
const enableIgniterQuery = "UPDATE status SET value = 1 WHERE key = 'igniter'";
dbfn.run(enableIgniterQuery).then(res => {
console.log(`[${(Date.now() - config.timestamps.procStart) / 1000}] I: Igniter enabled.`);
return;
}).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`));
},
igniterOff() {
const disableIgniterQuery = "UPDATE status SET value = 0 WHERE key = 'igniter'";
dbfn.run(disableIgniterQuery).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res.status}`);
console.log(`[${(Date.now() - config.timestamps.procStart) / 1000}] I: Igniter disabled.`);
return;
}).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`));
},
exhaustOn() {
const enableExhaustQuery = "UPDATE status SET value = 1 WHERE key = 'blower'";
dbfn.run(enableExhaustQuery).then(res => {
console.log(`[${(Date.now() - config.timestamps.procStart) / 1000}] I: Exhaust enabled.`);
return;
}).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`));
},
exhaustOff() {
const disableExhaustQuery = "UPDATE status SET value = 0 WHERE key = 'blower'";
dbfn.run(disableExhaustQuery).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res.status}`);
console.log(`[${(Date.now() - config.timestamps.procStart) / 1000}] I: Exhaust disabled.`);
return;
}).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`));
},
// Pauses the script for the time defined in env variables // Pauses the script for the time defined in env variables
pause() { pause() {
return new Promise((resolve) => { return new Promise((resolve) => {
@ -265,7 +158,7 @@ const functions = {
let { status } = config; let { status } = config;
let { rows } = res; let { rows } = res;
status.auger = rows.auger; status.auger = rows.auger;
status.exhaust = rows.blower; // TODO update db to use exhaust not blower status.blower = rows.blower;
status.igniter = rows.igniter; status.igniter = rows.igniter;
status.igniterFinished = rows.igniter_finished; status.igniterFinished = rows.igniter_finished;
status.pof = rows.proof_of_fire; status.pof = rows.proof_of_fire;
@ -277,8 +170,8 @@ const functions = {
dbfn.all(selectTimestampsQuery).then(res => { dbfn.all(selectTimestampsQuery).then(res => {
let { timestamps } = config; let { timestamps } = config;
let { rows } = res; let { rows } = res;
timestamps.exhaustOff = rows.blower_off; timestamps.blowerOff = rows.blower_off;
timestamps.exhaustOn = rows.blower_on; timestamps.blowerOn = rows.blower_on;
timestamps.igniterOff = rows.igniter_off; timestamps.igniterOff = rows.igniter_off;
timestamps.igniterOn = rows.igniter_on; timestamps.igniterOn = rows.igniter_on;
timestamps.procStart = rows.process_start; timestamps.procStart = rows.process_start;
@ -362,25 +255,12 @@ const functions = {
gpio.setup(augerPin, gpio.DIR_OUT, (err) => { gpio.setup(augerPin, gpio.DIR_OUT, (err) => {
if (err) reject(err); if (err) reject(err);
if (process.env.DEBUG) console.log('== Auger pin initialized.'); if (process.env.DEBUG) console.log('== Auger pin initialized.');
this.auger.ready(); // Resolve the promise now that all pins have been initialized
// Init the Igniter pin resolve('== GPIO Initialized.');
gpio.setup(igniterPin, gpio.DIR_OUT, (err) => {
if (err) reject(err);
if (process.env.DEBUG) console.log('== Igniter pin initialized.');
this.igniter.ready();
// Init the Exhaust pin
gpio.setup(exhaustPin, gpio.DIR_OUT, (err) => {
if (err) reject(err);
if (process.env.DEBUG) console.log('== Exhaust pin initialized.');
this.exhaust.ready();
// Resolve the promise now that all pins have been initialized
resolve('== GPIO Initialized.');
});
});
}); });
} else { } else {
// Resolve the promise // Resolve the promise
resolve('== GPIO Simulated'); resolve('== GPIO Not Available');
} }
}); });
}, },
@ -395,11 +275,6 @@ const functions = {
if (err) console.log('Error removing the quit file: ' + err); if (err) console.log('Error removing the quit file: ' + err);
config.status.shutdownNextCycle = 1; config.status.shutdownNextCycle = 1;
config.status.auger = 0; config.status.auger = 0;
const shutdownNextCycleQuery = "UPDATE status SET value = 1 WHERE key = 'shutdown_next_cycle'";
dbfn.run(shutdownNextCycleQuery).then(res => {
if (process.env.DEBUG) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res.status}`);
console.log(`[${(Date.now() - config.timestamps.procStart) / 1000}] I: Shutting down next cycle.`);
}).catch(err => console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`));
resolve(); resolve();
}); });
} else { } else {

2692
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "hestia", "name": "pscontrolpanel",
"version": "0.3.0", "version": "0.2.1",
"requires": true, "requires": true,
"packages": {}, "packages": {},
"dependencies": { "dependencies": {
@ -10,6 +10,6 @@
"express": "^4.18.2", "express": "^4.18.2",
"rpi-gpio": "^2.1.7", "rpi-gpio": "^2.1.7",
"sequelize": "^6.28.0", "sequelize": "^6.28.0",
"sqlite3": "^5.1.6" "sqlite3": "^5.1.4"
} }
} }

View File

@ -87,7 +87,7 @@ html, body {
} }
table { table {
margin: 10; margin: 0 auto;
color: aqua !important; color: aqua !important;
} }
@ -96,11 +96,3 @@ table, th, td {
border-collapse: collapse; border-collapse: collapse;
padding: 3px; padding: 3px;
} }
th, td {
width: 50%;
}
#quit {
/* visibility: hidden; */
}

View File

@ -21,28 +21,22 @@
</div> </div>
<div id="status" class="row"> <div id="status" class="row">
<!-- <!--
| Igniter | rows[0].cells[1] | Auger | rows[0].cells[1] | On Time | rows[0].cells[3] |
| Exhaust | rows[1].cells[1] | Feed Rate | rows[1].cells[1] | Off Time | rows[1].cells[3] |
| Auger | rows[2].cells[1]
| Feed Rate | rows[3].cells[1]
--> -->
<table id="status-table" class="table table-bordered col-sm-12 col-md-6"> <table id="status-table" class="table table-bordered col-sm-12 col-md-6">
<tr>
<td>Igniter</td>
<td></td>
</tr>
<tr>
<td>Exhaust</td>
<td></td>
</tr>
<tr> <tr>
<td>Auger</td> <td>Auger</td>
<td></td> <td></td>
<td>On Time</td>
<td></td>
</tr> </tr>
<tr> <tr>
<td>Feed Rate</td> <td>Feed Rate</td>
<td></td> <td></td>
<td>Off Time</td>
<td></td>
</tr> </tr>
</table> </table>
</div> </div>
@ -53,27 +47,15 @@
<form action="/" method="post"> <form action="/" method="post">
<!-- Start | Shutdown | Reload Settings --> <!-- Start | Shutdown | Reload Settings -->
<div class="button-container d-flex justify-content-between"> <div class="button-container d-flex justify-content-between">
<input class="btn btn-outline-secondary" type="submit" id="igniter-off" value="Disable Igniter" name="igniterOff"> <input class="btn btn-outline-secondary" type="submit" id="ignite" value="Enable Auger" name="start">
<input class="btn btn-outline-secondary" type="submit" id="igniter-on" value="Enable Igniter" name="igniterOn"> <input class="btn btn-outline-secondary" type="submit" id="shutdown" value="Disable Auger" name="shutdown">
</div> </div>
<div class="button-container d-flex justify-content-between">
<input class="btn btn-outline-secondary" type="submit" id="exhaust-off" value="Disable Exhaust" name="exhaustOff">
<input class="btn btn-outline-secondary" type="submit" id="exhaust-on" value="Enable Exhaust" name="exhaustOn">
</div>
<div class="button-container d-flex justify-content-between">
<input class="btn btn-outline-secondary" type="submit" id="auger-off" value="Disable Auger" name="augerOff">
<input class="btn btn-outline-secondary" type="submit" id="auger-on" value="Enable Auger" name="augerOn">
</div>
<!-- Set feed rates --> <!-- Set feed rates -->
<div class="form-group"> <div class="form-group">
<label for="feedRate">Feed Rate: </label> <label for="feedRate">Feed Rate: </label>
<select name="feedRate" class="form-control" id="feed-rate-select"> <select name="feedRate" class="form-control" id="feed-rate-select">
<option value="500">Low</option> <option value="600">Low</option>
<option value="625">Medium-Low</option> <option value="800">Medium</option>
<option value="750">Medium</option>
<option value="875">Medium-High</option>
<option value="1000">High</option> <option value="1000">High</option>
</select> </select>
</div> </div>
@ -82,12 +64,12 @@
</div> </div>
</form> </form>
</div> </div>
<div class="text-center my-4"> <!-- <div class="text-center my-4">
<img src="./dancing_jesus.gif" class="img-fluid"> <img src="./dancing_jesus.gif" class="img-fluid">
</div> </div> -->
<div class="controls-container"> <div class="controls-container">
<form action="/" method="POST"> <form action="/" method="POST">
<input class="btn btn-danger" type="submit" id="quit" value="Quit!!" name="quit"> <input class="btn btn-danger" type="submit" id="quit" value="Quit!!" name="quit" style="visibility: hidden;">
</form> </form>
</div> </div>
<!-- <script src="./main.js"></script> --> <!-- <script src="./main.js"></script> -->
@ -131,38 +113,30 @@
// Get the elements we need to update // Get the elements we need to update
const statusTable = document.getElementById('status-table'); const statusTable = document.getElementById('status-table');
const igniterStatus = statusTable.rows[0].cells[1]; const augerStatus = statusTable.rows[0].cells[1];
const exhaustStatus = statusTable.rows[1].cells[1]; const augerOn = statusTable.rows[0].cells[3];
const augerStatus = statusTable.rows[2].cells[1]; const augerOff = statusTable.rows[1].cells[3];
const feedRate = statusTable.rows[3].cells[1]; const feedRate = statusTable.rows[1].cells[1];
const feedRateSelect = document.getElementById('feed-rate-select'); const feedRateSelect = document.getElementById('feed-rate-select');
// console.log(config); // console.log(config);
igniterStatus.innerHTML = parseStatus(config.status.igniter);
exhaustStatus.innerHTML = parseStatus(config.status.exhaust);
augerStatus.innerHTML = parseStatus(config.status.auger); augerStatus.innerHTML = parseStatus(config.status.auger);
augerOn.innerHTML = config.intervals.augerOn;
augerOff.innerHTML = config.intervals.augerOff;
switch (config.intervals.augerOn) { switch (config.intervals.augerOn) {
case '500': case '600':
feedRate.innerHTML = 'Low'; feedRate.innerHTML = 'Low';
feedRateSelect.selectedIndex = 0; feedRateSelect.selectedIndex = 0;
break; break;
case '625': case '800':
feedRate.innerHTML = 'Medium-Low';
feedRateSelect.selectedIndex = 1;
break;
case '750':
feedRate.innerHTML = 'Medium'; feedRate.innerHTML = 'Medium';
feedRateSelect.selectedIndex = 2; feedRateSelect.selectedIndex = 1;
break;
case '875':
feedRate.innerHTML = 'Medium-High';
feedRateSelect.selectedIndex = 3;
break; break;
case '1000': case '1000':
feedRate.innerHTML = 'High'; feedRate.innerHTML = 'High';
feedRateSelect.selectedIndex = 4; feedRateSelect.selectedIndex = 2;
break; break;
default: default:
feedRate.innerHTML = 'Unknown'; feedRate.innerHTML = 'Unknown';