1
0
mirror of https://github.com/node-red/node-red-nodes.git synced 2023-10-10 13:36:58 +02:00

Added pulse-out node

This commit is contained in:
Maxwell Hadley 2014-02-27 18:33:14 +00:00
parent e8df573ea3
commit 65a0c9336f
2 changed files with 203 additions and 8 deletions

View File

@ -91,7 +91,7 @@ Discrete input for the Beaglebone Black. Sends a message with payload 0 or 1 on
first output when the pin changes state, and logs the total time in the active state.
</p>
<p>
The node sends a message with a payload of the current total active time
Sends a message with a payload of the current total active time
(in seconds) on the second output at selectable intervals. An input message with topic 'load'
and a numeric payload will set the total active time to that value: any other input message
will reset it to zero.
@ -207,8 +207,8 @@ press. When using buttons or switches, enable debouncing to improve reliability.
<!-- Help text for pulse-in -->
<script type="text/x-red" data-help-name="pulse-in">
<p>
Pulse input for the Beaglebone Black. Counts input pulses or pulse edges, outputs
the total counts and the rate of counts/second, each with scaling applied.
Pulse input for the Beaglebone Black. Counts input pulses or pulse edges: outputs
total counts and the rate of counts/sec, with scaling.
</p>
<p>
Sends the total count message on the first output, and the current count
@ -311,17 +311,17 @@ any other input message will reset it to zero.
<!-- Help text for discrete-out -->
<script type="text/x-red" data-help-name="discrete-out">
<p>
Discrete output for the Beaglebone Black.
Directly control an output pin on the Beaglebone Black.
</p>
<p>
Sets the output pin high or low depending on the payload of the input message. Numeric
payloads > 0.5 are 'high', payloads <= 0.5 are 'low'. Other payloads which
payloads > 0.5 are 'high' (1), payloads <= 0.5 are 'low' (0). Other payloads which
evaluate to true are 'high', if not then 'low'. Selecting the Inverting checkbox will
switch the sense of the comparison.
switch the sense of the pin output.
</p>
<p>
If the Toggle state checkbox is checked, any message will cause the pin to switch from
1 to 0 and back.
If the Toggle state checkbox is checked, the message content is ignored: successive
messages cause the pin to toggle between 0 and 1.
</P>
<p>
The pin will be initially set to the given Startup state until the first message arrives:
@ -352,3 +352,116 @@ the Inverting property is not applied to this value.
}
});
</script>
<!-- Edit dialog for pulse-out -->
<script type="text/x-red" data-template-name="pulse-out">
<div class="form-row">
<label for="node-input-pin"><i class="icon-asterisk"></i>Output pin</label>
<select type="text" id="node-input-pin" style="width: 200px;">
<option value="">select pin</option>
<option value="P8_7">GPIO2_2 (P8 pin 7)</option>
<option value="P8_8">GPIO2_3 (P8 pin 8)</option>
<option value="P8_9">GPIO2_5 (P8 pin 9)</option>
<option value="P8_10">GPIO2_4 (P8 pin 10)</option>
<option value="P8_11">GPIO1_13 (P8 pin 11)</option>
<option value="P8_12">GPIO1_12 (P8 pin 12)</option>
<option value="P8_13">GPIO0_23 (P8 pin 13)</option>
<option value="P8_14">GPIO0_26 (P8 pin 14)</option>
<option value="P8_15">GPIO1_15 (P8 pin 15)</option>
<option value="P8_16">GPIO1_14 (P8 pin 16)</option>
<option value="P8_17">GPIO0_27 (P8 pin 17)</option>
<option value="P8_18">GPIO2_1 (P8 pin 18)</option>
<option value="P8_19">GPIO0_22 (P8 pin 19)</option>
<option value="P8_26">GPIO1_29 (P8 pin 26)</option>
<option value="P9_11">GPIO0_30 (P9 pin 11)</option>
<option value="P9_12">GPIO1_28 (P9 pin 12)</option>
<option value="P9_13">GPIO0_31 (P9 pin 13)</option>
<option value="P9_14">GPIO1_18 (P9 pin 14)</option>
<option value="P9_15">GPIO1_16 (P9 pin 15)</option>
<option value="P9_16">GPIO1_19 (P9 pin 16)</option>
<option value="P9_17">GPIO0_5 (P9 pin 17)</option>
<option value="P9_18">GPIO0_4 (P9 pin 18)</option>
<option value="P9_21">GPIO0_3 (P9 pin 21)</option>
<option value="P9_22">GPIO0_2 (P9 pin 22)</option>
<option value="P9_23">GPIO1_17 (P9 pin 23)</option>
<option value="P9_24">GPIO0_15 (P9 pin 24)</option>
<option value="P9_26">GPIO0_14 (P9 pin 26)</option>
<option value="P9_27">GPIO3_19 (P9 pin 27)</option>
<option value="P9_30">GPIO3_16 (P9 pin 30)</option>
<option value="P9_41">GPIO0_20 (P9 pin 41)</option>
<option value="P9_42">GPIO0_7 (P9 pin 42)</option>
<option value="USR0">User LED 0</option>
<option value="USR1">User LED 1</option>
<option value="USR2">User LED 2</option>
<option value="USR3">User LED 3</option>
</select>
</div>
<div class="form-row">
<label for="node-input-pulseTime"><i class="icon-repeat"></i> Pulse time</label>
<input id="node-input-pulseTime" type="text" style="width: 65px">
<label> seconds</label>
</div>
<div class="form-row">
<label for="node-input-retriggerable">Retriggerable</label>
<input type="checkbox" id="node-input-retriggerable" style="display:inline-block; width:auto; vertical-align:top;">
</div>
<div class="form-row">
<label for="node-input-pulseState">Pulse state</label>
<select type="text" id="node-input-pulseState" style="width: 80px;">
<option value="0">0</option>
<option value="1">1</option>
</select>
</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>
<!-- Help text for pulse-out -->
<script type="text/x-red" data-help-name="pulse-out">
<p>
Pulse an output pin on the Beaglebone Black.
</p>
<p>
Pulses the output pin for the set time after receiving an input message, unless the
message has a topic including the text 'time' and a numeric payload. In this case, the
the pulse time will be the value of the payload in seconds. If the time from either
source is < 0.001 seconds, no pulse is generated.
</p>
<p>
In retriggerable mode, a second message within the pulse period will extend the duration
of the pulse by the time value: in non-retriggerable mode, input messages arriving during
the duration of the pulse are ignored.
</p>
<p>
The pin state of the pulse may be set to either 0 or 1: the output pin will switch
back to the other state after the pulse time. An output message is generated each time
the pin changes state: its payload is the new state (0 or 1).
</p>
</script>
<!-- Register pulse-out -->
<script type="text/javascript">
RED.nodes.registerType('pulse-out', {
category: 'advanced-input', // the palette category
color:"#c6dbef",
defaults: { // defines the editable properties of the node
pin: { value:"", required:true },
pulseTime: { value:1, required:true, validate:RED.validators.number() },
retriggerable: { value:false, required:true },
pulseState: { value:"1", required:true },
name: { value:"" }
},
inputs:1, // set the number of inputs - only 0 or 1
outputs:1, // set the number of outputs - 0 to n
icon: "arrow-out.png", // set the icon (held in public/icons)
label: function() { // sets the default label contents
return this.name || "pulse-out: " + this.pin;
},
labelStyle: function() { // sets the class to apply to the label
return this.name ? "node_label_italic" : "";
}
});
</script>

View File

@ -340,10 +340,85 @@ function DiscreteOutputNode(n) {
}
}
// Node constructor for pulse-out
function PulseOutputNode(n) {
RED.nodes.createNode(this, n);
// Store local copies of the node configuration (as defined in the .html)
this.topic = n.topic; // the topic is not currently used
this.pin = n.pin; // The Beaglebone Black pin identifying string
this.pulseState = Number(n.pulseState); // What state the pulse will be..
this.defaultState = this.pulseState === 1 ? 0 : 1;
this.retriggerable = n.retriggerable;
this.pulseTime = n.pulseTime * 1000; // Pulse width in milliseconds
// Working variables
this.pulseTimer = null; // Non-null while a pulse is being generated
var node = this;
// Generate a pulse in response to an input message. If the topic includes the text
// 'time' (case insensitive) and the payload is numeric, use this value as the
// pulse time. Otherwise use the value from the properties dialog.
// If the resulting pulse time is < 1ms, do nothing.
// If the pulse mode is not retriggerable, then if no pulseTimer is active, generate
// a pulse. If the pulse mode is retriggerable, and a pulseTimer is active, cancel it.
// If no timer is active, set the pulse output. In both cases schedule a new pulse
// timer.
var inputCallback = function (msg) {
var time = node.pulseTime;
if (String(msg.topic).search(/time/i) >= 0 && isFinite(msg.payload)) {
time = msg.payload * 1000;
}
if (time >= 1) {
if (node.retriggerable === false) {
if (node.pulseTimer === null) {
node.pulseTimer = setTimeout(endPulseCallback, time);
bonescript.digitalWrite(node.pin, node.pulseState);
node.send({ topic:node.topic, payload:node.pulseState });
}
} else {
if (node.pulseTimer !== null) {
clearTimeout(node.pulseTimer);
} else {
bonescript.digitalWrite(node.pin, node.pulseState);
node.send({ topic:node.topic, payload:node.pulseState });
}
node.pulseTimer = setTimeout(endPulseCallback, time);
}
}
};
// At the end of the pulse, restore the default state and set the timer to null
var endPulseCallback = function () {
node.pulseTimer = null;
bonescript.digitalWrite(node.pin, node.defaultState);
node.send({ topic:node.topic, payload:node.defaultState });
};
// If we have a valid pin, set it as an output and set the default state
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
"P9_27", "P9_30", "P9_41", "P9_42", "USR0", "USR1", "USR2", "USR3"].indexOf(node.pin) >= 0) {
// Don't set up interrupts & intervals until after the close event handler has been installed
bonescript.detachInterrupt(node.pin);
process.nextTick(function () {
bonescript.pinMode(node.pin, bonescript.OUTPUT);
node.on("input", inputCallback);
// Set the pin to the default stte once the dust settles
setTimeout(endPulseCallback, 50);
});
} else {
node.error("Unconfigured output pin");
}
}
// Register the nodes by name. This must be called before overriding any of the Node functions.
RED.nodes.registerType("discrete-in", DiscreteInputNode);
RED.nodes.registerType("pulse-in", PulseInputNode);
RED.nodes.registerType("discrete-out", DiscreteOutputNode);
RED.nodes.registerType("pulse-out", PulseOutputNode);
// On close, detach the interrupt (if we attached one) and clear any active timers
DiscreteInputNode.prototype.close = function () {
@ -367,3 +442,10 @@ PulseInputNode.prototype.close = function () {
clearInterval(this.intervalId);
}
};
// On close, clear an active pulse timer
PulseOutputNode.prototype.close = function () {
if (this.pulseTimer !== null) {
clearTimeout(this.pulseTimer);
}
};