You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have encountered an issue where Johnny-five is causing Node-red to exit due to an uncaught exception.
I'm using the Node-red Johnny-five node to control a stepper, checking for the status of the end stop and stepper alarm and triggering a LED strip.
System setup
Node-red 0.15.2 running on a RPi3
node-red-contrib-gpio node: 0.10.0
Nodebot: Arduino/Firmata
Connection: Local Serial Port
Port: /dev/ttyUSB0
I'm using a version of AdvancedFirmata on an Arduino Nano, that I built in January 2017 with the following core features enabled:
firmataExt.addFeature(digitalInput);
firmataExt.addFeature(digitalOutput);
firmataExt.addFeature(analogInput);
firmataExt.addFeature(analogOutput);
firmataExt.addFeature(servo);
firmataExt.addFeature(i2c);
firmataExt.addFeature(stepper);
firmataExt.addFeature(reporting);
The issue happens randomly, but since my code within the Node-red Johnny-five node spends most of the time idling in a setTimeout loop, the issue has only happened when no gpio pin was being actively set, but some pins where being listened to.
It could very well be an issue with the Firmata code/Arduino Nano used and not the Johnny-five node, but the errors listed are too vaguely detailed for me to understand what is the root cause.
Excerpt from the log file:
Oct 29 19:08:19 master01 Node-RED[15825]: 29 Oct 19:08:19 - [red] Uncaught Exception:
Oct 29 19:08:20 master01 Node-RED[15825]: 29 Oct 19:08:20 - TypeError: Cannot read property 'pinMode' of null
Oct 29 19:08:20 master01 Node-RED[15825]: at Pin.set (/home/pi/.node-red/node_modules/johnny-five/lib/pin.js:82:16)
Oct 29 19:08:20 master01 Node-RED[15825]: at Function.Pin.write (/home/pi/.node-red/node_modules/johnny-five/lib/pin.js:193:12)
Oct 29 19:08:20 master01 Node-RED[15825]: at Pin.high (/home/pi/.node-red/node_modules/johnny-five/lib/pin.js:277:7)
Oct 29 19:08:20 master01 Node-RED[15825]: at stepperEnable (evalmachine.:80:26)
Oct 29 19:08:20 master01 Node-RED[15825]: at home (evalmachine.:112:5)
Oct 29 19:08:20 master01 Node-RED[15825]: at experimentStopped (evalmachine.:187:5)
Oct 29 19:08:20 master01 Node-RED[15825]: at loop (evalmachine.:213:13)
Oct 29 19:08:20 master01 Node-RED[15825]: at ontimeout (timers.js:365:14)
Oct 29 19:08:20 master01 Node-RED[15825]: at tryOnTimeout (timers.js:237:5)
Oct 29 19:08:20 master01 Node-RED[15825]: at Timer.listOnTimeout (timers.js:207:5)
Oct 29 19:08:20 master01 systemd[1]: nodered.service: main process exited, code=exited, status=1/FAILURE
Oct 29 19:08:20 master01 systemd[1]: Unit nodered.service entered failed state.
My Johnny-five code:
//Initializing GPIO
//------------------------------------------------------------------------------
//Initialize LED strip
var LEDEnablePin = new five.Pin(7);
//Initialize endstop
var endstop = new five.Button({
pin: 8,
invert: true,
isPullup: true
});
//Initialize stepper alram
var stepperAlarm = new five.Button({
pin: 9,
invert: true,
isPullup: true
});
//Initialize stepper
var stepper = new five.Stepper({
type: five.Stepper.TYPE.DRIVER,
stepsPerRev: 200,
pins: {
step: 10,
dir: 11
}
});
//Initialize stepper enable
var stepperEnablePin = new five.Pin(12);
//Initialize Arduino LED
var led = new five.Led(13);
//Define variables
//------------------------------------------------------------------------------
var experimentActiveStatus = false;
var stepperActive = false;
var rpm = 200;
var accel = 2000;
var decel = 2000;
var stepsPerCM = 111;
// Variables later fetched from Dashboard
var duration = 1;
var photoEveryXMin = 60;
var noOfPlants = 12;
var distanceToFirstPlantCM = 1;
var plantDistanceCM = 24;
var stepsPerPosition = stepsPerCM * plantDistanceCM;
var maxTravelCM = 289;
var maxSteps = maxTravelCM * stepsPerCM;
var currentTime = 1;
var nextLoop = 1;
var unixStartTime = 1;
var unixStopTime = 1;
var startTime = "Start date";
var stopTime = "End date";
var camerasEnabled = true;
var cameraPosition = 0;
var currentStep = 0; //consider adding logic to tie steps to camera position
var LEDEnableState = false;
var endstopTriggered = false;
var stepperAlarmTriggered = false;
//FUNCTIONS
//------------------------------------------------------------------------------
function stepperEnable(state) {
if (state === true) {
stepperActive = true;
stepperEnablePin.high();
}
if (state === false || state === undefined) {
stepperActive = false;
stepperEnablePin.low();
}
var msg = {payload: {stepperEnable: stepperActive}};
node.send(msg);
}
function LEDEnable(state) {
// var LEDEnableState = false;
if (state === true) {
LEDEnableState = true;
LEDEnablePin.high();
}
if (state === false || state === undefined) {
LEDEnableState = false;
LEDEnablePin.low();
}
var msg = {payload: {LEDEnable: LEDEnableState}};
node.send(msg);
}
function LEDFlash(leaveOnTime){
LEDEnable(true);
setTimeout(function(){
LEDEnable(false)}, 1000 * leaveOnTime);
}
function home() {
var home_steps = noOfPlants * stepsPerPosition;
stepperEnable(true);
stepper.rpm(rpm).step({steps: home_steps, direction: 0, accel: accel, decel: decel}, function() {
console.log("Homeing");
stepperEnable(false);
cameraPosition = 0;
currentStep = 0;
msg = {payload: {cameraPosition: cameraPosition}};
node.send(msg);
});
}
function forward() {
cameraPosition++;
led.blink(100);
stepperEnable(true);
stepper.rpm(rpm).step({steps: stepsPerPosition, direction: 1, accel: accel, decel: decel}, function() {
console.log("Moving forward");
LEDFlash(2);
stepperEnable(false);
msg = {payload: {cameraPosition: cameraPosition, takePhoto: camerasEnabled}};
node.send(msg);
});
}
function backward() {
cameraPosition--;
led.blink(200);
stepperEnable(true);
stepper.rpm(rpm).step({steps: stepsPerPosition, direction: 0, accel: accel, decel: decel}, function() {
console.log("Moving backward");
stepperEnable(false);
msg = {payload: {cameraPosition: cameraPosition}};
node.send(msg);
});
}
function experimentActive() {
experimentActiveStatus = true;
var msg = {
payload: {
overview: {
experimentStatus: "Active",
photoEveryXMin: photoEveryXMin,
noOfPlants: noOfPlants,
startTime: startTime,
stopTime: stopTime,
nextLoop: "Preparing"
}
}
};
node.send(msg);
home();
setTimeout(function () {
// run inner loop
mainLoop();
//setNextMinute();
}, 1000*4); //wait 4 seconds for camera rig to home before starting
}
function experimentStopped() {
experimentActiveStatus = false;
var msg = {
payload: {
overview: {
experimentStatus: "Finished",
photoEveryXMin: undefined,
noOfPlants: undefined,
startTime: undefined,
stopTime: undefined,
nextLoop: undefined
}
}
};
node.send(msg);
home();
}
function setNextMinute() {
// figure out how much time remains before the end of the current minute
//var d = new Date().getTime()%60000;
var d = 50000;
//set a timeout to occur when that expires.
setTimeout(function () {
// recalculate a new timeout so that your timer doesn't lag over time.
innerloop();
// note that calling a function() here will
// not offset the next minute, since it is recalculated in setNextMinute()
setNextMinute();
},60000-d);
}
function mainLoop() {
// var loops = 2;
// var delay = 12000*noOfPlants; //base wait on no of active plants
var loops = Math.floor((duration*24*60)/photoEveryXMin);
var delay = 1000*60*photoEveryXMin; //wait X minutes between each main pass
// Iterate sequence asynchronously
(function loop(main) {
if (main >= loops || experimentActiveStatus === false){
experimentStopped();
return;
} // all done
if(main == (loops-1)){
nextLoop = unixStartTime + ((main)*photoEveryXMin*60*1000);
var msg = {
payload: {
nextLoop: nextLoop
}
};
node.send(msg);
} else{
nextLoop = unixStartTime + ((main+1)*photoEveryXMin*60*1000);
var msg = {
payload: {
nextLoop: nextLoop
}
};
node.send(msg);
}
innerLoop();
setTimeout(loop.bind(null, main+1), delay);
})(0);
}
function innerLoop() {
var delay = 1000*7; //wait 7 seconds before continuing to move
// Iterate sequence asynchronously
(function loop(inner) {
if (inner >= noOfPlants && experimentActiveStatus == true){
home();
} else if (inner < noOfPlants && experimentActiveStatus != false){
forward();
}
if (inner >= noOfPlants || experimentActiveStatus === false){
return;
} // all done
setTimeout(loop.bind(null, inner+1), delay);
})(0);
}
//EVENT LISTENERS
//------------------------------------------------------------------------------
endstop.on("press", function() {
endstopTriggered = true;
//small hack to stop stepper if endstop triggered.
stepper.rpm(rpm).step({steps: stepsPerCM, direction: 1, accel: accel, decel: decel}, function() {
console.log("Endstop triggered");
stepperEnable(false);
cameraPosition = 0;
});
var msg = {payload: {endstopTriggered:true, cameraPosition: cameraPosition}};
node.send(msg);
});
endstop.on("release", function() {
endstopTriggered = false;
var msg = {payload: {endstopTriggered:false}};
node.send(msg);
});
stepperAlarm.on("press", function() {
stepperAlarmTriggered = true;
var msg = {payload: {stepperAlarm:true}};
node.send(msg);
});
stepperAlarm.on("release", function() {
stepperAlarmTriggered = false;
var msg = {payload: {stepperAlarm:false}};
node.send(msg);
});
//"Setup"
//------------------------------------------------------------------------------
// "blink" the Arduino led in 1000ms on-off phase periods as a visual feedback
//led.blink(1000);
//Energize stepper to hold position
stepperEnable(true);
//Ensure LEDs are off
LEDEnable(false);
//Home rig on startup
home();
//"LOOP"
//------------------------------------------------------------------------------
//direction: null, movePosition: null, gotoPosition: null, runExperiment: null
node.on('input', function(msg){
console.log("J5 input");
if(msg.payload.currentTime !== undefined){
currentTime = msg.payload.currentTime;
}
if(msg.payload.config !== undefined){
noOfCams = msg.payload.config.noOfCams;
distanceToFirstPlantCM = msg.payload.config.distanceToFirstPlantCM;
plantDistanceCM = msg.payload.config.plantDistanceCM;
maxTravelCM = msg.payload.config.maxTravelCM;
stepsPerPosition = stepsPerCM * plantDistanceCM;
}
if(msg.payload.experiment !== undefined){
duration = msg.payload.experiment.duration;
photoEveryXMin = msg.payload.experiment.photoEveryXMin;
noOfPlants = msg.payload.experiment.noOfPlants;
startTime = msg.payload.experiment.startTime;
stopTime = msg.payload.experiment.stopTime;
unixStartTime = msg.payload.experiment.unixStartTime;
unixStopTime = msg.payload.experiment.unixStopTime;
}
if(msg.payload.enableCameras === true){
camerasEnabled = true;
} else if(msg.payload.enableCameras === false){
camerasEnabled = false;
}
if(msg.payload.enableStepper === true){
stepperEnable(true);
} else if(msg.payload.enableStepper === false){
stepperEnable(false);
}
if(msg.payload.enableLED === true){
LEDEnable(true);
} else if(msg.payload.enableLED === false){
LEDEnable(false);
}
if(msg.payload.takePhoto === true && cameraPosition > 0){
msg = {payload: {takePhoto: camerasEnabled}};
node.send(msg);
LEDFlash(2);
}
//Next position
if(msg.payload.direction === 1 && stepperActive === false && cameraPosition < noOfPlants){
forward();
}
//Start experiment
else if (msg.payload.direction === 0 && msg.payload.gotoPosition === 0 && msg.payload.experimentActive === true && stepperActive === false){
experimentActive();
}
//Stop experiment
else if (msg.payload.direction === null && msg.payload.movePosition === null && msg.payload.gotoPosition === null && msg.payload.experimentActive === false){
experimentStopped();
}
//Home
else if(msg.payload.direction === 0 && msg.payload.gotoPosition === 0 && stepperActive === false /* && cameraPosition > 0 */){
home();
}
//Previous position
else if(msg.payload.direction === 0 && stepperActive === false && cameraPosition >= 1){
backward();
}
// "blink" the Arduino led in 500ms on-off phase periods as a visual feedback
//led.blink(500);
msg = {payload: {cameraPosition: cameraPosition}};
node.send(msg);
});
The text was updated successfully, but these errors were encountered:
I have encountered an issue where Johnny-five is causing Node-red to exit due to an uncaught exception.
I'm using the Node-red Johnny-five node to control a stepper, checking for the status of the end stop and stepper alarm and triggering a LED strip.
System setup
Node-red 0.15.2 running on a RPi3
node-red-contrib-gpio node: 0.10.0
Nodebot: Arduino/Firmata
Connection: Local Serial Port
Port: /dev/ttyUSB0
I'm using a version of AdvancedFirmata on an Arduino Nano, that I built in January 2017 with the following core features enabled:
firmataExt.addFeature(digitalInput);
firmataExt.addFeature(digitalOutput);
firmataExt.addFeature(analogInput);
firmataExt.addFeature(analogOutput);
firmataExt.addFeature(servo);
firmataExt.addFeature(i2c);
firmataExt.addFeature(stepper);
firmataExt.addFeature(reporting);
The issue happens randomly, but since my code within the Node-red Johnny-five node spends most of the time idling in a setTimeout loop, the issue has only happened when no gpio pin was being actively set, but some pins where being listened to.
It could very well be an issue with the Firmata code/Arduino Nano used and not the Johnny-five node, but the errors listed are too vaguely detailed for me to understand what is the root cause.
Excerpt from the log file:
My Johnny-five code:
The text was updated successfully, but these errors were encountered: