1
0
mirror of https://github.com/node-red/node-red-nodes.git synced 2023-10-10 13:36:58 +02:00
node-red-nodes/hardware/BBB/144-analog-in.html
Maxwell Hadley f46b59d69f Added analogue scaling & averaging; discrete check reads
Added input scaling function and averaging of multiple readings for
noise reduction to the analogue input node.
Added the ‘sanity check’ read of the digital input pin to the timer
callback in the discrete input node
2014-02-12 22:27:08 +00:00

184 lines
9.3 KiB
HTML

<!--
Copyright 2014 Maxwell R Hadley
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Define the edit dialog -->
<script type="text/x-red" data-template-name="analog-in">
<div class="form-row">
<label for="node-input-pin"><i class="icon-asterisk"></i>Input pin</label>
<select type="text" id="node-input-pin" style="width: 150px;">
<option value="">select pin</option>
<option value="P9_39">AIN0 (P9 pin 39)</option>
<option value="P9_40">AIN1 (P9 pin 40)</option>
<option value="P9_37">AIN2 (P9 pin 37)</option>
<option value="P9_38">AIN3 (P9 pin 38)</option>
<option value="P9_33">AIN4 (P9 pin 33)</option>
<option value="P9_36">AIN5 (P9 pin 36)</option>
<option value="P9_35">AIN6 (P9 pin 35)</option>
</select>
</div>
<div class="form-row">
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
<input type="text" id="node-input-topic" placeholder="Topic">
</div>
<div class="form-row">
Input Scaling
</div>
<div class="form-row">
<div id="node-input-breakpoint-container-div" style="border-radius: 5px; height: 132px; padding: 5px; border: 1px solid #ccc; overflow-y:scroll;">
<ol id="node-input-breakpoint-container" style=" list-style-type:none; margin: 0;">
</ol>
</div>
</div>
<div class="form-row">
<a href="#" class="btn btn-mini" id="node-input-add-breakpoint" style="margin-top: 4px;"><i class="icon-plus"></i> Add Breakpoint</a>
<span style="float:right; margin-top:4px">
<input type="checkbox" id="node-input-averaging" style="display:inline-block; width:auto; vertical-align:top;"> Averaging&nbsp;
</span>
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<!-- Add help text -->
<script type="text/x-red" data-help-name="analog-in">
<p>
Analogue input for the Beaglebone Black. Reads an analogue pin when triggered
</p>
<p>The output message topic is the node topic: the output message value is the
scaled analogue input or NaN if a read error occurs.
</p>
<p>
Simple linear scaling is defined by setting the output values required for input
values of 0 and 1. You can apply more complicated scaling, e.g. for sensor linearisation,
by defining breakpoints at intermediate input values, with the desired output for
each. Intermediate values are linearly interpolated.
</p>
<p>
To reduce the effect of noise, enable averaging. This will read the input pin
voltage ten times in rapid succession for each input message and output the mean value.
</p>
</script>
<!-- Register the node -->
<script type="text/javascript">
RED.nodes.registerType('analog-in', {
category: 'advanced-input', // the palette category
color:"#c6dbef",
defaults: { // defines the editable properties of the node
name: { value:"" }, // along with default values.
topic: { value:"", required:true },
pin: { value:"", required:true },
breakpoints: { value:[{input:0.0, output:0.0, mutable:false}, {input:1.0, output:1.0, mutable:false}] },
averaging: { value:false, required:true }
},
inputs:1, // set the number of inputs - only 0 or 1
outputs:1, // set the number of outputs - 0 to n
icon: "arrow-in.png", // set the icon (held in public/icons)
label: function() { // sets the default label contents
return this.name || "analog-in: " + this.pin;
},
labelStyle: function() { // sets the class to apply to the label
return this.name ? "node_label_italic" : "";
},
oneditprepare: function () {
function generateBreakpoint(breakpoint, insert) {
var container = $('<li/>', {style:"margin:0; padding:4px; padding-left 10px;"});
var row = $('<div/>').appendTo(container);
var breakpointField = $('<span/>').appendTo(row);
var inputValueField = $('<input/>',
{disabled:"", class:"node-input-breakpoint-input-value", type:"text", style:"margin-left:5px; margin-right:2px; width:36%;"}).appendTo(breakpointField);
if (breakpoint.mutable) {
inputValueField.removeAttr("disabled");
}
breakpointField.append(" => ");
var outputValueField = $('<input/>',
{class:"node-input-breakpoint-output-value", type:"text", style:"margin-left:0px; width:36%;"}).appendTo(breakpointField);
var finalSpan = $('<span/>', {style:"float:right; margin-top:3px; margin-right:10px;"}).appendTo(row);
var mutableFlag = $('<span/>', {class:"node-input-breakpoint-mutable", style:"display:hide;"}).appendTo(row);
if (breakpoint.mutable) {
mutableFlag.attr("mutable", "true");
var deleteButton = $('<a/>', {href:"#", class:"btn btn-mini", style:"margin-left: 5px;"}).appendTo(finalSpan);
$('<i/>', {class:"icon-remove"}).appendTo(deleteButton);
deleteButton.click(function() {
container.css({"background":"#fee"});
container.fadeOut(300, function() {
$(this).remove();
});
});
} else {
mutableFlag.attr("mutable", "false");
}
if (insert === true) {
var last = $("#node-input-breakpoint-container").children().last();
var prev = last.prev();
inputValueField.val((Number(last.find(".node-input-breakpoint-input-value").val()) +
Number(prev.find(".node-input-breakpoint-input-value").val()))/2);
outputValueField.val((Number(last.find(".node-input-breakpoint-output-value").val()) +
Number(prev.find(".node-input-breakpoint-output-value").val()))/2);
last.before(container);
} else {
inputValueField.val(breakpoint.input);
outputValueField.val(breakpoint.output);
$("#node-input-breakpoint-container").append(container);
}
}
$("#node-input-add-breakpoint").click(function () {
generateBreakpoint({input:0, output:0, mutable:true}, true);
$("#node-input-breakpoint-container-div").scrollTop($("#node-input-breakpoint-container-div").get(0).scrollHeight);
});
for (var i = 0; i < this.breakpoints.length; i++) {
var breakpoint = this.breakpoints[i];
generateBreakpoint(breakpoint, false);
}
// Handle resizing the Input Scaling div when the dialog is resized - this isn't quite right!
function switchDialogResize(ev, ui) {
$("#node-input-breakpoint-container-div").css("height", (ui.size.height - 299) + "px");
};
$("#dialog").on("dialogresize", switchDialogResize);
$("#dialog").one("dialogopen", function (ev) {
var size = $("#dialog").dialog('option', 'sizeCache-switch');
if (size) {
switchDialogResize(null, { size:size });
}
});
$("#dialog").one("dialogclose", function(ev, ui) {
$("#dialog").off("dialogresize", switchDialogResize);
});
},
oneditsave: function() {
var breakpoints = $("#node-input-breakpoint-container").children();
var node = this;
node.breakpoints = [];
breakpoints.each(function (i) {
var breakpoint = $(this);
var r = {};
r.input = Number(breakpoint.find(".node-input-breakpoint-input-value").val());
r.output = Number(breakpoint.find(".node-input-breakpoint-output-value").val());
r.mutable = breakpoint.find(".node-input-breakpoint-mutable").attr("mutable") == "true";
node.breakpoints.push(r);
});
node.breakpoints = node.breakpoints.sort(function (a, b) { return a.input - b.input; });
}
});
</script>