mirror of
https://github.com/node-red/node-red-nodes.git
synced 2023-10-10 13:36:58 +02:00
f46b59d69f
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
184 lines
9.3 KiB
HTML
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
|
|
</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>
|