Add warning to Arduino node (as underlying firmata won't allow pins to be both inputas and outputs at the same time)

This commit is contained in:
Dave C-J 2013-10-16 19:04:32 +01:00
parent f3ec90eee0
commit f3040ae95c
2 changed files with 166 additions and 154 deletions

View File

@ -1,12 +1,12 @@
<!-- <!--
Copyright 2013 IBM Corp. Copyright 2013 IBM Corp.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -14,7 +14,7 @@
limitations under the License. limitations under the License.
--> -->
<script type="text/x-red" data-template-name="arduino in"> <script type="text/x-red" data-template-name="arduino in">
<div class="form-row"> <div class="form-row">
<label for="node-input-arduino"><i class="icon-tasks"></i> Arduino</label> <label for="node-input-arduino"><i class="icon-tasks"></i> Arduino</label>
<input type="text" id="node-input-arduino"> <input type="text" id="node-input-arduino">
</div> </div>
@ -33,13 +33,14 @@
<label for="node-input-name"><i class="icon-tag"></i> Name</label> <label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name"> <input type="text" id="node-input-name" placeholder="Name">
</div> </div>
<div class="form-tips"><b>Note:</b> You cannot use the same pin for both output and input.</div>
</script> </script>
<script type="text/x-red" data-help-name="arduino in"> <script type="text/x-red" data-help-name="arduino in">
<p>Arduino input node. Connects to local Arduino and monitors the selected pin for changes. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p> <p>Arduino input node. Connects to local Arduino and monitors the selected pin for changes. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
<p>You can select either Digital or Analogue input. Outputs the value read as <b>msg.payload</b> and the pin number as <b>msg.topic</b>.</p> <p>You can select either Digital or Analogue input. Outputs the value read as <b>msg.payload</b> and the pin number as <b>msg.topic</b>.</p>
<p>It only outputs on a change of value - fine for digital inputs, but you can get a lot of data from analogue pins which you must then handle.</p> <p>It only outputs on a change of value - fine for digital inputs, but you can get a lot of data from analogue pins which you must then handle.</p>
<p>You can set the sample rate in ms from 20 to 65535.</p> <p>You can set the sample rate in ms from 20 to 65535.</p>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
@ -56,8 +57,8 @@
outputs:1, outputs:1,
icon: "arduino.png", icon: "arduino.png",
label: function() { label: function() {
var a = ""; var a = "";
if (this.state == "ANALOG") a = "A"; if (this.state == "ANALOG") a = "A";
return this.name||"Pin: "+a+this.pin; return this.name||"Pin: "+a+this.pin;
}, },
labelStyle: function() { labelStyle: function() {
@ -67,7 +68,7 @@
</script> </script>
<script type="text/x-red" data-template-name="arduino out"> <script type="text/x-red" data-template-name="arduino out">
<div class="form-row"> <div class="form-row">
<label for="node-input-arduino"><i class="icon-tasks"></i> Arduino</label> <label for="node-input-arduino"><i class="icon-tasks"></i> Arduino</label>
<input type="text" id="node-input-arduino"> <input type="text" id="node-input-arduino">
</div> </div>
@ -87,11 +88,12 @@
<label for="node-input-name"><i class="icon-tag"></i> Name</label> <label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name"> <input type="text" id="node-input-name" placeholder="Name">
</div> </div>
<div class="form-tips"><b>Note:</b> You cannot use the same pin for both output and input.</div>
</script> </script>
<script type="text/x-red" data-help-name="arduino out"> <script type="text/x-red" data-help-name="arduino out">
<p>Arduino output node. Connects to local Arduino and writes to the selected digital pin. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p> <p>Arduino output node. Connects to local Arduino and writes to the selected digital pin. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
<p>You can select Digital, Analogue (PWM) or Servo type outputs. Expects a numeric value in <b>msg.payload</b>. The pin number is set in the properties panel.</p> <p>You can select Digital, Analogue (PWM) or Servo type outputs. Expects a numeric value in <b>msg.payload</b>. The pin number is set in the properties panel.</p>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">

View File

@ -19,168 +19,178 @@ var util = require("util");
var firmata = require("firmata"); var firmata = require("firmata");
var arduinoReady = false; var arduinoReady = false;
var thisboard = null; var thisboard = null;
var pins = [];
// The Board Definition - this opens (and closes) the connection // The Board Definition - this opens (and closes) the connection
function ArduinoNode(n) { function ArduinoNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.device = n.device; this.device = n.device;
this.repeat = n.repeat||25; this.repeat = n.repeat||25;
util.log("[firmata] Opening "+this.device); util.log("[firmata] Opening "+this.device);
var node = this; var node = this;
node.toun = setInterval(function() { node.toun = setInterval(function() {
if (!arduinoReady) { if (!arduinoReady) {
if (thisboard == null) { if (thisboard == null) {
node.board = new firmata.Board(node.device, function(err) { node.board = new firmata.Board(node.device, function(err) {
if (err) { if (err) {
console.log("[firmata] error: ",err); util.log("[firmata] error: "+err);
return; return;
} }
arduinoReady = true; arduinoReady = true;
thisboard = node.board; thisboard = node.board;
clearInterval(node.toun); clearInterval(node.toun);
util.log('[firmata] Arduino connected'); util.log('[firmata] Arduino connected');
}); });
} }
else { else {
node.board = thisboard; node.board = thisboard;
node.board.removeAllListeners(); node.board.removeAllListeners();
arduinoReady = true; arduinoReady = true;
clearInterval(node.toun); clearInterval(node.toun);
node.toun = false; node.toun = false;
util.log("[firmata] Arduino already connected"); util.log("[firmata] Arduino already connected");
} }
} else { util.log("[firmata] Waiting for Firmata"); } } else { util.log("[firmata] Waiting for Firmata"); }
}, 10000); // wait for firmata to connect to arduino }, 10000); // wait for firmata to connect to arduino
this.on('close', function() { this.on('close', function() {
//this.board.sp.close(function() { console.log("[firmata] Serial port closed"); arduinoReady = false; }); //this.board.sp.close(function() { console.log("[firmata] Serial port closed"); arduinoReady = false; });
arduinoReady = false; arduinoReady = false;
if (node.toun) { if (node.toun) {
clearInterval(node.toun); clearInterval(node.toun);
util.log("[firmata] arduino wait loop stopped"); util.log("[firmata] arduino wait loop stopped");
} }
util.log("[firmata] Stopped"); util.log("[firmata] Stopped");
}); });
} }
RED.nodes.registerType("arduino-board",ArduinoNode); RED.nodes.registerType("arduino-board",ArduinoNode);
// The Input Node // The Input Node
function DuinoNodeIn(n) { function DuinoNodeIn(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.buttonState = -1; this.buttonState = -1;
this.pin = n.pin; this.pin = n.pin;
this.state = n.state; this.state = n.state;
this.arduino = n.arduino; this.arduino = n.arduino;
this.serverConfig = RED.nodes.getNode(this.arduino); this.serverConfig = RED.nodes.getNode(this.arduino);
if (typeof this.serverConfig === "object") { if (pins.indexOf(this.pin) > -1) {
this.board = this.serverConfig.board; this.error("Arduino pin being used more than once");
this.repeat = this.serverConfig.repeat; }
var node = this; else pins.push(this.pin);
if (typeof this.serverConfig === "object") {
this.board = this.serverConfig.board;
this.repeat = this.serverConfig.repeat;
var node = this;
node.toui = setInterval(function() { node.toui = setInterval(function() {
if (thisboard != null) { if (thisboard != null) {
node.board = thisboard; node.board = thisboard;
clearInterval(node.toui); clearInterval(node.toui);
node.toui = false; node.toui = false;
//console.log(node.state,node.pin,node.board.MODES[node.state]); //console.log("i",node.state,node.pin,node.board.MODES[node.state]);
node.board.pinMode(node.pin, node.board.MODES[node.state]); node.board.pinMode(node.pin, node.board.MODES[node.state]);
node.board.setSamplingInterval(node.repeat); node.board.setSamplingInterval(node.repeat);
var oldrdg = ""; var oldrdg = "";
if (node.state == "ANALOG") { if (node.state == "ANALOG") {
node.board.analogRead(node.pin, function(data) { node.board.analogRead(node.pin, function(data) {
var msg = {payload:data, topic:"A"+node.pin}; var msg = {payload:data, topic:"A"+node.pin};
if (data != oldrdg) { if (data != oldrdg) {
node.send(msg); node.send(msg);
oldrdg = data; oldrdg = data;
} }
}); });
} }
else { else {
node.board.digitalRead(node.pin, function(data) { node.board.digitalRead(node.pin, function(data) {
var msg = {payload:data, topic:node.pin}; var msg = {payload:data, topic:node.pin};
node.send(msg); node.send(msg);
}); });
} }
} }
else { node.log("Waiting for Arduino"); } else { node.log("Waiting for Arduino"); }
}, 5000); // loop to wait for firmata to connect to arduino }, 5000); // loop to wait for firmata to connect to arduino
this.on('close', function() { this.on('close', function() {
if (node.toui) { if (node.toui) {
clearInterval(node.toui); clearInterval(node.toui);
util.log("[firmata] input wait loop stopped"); util.log("[firmata] input wait loop stopped");
} }
}); });
} }
else { else {
util.log("[firmata] Serial Port not Configured"); util.log("[firmata] Serial Port not Configured");
} }
} }
RED.nodes.registerType("arduino in",DuinoNodeIn); RED.nodes.registerType("arduino in",DuinoNodeIn);
// The Output Node // The Output Node
function DuinoNodeOut(n) { function DuinoNodeOut(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.buttonState = -1; this.buttonState = -1;
this.pin = n.pin; this.pin = n.pin;
this.state = n.state; this.state = n.state;
this.arduino = n.arduino; this.arduino = n.arduino;
this.serverConfig = RED.nodes.getNode(this.arduino); if (pins.indexOf(this.pin) > -1) {
if (typeof this.serverConfig === "object") { this.error("Arduino pin being used more than once");
this.board = this.serverConfig.board; }
var node = this; else pins.push(this.pin);
this.serverConfig = RED.nodes.getNode(this.arduino);
if (typeof this.serverConfig === "object") {
this.board = this.serverConfig.board;
var node = this;
this.on("input", function(msg) { this.on("input", function(msg) {
//console.log(msg); //console.log(msg);
if (thisboard != null) { if (node.board != null) {
if (node.state == "OUTPUT") { if (node.state == "OUTPUT") {
if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) { if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) {
node.board.digitalWrite(node.pin, node.board.HIGH); node.board.digitalWrite(node.pin, node.board.HIGH);
} }
if ((msg.payload == false)||(msg.payload == 0)||(msg.payload.toString().toLowerCase() == "off")) { if ((msg.payload == false)||(msg.payload == 0)||(msg.payload.toString().toLowerCase() == "off")) {
node.board.digitalWrite(node.pin, node.board.LOW); node.board.digitalWrite(node.pin, node.board.LOW);
} }
} }
if (node.state == "PWM") { if (node.state == "PWM") {
msg.payload = msg.payload * 1; msg.payload = msg.payload * 1;
if ((msg.payload >= 0) && (msg.payload <= 255)) { if ((msg.payload >= 0) && (msg.payload <= 255)) {
//console.log(msg.payload, node.pin); //console.log(msg.payload, node.pin);
node.board.servoWrite(node.pin, msg.payload); node.board.servoWrite(node.pin, msg.payload);
} }
} }
if (node.state == "SERVO") { if (node.state == "SERVO") {
msg.payload = msg.payload * 1; msg.payload = msg.payload * 1;
if ((msg.payload >= 0) && (msg.payload <= 180)) { if ((msg.payload >= 0) && (msg.payload <= 180)) {
//console.log(msg.payload, node.pin); //console.log(msg.payload, node.pin);
node.board.servoWrite(node.pin, msg.payload); node.board.servoWrite(node.pin, msg.payload);
} }
} }
} }
//else { console.log("Arduino not ready"); } //else { console.log("Arduino not ready"); }
}); });
node.touo = setInterval(function() { node.touo = setInterval(function() {
if (thisboard != null) { if (thisboard != null) {
clearInterval(node.touo); clearInterval(node.touo);
node.touo = false; node.touo = false;
node.board = thisboard; node.board = thisboard;
node.board.pinMode(node.pin, node.board.MODES[node.state]); //console.log("o",node.state,node.pin,node.board.MODES[node.state]);
} node.board.pinMode(node.pin, node.board.MODES[node.state]);
else { util.log("[firmata] waiting for arduino to connect"); } }
}, 5000); // loop to wait for firmata to connect to arduino else { util.log("[firmata] waiting for arduino to connect"); }
}, 5000); // loop to wait for firmata to connect to arduino
this.on('close', function() { this.on('close', function() {
if (node.touo) { if (node.touo) {
clearInterval(node.touo); clearInterval(node.touo);
util.log("[firmata] output wait loop stopped"); util.log("[firmata] output wait loop stopped");
} }
}); });
} }
else { else {
util.log("[firmata] Serial Port not Configured"); util.log("[firmata] Serial Port not Configured");
} }
} }
RED.nodes.registerType("arduino out",DuinoNodeOut); RED.nodes.registerType("arduino out",DuinoNodeOut);