mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
New Pi GPIO node based on RPI.GPIO library.
Adds PWM support of outputs and easier access to interrupts for inputs.
This commit is contained in:
parent
b4dc66944a
commit
9e4187d6a8
@ -45,7 +45,6 @@
|
|||||||
<option value="tri">none</option>
|
<option value="tri">none</option>
|
||||||
<option value="up">pullup</option>
|
<option value="up">pullup</option>
|
||||||
<option value="down">pulldown</option>
|
<option value="down">pulldown</option>
|
||||||
<!--<option value="tri">tristate</option>-->
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
@ -63,11 +62,11 @@
|
|||||||
|
|
||||||
<script type="text/x-red" data-help-name="rpi-gpio in">
|
<script type="text/x-red" data-help-name="rpi-gpio in">
|
||||||
<p>Raspberry Pi input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin. Requires the gpio command to work.</p>
|
<p>Raspberry Pi input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin. Requires the gpio command to work.</p>
|
||||||
<p>You may also enable the input pullup resitor or the pulldown resistor.</p>
|
<p>You may also enable the input pullup resistor or the pulldown resistor.</p>
|
||||||
<p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p>
|
<p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p>
|
||||||
|
<p>Requires the RPi.GPIO python library version 0.5.8 (or better) in order to work.</p>
|
||||||
<p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
|
<p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
|
||||||
<p><b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu.</p>
|
</script>
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
RED.nodes.registerType('rpi-gpio in',{
|
RED.nodes.registerType('rpi-gpio in',{
|
||||||
@ -90,6 +89,7 @@
|
|||||||
},
|
},
|
||||||
oneditprepare: function() {
|
oneditprepare: function() {
|
||||||
var pinnow = this.pin;
|
var pinnow = this.pin;
|
||||||
|
var pinsInUse = {};
|
||||||
$.getJSON('rpi-gpio/'+this.id,function(data) {
|
$.getJSON('rpi-gpio/'+this.id,function(data) {
|
||||||
$('#pitype').text(data.type);
|
$('#pitype').text(data.type);
|
||||||
if ((data.type === "Model B+") || (data.type === "Model A+")) {
|
if ((data.type === "Model B+") || (data.type === "Model A+")) {
|
||||||
@ -107,11 +107,31 @@
|
|||||||
$('#node-input-pin').val(pinnow);
|
$('#node-input-pin').val(pinnow);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$.getJSON('rpi-pins/'+this.id,function(data) {
|
||||||
|
pinsInUse = data || {};
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#node-input-pin").change(function() {
|
||||||
|
var pinnew = $("#node-input-pin").val();
|
||||||
|
if ((pinnew) && (pinnew !== pinnow)) {
|
||||||
|
if (pinsInUse.hasOwnProperty(pinnew)) {
|
||||||
|
RED.notify("Pin "+pinnew+" already in use.","info");
|
||||||
|
}
|
||||||
|
pinnow = pinnew;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#node-input-intype").change(function() {
|
||||||
|
var newtype = $("#node-input-intype option:selected").val();
|
||||||
|
if ((pinsInUse.hasOwnProperty(pinnow)) && (pinsInUse[pinnow] !== newtype)) {
|
||||||
|
RED.notify("Pin "+pinnow+" already set as "+pinsInUse[pinnow],"error");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<script type="text/x-red" data-template-name="rpi-gpio out">
|
<script type="text/x-red" data-template-name="rpi-gpio out">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
|
<label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
|
||||||
@ -123,7 +143,7 @@
|
|||||||
<option value="8">8 - TxD </option>
|
<option value="8">8 - TxD </option>
|
||||||
<option value="10">10 - RxD </option>
|
<option value="10">10 - RxD </option>
|
||||||
<option value="11">11 - GPIO0</option>
|
<option value="11">11 - GPIO0</option>
|
||||||
<option value="12">12 - GPIO1 (PWM)</option>
|
<option value="12">12 - GPIO1</option>
|
||||||
<option value="13">13 - GPIO2</option>
|
<option value="13">13 - GPIO2</option>
|
||||||
<option value="15">15 - GPIO3</option>
|
<option value="15">15 - GPIO3</option>
|
||||||
<option value="16">16 - GPIO4</option>
|
<option value="16">16 - GPIO4</option>
|
||||||
@ -169,7 +189,8 @@
|
|||||||
<p>Raspberry Pi output node. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false). Requires the gpio command to work.</p>
|
<p>Raspberry Pi output node. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false). Requires the gpio command to work.</p>
|
||||||
<p>Will set the selected physical pin high or low depending on the value passed in.</p>
|
<p>Will set the selected physical pin high or low depending on the value passed in.</p>
|
||||||
<p>The initial value of the pin at deploy time can also be set to 0 or 1.</p>
|
<p>The initial value of the pin at deploy time can also be set to 0 or 1.</p>
|
||||||
<p>Use of PWM on Pin 12 - GPIO1 will interfere with any other audio playback.</p>
|
<p>When using PWM mode - expects an input value of a number 0 - 100.</p>
|
||||||
|
<p>Requires the RPi.GPIO python library version 0.5.8 (or better) in order to work.</p>
|
||||||
<p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
|
<p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -189,7 +210,7 @@
|
|||||||
icon: "rpi.png",
|
icon: "rpi.png",
|
||||||
align: "right",
|
align: "right",
|
||||||
label: function() {
|
label: function() {
|
||||||
if ((this.pin == 12) && (this.out === "pwm")) { return this.name || "PWM: 12"; }
|
if (this.out === "pwm") { return this.name || "PWM: "+this.pin; }
|
||||||
else { return this.name||"Pin: "+this.pin ; }
|
else { return this.name||"Pin: "+this.pin ; }
|
||||||
},
|
},
|
||||||
labelStyle: function() {
|
labelStyle: function() {
|
||||||
@ -197,6 +218,7 @@
|
|||||||
},
|
},
|
||||||
oneditprepare: function() {
|
oneditprepare: function() {
|
||||||
var pinnow = this.pin;
|
var pinnow = this.pin;
|
||||||
|
var pinsInUse = {};
|
||||||
if (!$("#node-input-out").val()) { $("#node-input-out").val("out"); }
|
if (!$("#node-input-out").val()) { $("#node-input-out").val("out"); }
|
||||||
$.getJSON('rpi-gpio/'+this.id,function(data) {
|
$.getJSON('rpi-gpio/'+this.id,function(data) {
|
||||||
$('#pitype').text(data.type);
|
$('#pitype').text(data.type);
|
||||||
@ -216,17 +238,26 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var hidepwm = function() {
|
$.getJSON('rpi-pins/'+this.id,function(data) {
|
||||||
if ($('#node-input-pin').val() == 12) {
|
pinsInUse = data || {};
|
||||||
$('#node-set-pwm').show();
|
});
|
||||||
|
|
||||||
|
$("#node-input-pin").change(function() {
|
||||||
|
var pinnew = $("#node-input-pin").val();
|
||||||
|
if ((pinnew) && (pinnew !== pinnow)) {
|
||||||
|
if (pinsInUse.hasOwnProperty(pinnew)) {
|
||||||
|
RED.notify("Pin "+pinnew+" already in use.","info");
|
||||||
|
}
|
||||||
|
pinnow = pinnew;
|
||||||
}
|
}
|
||||||
else {
|
});
|
||||||
$('#node-set-pwm').hide();
|
|
||||||
$('#node-input-out').val("out");
|
$("#node-input-out").change(function() {
|
||||||
|
var newtype = $("#node-input-out option:selected").val();
|
||||||
|
if ((pinsInUse.hasOwnProperty(pinnow)) && (pinsInUse[pinnow] !== newtype)) {
|
||||||
|
RED.notify("Pin "+pinnow+" already set as "+pinsInUse[pinnow],"error");
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
$("#node-input-pin").change(function () { hidepwm(); });
|
|
||||||
hidepwm();
|
|
||||||
|
|
||||||
var hidestate = function () {
|
var hidestate = function () {
|
||||||
if ($("#node-input-out").val() === "pwm") {
|
if ($("#node-input-out").val() === "pwm") {
|
||||||
|
@ -18,179 +18,202 @@ module.exports = function(RED) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
var util = require("util");
|
var util = require("util");
|
||||||
var exec = require('child_process').exec;
|
var exec = require('child_process').exec;
|
||||||
|
var spawn = require('child_process').spawn;
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
var gpioCommand = '/usr/local/bin/gpio';
|
var gpioCommand = __dirname+'/nrgpio';
|
||||||
|
|
||||||
if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
|
if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
|
||||||
|
//util.log("Info : Ignoring Raspberry Pi specific node.");
|
||||||
throw "Info : Ignoring Raspberry Pi specific node.";
|
throw "Info : Ignoring Raspberry Pi specific node.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fs.existsSync(gpioCommand)) { // gpio command not installed
|
if (!fs.existsSync("/usr/share/doc/python-rpi.gpio")) {
|
||||||
throw "Info : Can't find Raspberry Pi wiringPi gpio command.";
|
util.log("[rpi-gpio] Info : Can't find Pi RPi.GPIO python library.");
|
||||||
|
throw "Warning : Can't find Pi RPi.GPIO python library.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant)
|
if ( !(1 & parseInt ((fs.statSync(gpioCommand).mode & parseInt ("777", 8)).toString (8)[0]) )) {
|
||||||
var pintable = {
|
util.log("[rpi-gpio] Error : "+gpioCommand+" needs to be executable.");
|
||||||
// Physical : WiringPi
|
throw "Error : nrgpio must to be executable.";
|
||||||
"11":"0",
|
|
||||||
"12":"1",
|
|
||||||
"13":"2",
|
|
||||||
"15":"3",
|
|
||||||
"16":"4",
|
|
||||||
"18":"5",
|
|
||||||
"22":"6",
|
|
||||||
"7":"7",
|
|
||||||
"3":"8",
|
|
||||||
"5":"9",
|
|
||||||
"24":"10",
|
|
||||||
"26":"11",
|
|
||||||
"19":"12",
|
|
||||||
"21":"13",
|
|
||||||
"23":"14",
|
|
||||||
"8":"15",
|
|
||||||
"10":"16",
|
|
||||||
"27":"30",
|
|
||||||
"28":"31",
|
|
||||||
"29":"21",
|
|
||||||
"31":"22",
|
|
||||||
"32":"26",
|
|
||||||
"33":"23",
|
|
||||||
"35":"24",
|
|
||||||
"36":"27",
|
|
||||||
"37":"25",
|
|
||||||
"38":"28",
|
|
||||||
"40":"29"
|
|
||||||
}
|
|
||||||
var tablepin = {
|
|
||||||
// WiringPi : Physical
|
|
||||||
"0":"11",
|
|
||||||
"1":"12",
|
|
||||||
"2":"13",
|
|
||||||
"3":"15",
|
|
||||||
"4":"16",
|
|
||||||
"5":"18",
|
|
||||||
"6":"22",
|
|
||||||
"7":"7",
|
|
||||||
"8":"3",
|
|
||||||
"9":"5",
|
|
||||||
"10":"24",
|
|
||||||
"11":"26",
|
|
||||||
"12":"19",
|
|
||||||
"13":"21",
|
|
||||||
"14":"23",
|
|
||||||
"15":"8",
|
|
||||||
"16":"10",
|
|
||||||
"30":"27",
|
|
||||||
"31":"28",
|
|
||||||
"21":"29",
|
|
||||||
"22":"31",
|
|
||||||
"26":"32",
|
|
||||||
"23":"33",
|
|
||||||
"24":"35",
|
|
||||||
"27":"36",
|
|
||||||
"25":"37",
|
|
||||||
"28":"38",
|
|
||||||
"29":"40"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pinsInUse = {};
|
||||||
|
var pinTypes = {"out":"digital output", "tri":"input", "up":"input with pull up", "down":"input with pull down", "pwm":"PWM output"};
|
||||||
|
|
||||||
function GPIOInNode(n) {
|
function GPIOInNode(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
this.buttonState = -1;
|
this.buttonState = -1;
|
||||||
this.pin = pintable[n.pin];
|
this.pin = n.pin;
|
||||||
this.intype = n.intype;
|
this.intype = n.intype;
|
||||||
this.read = n.read || false;
|
this.read = n.read || false;
|
||||||
if (this.read) { this.buttonState = -2; }
|
if (this.read) { this.buttonState = -2; }
|
||||||
var node = this;
|
var node = this;
|
||||||
|
if (!pinsInUse.hasOwnProperty(this.pin)) {
|
||||||
|
pinsInUse[this.pin] = this.intype;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((pinsInUse[this.pin] !== this.intype)||(pinsInUse[this.pin] === "pwm")) {
|
||||||
|
node.error("GPIO pin "+this.pin+" already set as "+pinTypes[pinsInUse[this.pin]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (node.pin !== undefined) {
|
if (node.pin !== undefined) {
|
||||||
exec(gpioCommand+" mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
|
if (node.intype === "tri") {
|
||||||
if (err) { node.error(err); }
|
node.child = spawn(gpioCommand, ["in",node.pin]);
|
||||||
else {
|
} else {
|
||||||
node._interval = setInterval( function() {
|
node.child = spawn(gpioCommand, ["in",node.pin,node.intype]);
|
||||||
exec(gpioCommand+" read "+node.pin, function(err,stdout,stderr) {
|
}
|
||||||
if (err) { node.error(err); }
|
node.running = true;
|
||||||
else {
|
node.status({fill:"green",shape:"dot",text:"OK"});
|
||||||
if (node.buttonState !== Number(stdout)) {
|
|
||||||
var previousState = node.buttonState;
|
node.child.stdout.on('data', function (data) {
|
||||||
node.buttonState = Number(stdout);
|
data = data.toString().trim();
|
||||||
if (previousState !== -1) {
|
if (data.length > 0) {
|
||||||
var msg = {topic:"pi/"+tablepin[node.pin], payload:node.buttonState};
|
if (node.buttonState !== -1) {
|
||||||
node.send(msg);
|
node.send({ topic:"pi/"+node.pin, payload:Number(data) });
|
||||||
}
|
}
|
||||||
}
|
node.buttonState = data;
|
||||||
}
|
node.status({fill:"green",shape:"dot",text:data});
|
||||||
});
|
if (RED.settings.verbose) { node.log("out: "+data+" :"); }
|
||||||
}, 250);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
node.child.stderr.on('data', function (data) {
|
||||||
|
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('close', function (code) {
|
||||||
|
if (RED.settings.verbose) { node.log("ret: "+code+" :"); }
|
||||||
|
node.child = null;
|
||||||
|
node.running = false;
|
||||||
|
node.status({fill:"red",shape:"circle",text:""});
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('error', function (err) {
|
||||||
|
if (err.errno === "ENOENT") { node.warn('Command not found'); }
|
||||||
|
else if (err.errno === "EACCES") { node.warn('Command not executable'); }
|
||||||
|
else { node.log('error: ' + err); }
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
node.error("Invalid GPIO pin: "+node.pin);
|
node.error("Invalid GPIO pin: "+node.pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.on("close", function() {
|
node.on("close", function() {
|
||||||
clearInterval(node._interval);
|
if (node.child != null) {
|
||||||
|
node.child.stdin.write(" close "+node.pin);
|
||||||
|
node.child.kill('SIGKILL');
|
||||||
|
}
|
||||||
|
node.status({fill:"red",shape:"circle",text:""});
|
||||||
|
delete pinsInUse[node.pin];
|
||||||
|
if (RED.settings.verbose) { node.log("end"); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
RED.nodes.registerType("rpi-gpio in",GPIOInNode);
|
||||||
|
|
||||||
|
|
||||||
function GPIOOutNode(n) {
|
function GPIOOutNode(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
this.pin = pintable[n.pin];
|
this.pin = n.pin;
|
||||||
this.set = n.set || false;
|
this.set = n.set || false;
|
||||||
this.level = n.level || 0;
|
this.level = n.level || 0;
|
||||||
this.out = n.out || "out";
|
this.out = n.out || "out";
|
||||||
var node = this;
|
var node = this;
|
||||||
(node.out === "pwm") ? (node.op = "pwm") : (node.op = "write");
|
if (!pinsInUse.hasOwnProperty(this.pin)) {
|
||||||
|
pinsInUse[this.pin] = this.out;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((pinsInUse[this.pin] !== this.out)||(pinsInUse[this.pin] === "pwm")) {
|
||||||
|
node.error("GPIO pin "+this.pin+" already set as "+pinTypes[pinsInUse[this.pin]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inputlistener(msg) {
|
||||||
|
if (msg.payload === "true") { msg.payload = true; }
|
||||||
|
if (msg.payload === "false") { msg.payload = false; }
|
||||||
|
var out = Number(msg.payload);
|
||||||
|
var limit = 1;
|
||||||
|
if (node.out === "pwm") { limit = 100; }
|
||||||
|
if ((out >= 0) && (out <= limit)) {
|
||||||
|
if (RED.settings.verbose) { node.log("inp: "+msg.payload); }
|
||||||
|
if (node.child !== null) { node.child.stdin.write(msg.payload+"\n"); }
|
||||||
|
else { node.warn("Command not running"); }
|
||||||
|
node.status({fill:"green",shape:"dot",text:msg.payload});
|
||||||
|
}
|
||||||
|
else { node.warn("Invalid input: "+out); }
|
||||||
|
}
|
||||||
|
|
||||||
if (node.pin !== undefined) {
|
if (node.pin !== undefined) {
|
||||||
exec(gpioCommand+" mode "+node.pin+" "+node.out, function(err,stdout,stderr) {
|
if (node.set && (node.out === "out")) {
|
||||||
if (err) { node.error(err); }
|
node.child = spawn(gpioCommand, [node.out,node.pin,node.level]);
|
||||||
else {
|
} else {
|
||||||
if (node.set && (node.out === "out")) {
|
node.child = spawn(gpioCommand, [node.out,node.pin]);
|
||||||
exec(gpioCommand+" write "+node.pin+" "+node.level, function(err,stdout,stderr) {
|
}
|
||||||
if (err) { node.error(err); }
|
node.running = true;
|
||||||
});
|
node.status({fill:"green",shape:"dot",text:"OK"});
|
||||||
}
|
|
||||||
node.on("input", function(msg) {
|
node.on("input", inputlistener);
|
||||||
if (msg.payload === "true") { msg.payload = true; }
|
|
||||||
if (msg.payload === "false") { msg.payload = false; }
|
node.child.stdout.on('data', function (data) {
|
||||||
var out = Number(msg.payload);
|
if (RED.settings.verbose) { node.log("out: "+data+" :"); }
|
||||||
var limit = 1;
|
|
||||||
if (node.out === "pwm") { limit = 1023; }
|
|
||||||
if ((out >= 0) && (out <= limit)) {
|
|
||||||
exec(gpioCommand+" "+node.op+" "+node.pin+" "+out, function(err,stdout,stderr) {
|
|
||||||
if (err) { node.error(err); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else { node.warn("Invalid input: "+out); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
node.child.stderr.on('data', function (data) {
|
||||||
|
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('close', function (code) {
|
||||||
|
if (RED.settings.verbose) { node.log("ret: "+code+" :"); }
|
||||||
|
node.child = null;
|
||||||
|
node.running = false;
|
||||||
|
node.status({fill:"red",shape:"circle",text:""});
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('error', function (err) {
|
||||||
|
if (err.errno === "ENOENT") { node.warn('Command not found'); }
|
||||||
|
else if (err.errno === "EACCES") { node.warn('Command not executable'); }
|
||||||
|
else { node.log('error: ' + err); }
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
node.error("Invalid GPIO pin: "+node.pin);
|
node.error("Invalid GPIO pin: "+node.pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
node.on("close", function() {
|
node.on("close", function() {
|
||||||
exec(gpioCommand+" mode "+node.pin+" in");
|
if (node.child != null) {
|
||||||
|
node.child.stdin.write(" close "+node.pin);
|
||||||
|
node.child.kill('SIGKILL');
|
||||||
|
}
|
||||||
|
node.status({fill:"red",shape:"circle",text:""});
|
||||||
|
delete pinsInUse[node.pin];
|
||||||
|
if (RED.settings.verbose) { node.log("end"); }
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var pitype = { type:"" };
|
var pitype = { type:"" };
|
||||||
exec(gpioCommand+" -v | grep Type", function(err,stdout,stderr) {
|
exec(gpioCommand+" rev 0", function(err,stdout,stderr) {
|
||||||
if (err) {
|
if (err) {
|
||||||
util.log('[36-rpi-gpio.js] Error: "'+gpioCommand+' -v" command failed for some reason.');
|
console.log('[rpi-gpio] Version command failed for some reason.');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pitype = { type:(stdout.split(","))[0].split(": ")[1], rev:(stdout.split(","))[1].split(": ")[1] };
|
if (stdout.trim() == "0") { pitype = { type:"Compute" }; }
|
||||||
|
else if (stdout.trim() == "1") { pitype = { type:"A/B v1" }; }
|
||||||
|
else if (stdout.trim() == "2") { pitype = { type:"A/B v2" }; }
|
||||||
|
else if (stdout.trim() == "3") { pitype = { type:"Model B+" }; }
|
||||||
|
else { console.log("SAW Pi TYPE",stdout.trim()); }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
RED.nodes.registerType("rpi-gpio in",GPIOInNode);
|
|
||||||
RED.nodes.registerType("rpi-gpio out",GPIOOutNode);
|
RED.nodes.registerType("rpi-gpio out",GPIOOutNode);
|
||||||
|
|
||||||
RED.httpAdmin.get('/rpi-gpio/:id',function(req,res) {
|
RED.httpAdmin.get('/rpi-gpio/:id',function(req,res) {
|
||||||
res.send( JSON.stringify(pitype) );
|
res.send( JSON.stringify(pitype) );
|
||||||
});
|
});
|
||||||
|
|
||||||
|
RED.httpAdmin.get('/rpi-pins/:id',function(req,res) {
|
||||||
|
res.send( JSON.stringify(pinsInUse) );
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
16
nodes/core/hardware/nrgpio
Executable file
16
nodes/core/hardware/nrgpio
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2014 IBM Corp.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
BASEDIR=$(dirname $0)
|
||||||
|
sudo python -u $BASEDIR/nrgpio.py $@
|
125
nodes/core/hardware/nrgpio.py
Normal file
125
nodes/core/hardware/nrgpio.py
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
#
|
||||||
|
# Copyright 2014 IBM Corp.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Import library functions we need
|
||||||
|
import RPi.GPIO as GPIO
|
||||||
|
import sys
|
||||||
|
|
||||||
|
bounce = 20 # bounce time in mS to apply
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
cmd = sys.argv[1].lower()
|
||||||
|
pin = int(sys.argv[2])
|
||||||
|
GPIO.setmode(GPIO.BOARD)
|
||||||
|
GPIO.setwarnings(False)
|
||||||
|
|
||||||
|
if cmd == "pwm":
|
||||||
|
#print "Initialised pin "+str(pin)+" to PWM"
|
||||||
|
GPIO.setup(pin,GPIO.OUT)
|
||||||
|
p = GPIO.PWM(pin, 100)
|
||||||
|
p.start(0)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = raw_input()
|
||||||
|
if data == "close":
|
||||||
|
GPIO.cleanup(pin)
|
||||||
|
sys.exit(0)
|
||||||
|
p.ChangeDutyCycle(float(data))
|
||||||
|
except EOFError: # hopefully always caused by us sigint'ing the program
|
||||||
|
GPIO.cleanup(pin)
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as ex:
|
||||||
|
print "bad data: "+data
|
||||||
|
|
||||||
|
if cmd == "buzz":
|
||||||
|
#print "Initialised pin "+str(pin)+" to Buzz"
|
||||||
|
GPIO.setup(pin,GPIO.OUT)
|
||||||
|
p = GPIO.PWM(pin, 100)
|
||||||
|
p.stop()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = raw_input()
|
||||||
|
if data == "close":
|
||||||
|
GPIO.cleanup(pin)
|
||||||
|
sys.exit(0)
|
||||||
|
elif float(data) == 0:
|
||||||
|
p.stop()
|
||||||
|
else:
|
||||||
|
p.start(50)
|
||||||
|
p.ChangeFrequency(float(data))
|
||||||
|
except EOFError: # hopefully always caused by us sigint'ing the program
|
||||||
|
GPIO.cleanup(pin)
|
||||||
|
sys.exit(0)
|
||||||
|
except Exception as ex:
|
||||||
|
print "bad data: "+data
|
||||||
|
|
||||||
|
elif cmd == "out":
|
||||||
|
#print "Initialised pin "+str(pin)+" to OUT"
|
||||||
|
GPIO.setup(pin,GPIO.OUT)
|
||||||
|
if len(sys.argv) == 4:
|
||||||
|
GPIO.output(pin,int(sys.argv[3]))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = raw_input()
|
||||||
|
if data == "close":
|
||||||
|
GPIO.cleanup(pin)
|
||||||
|
sys.exit(0)
|
||||||
|
data = int(data)
|
||||||
|
except EOFError: # hopefully always caused by us sigint'ing the program
|
||||||
|
GPIO.cleanup(pin)
|
||||||
|
sys.exit(0)
|
||||||
|
except:
|
||||||
|
data = 0
|
||||||
|
if data != 0:
|
||||||
|
data = 1
|
||||||
|
GPIO.output(pin,data)
|
||||||
|
|
||||||
|
elif cmd == "in":
|
||||||
|
#print "Initialised pin "+str(pin)+" to IN"
|
||||||
|
def handle_callback(chan):
|
||||||
|
print GPIO.input(chan)
|
||||||
|
|
||||||
|
if len(sys.argv) == 4:
|
||||||
|
if sys.argv[3].lower() == "up":
|
||||||
|
GPIO.setup(pin,GPIO.IN,GPIO.PUD_UP)
|
||||||
|
elif sys.argv[3].lower() == "down":
|
||||||
|
GPIO.setup(pin,GPIO.IN,GPIO.PUD_DOWN)
|
||||||
|
else:
|
||||||
|
GPIO.setup(pin,GPIO.IN)
|
||||||
|
else:
|
||||||
|
GPIO.setup(pin,GPIO.IN)
|
||||||
|
print GPIO.input(pin)
|
||||||
|
GPIO.add_event_detect(pin, GPIO.BOTH, callback=handle_callback, bouncetime=bounce)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = raw_input()
|
||||||
|
if data == "close":
|
||||||
|
GPIO.cleanup(pin)
|
||||||
|
sys.exit(0)
|
||||||
|
except EOFError: # hopefully always caused by us sigint'ing the program
|
||||||
|
GPIO.cleanup(pin)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
elif cmd == "rev":
|
||||||
|
print GPIO.RPI_REVISION
|
||||||
|
|
||||||
|
elif cmd == "ver":
|
||||||
|
print GPIO.VERSION
|
||||||
|
|
||||||
|
else:
|
||||||
|
print "Bad parameters - {in|out|pwm} {pin} {value|up|down}"
|
Loading…
Reference in New Issue
Block a user