Last active
August 29, 2015 14:08
-
-
Save BrianAdams/549521d7bb83b664941a to your computer and use it in GitHub Desktop.
Initial test code for a bed of nails tester for the OpenROV controller board
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var jsm = require('javascript-state-machine'); | |
var b = require('bonescript'); | |
var proc = require('child_process'); | |
var spawn = proc.spawn; | |
var Q = require('q'); | |
var serialPort = require('serialport'); | |
var testnumberInProgress = 0; | |
// Pin Mappings, names match the schematic | |
var SW_LID = 'P8_7'; | |
b.pinMode(SW_LID, b.INPUT); | |
var SW_TEST = 'P8_8'; | |
b.pinMode(SW_TEST, b.INPUT); | |
var LED_FAIL = 'P8_9'; | |
b.pinMode(LED_FAIL, b.OUTPUT); | |
var LED_SUCCESS = 'P8_10'; | |
b.pinMode(LED_SUCCESS, b.OUTPUT); | |
var LED_PROGRESS = 'P8_12'; | |
b.pinMode(LED_PROGRESS, b.OUTPUT); | |
var LED_READY = 'P8_11'; | |
b.pinMode(LED_READY, b.OUTPUT); | |
var EN_12V_POWER = 'P8_13'; | |
b.pinMode(EN_12V_POWER, b.OUTPUT); | |
var C5V_ON = 'P8_14'; | |
b.pinMode(C5V_ON, b.INPUT); | |
var EN_5V_POWER = 'P8_15'; | |
b.pinMode(EN_5V_POWER, b.OUTPUT); | |
var start; | |
var failureBlinkTimer; | |
var fsm = jsm.StateMachine.create({ | |
initial: 'init', | |
error: function(eventName, from, to, args, errorCode, errorMessage) { | |
console.log( 'event ' + eventName + ' was naughty :- ' + errorMessage); | |
}, | |
events : [ | |
{ name: 'lid_closed', from:['open','init'], to:'ready_to_test'}, | |
{ name: 'test_button_pushed', from:'ready_to_test', to:'test_in_progress'}, | |
{ name: 'test_failed', from:'*', to:'test_complete_failure' }, | |
{ name: 'test_complete', from:'test_in_progress', to:'test_complete_passing' }, | |
{ name: 'lid_open', from:'*', to:'open' } | |
], | |
callbacks : { | |
oninit: function(event, from, to, msg) { | |
var ledstate = b.LOW; | |
var blinktimer = setInterval(function(){ | |
if (ledstate === b.LOW){ | |
ledstate = b.HIGH; | |
} else { | |
ledstate = b.LOW; | |
} | |
b.digitalWrite(LED_FAIL, ledstate); | |
b.digitalWrite(LED_SUCCESS, ledstate); | |
b.digitalWrite(LED_PROGRESS, ledstate); | |
b.digitalWrite(LED_READY, ledstate); | |
console.log('blink' + ledstate); | |
},500); | |
setTimeout(function(){ | |
clearInterval(blinktimer); | |
var lidstate = b.digitalRead(SW_LID); | |
// init the state machine | |
if (lidstate) {fsm.lid_open()} else {fsm.lid_closed()} | |
},5000); | |
}, | |
onopen: function(event, from, to, msg) { | |
proc.exec('pkill avrdude'); | |
clearInterval(failureBlinkTimer); | |
//all LEDs except power are extinguished | |
b.digitalWrite(LED_FAIL, b.LOW); | |
b.digitalWrite(LED_SUCCESS, b.LOW); | |
b.digitalWrite(LED_PROGRESS, b.LOW); | |
b.digitalWrite(LED_READY, b.LOW); | |
//battery and tether power are disabled | |
b.digitalWrite(EN_12V_POWER, b.LOW); | |
b.digitalWrite(EN_5V_POWER, b.LOW); | |
b.digitalWrite('USR3', b.HIGH); | |
console.log('Did the open stuff.'); | |
}, | |
onready_to_test: function(event, from, to, msg) { | |
//set <Ready To Test> pin high to turn on LED | |
b.digitalWrite(LED_READY, b.HIGH); | |
testnumberInProgress = 0; | |
}, | |
ontest_in_progress: function(event, from, to, msg) { | |
Q.fcall(function(){ | |
//set <Ready To Test> pin low to turn off LED | |
b.digitalWrite(LED_READY, b.LOW); | |
//Turn on <Test in Progress> LED | |
b.digitalWrite(LED_PROGRESS, b.HIGH); | |
//Enable power on 12V and then pause 100ms | |
b.digitalWrite(EN_12V_POWER, b.HIGH); | |
start = +new Date(); | |
}) | |
.then( function () { return Q().delay( 250 ); } ) | |
.then(function(){ | |
var end = +new Date(); | |
console.log('diff in ms:' + (end - start) ); | |
// TEST: 5V is off | |
testnumberInProgress = 16; | |
var result = b.digitalRead(C5V_ON); | |
if(result !== 1){ | |
throw new '5V was not high'; | |
}; | |
// if high fail | |
b.digitalWrite(EN_5V_POWER, b.HIGH); | |
// TEST: 5V is on | |
//wait 100ms | |
console.log('Step1'); | |
}) | |
.then( function () { return Q().delay( 250 ); } ) | |
.then(function(){ | |
testnumberInProgress = 17; | |
var result = b.digitalRead(C5V_ON); | |
if(result !==0 ){ | |
console.log("Throwing error"); | |
throw '5V was not low'; | |
}; | |
console.log("Step2"); | |
}) | |
.then(function(){testnumberInProgress = 18; return runScript('bash',['/opt/openrov/cockpit/linux/burn-bootloader.sh'])}) | |
.then(function(){testnumberInProgress = 19; return runScript('bash',['/opt/openrov/cockpit/linux/install-afro-esc-firmware.sh'],{timeout:120000, cwd:'/opt/openrov/cockpit/linux'})}) | |
.progress(function(childProcess) { | |
console.log('[spawn] childProcess.pid: ', childProcess.pid); | |
childProcess.stdout.on('data', function(data) { | |
console.log('[spawn] stdout: ', data.toString()); | |
}); | |
childProcess.stderr.on('data', function(data) { | |
console.log('[spawn] stderr: ', data.toString()); | |
}); | |
}) | |
.then(function(){testnumberInProgress = 20; return runScript('bash',['/opt/openrov/cockpit/linux/arduino/firmware-install-tester.sh'])}) | |
.then(function(){return checkArduinoTests().timeout(10000, "Arduino tests timed out")}) | |
.then(function(){testnumberInProgress = 21;return runScript('bash',['/opt/openrov/cockpit/linux/arduino/firmware-installfromsource.sh'])}) | |
.then(function(){fsm.test_complete();}) | |
.catch(function(err){ | |
console.log("Caught the error in catch block"); | |
fsm.test_failed(err); | |
}) | |
.done(null, function(err) { | |
console.log("Caught the error"); | |
fsm.test_failed(err); | |
}); | |
}, | |
onleavetest_in_progress: function(event, from, to, msg){ | |
//Turn off <Test in Progress> LED | |
b.digitalWrite(LED_PROGRESS, b.LOW); | |
//Disable battery and tether power | |
b.digitalWrite(EN_12V_POWER, b.LOW); | |
b.digitalWrite(EN_5V_POWER, b.LOW); | |
}, | |
onleaveinit: function(event, from, to, msg){ | |
b.digitalWrite(LED_FAIL, b.LOW); | |
b.digitalWrite(LED_SUCCESS, b.LOW); | |
b.digitalWrite(LED_PROGRESS, b.LOW); | |
b.digitalWrite(LED_READY, b.LOW); | |
b.attachInterrupt(SW_LID, function(){return !IsDeBounceMode(SW_LID_debounce)}, b.CHANGE, function(){setTimeout(function(){if (b.digitalRead(SW_LID)) {fsm.lid_open()} else {fsm.lid_closed()}},50)}); | |
b.attachInterrupt(SW_TEST, function(){return !IsDeBounceMode(SW_TEST_debounce)}, b.RISING, function(){fsm.test_button_pushed()}); | |
}, | |
ontest_complete_failure: function(event, from, to, msg) { | |
//Turn on <Test Failure> LED | |
console.log("Test failed on:" + msg); | |
b.digitalWrite(LED_FAIL, b.HIGH); | |
failureBlinkTimer = repatedlyBlinkLED(LED_READY,testnumberInProgress,150); | |
console.log('Should blink' + testnumberInProgress); | |
//failureblink = setInterval(function(){},500); | |
console.log("Test fail stuff done"); | |
}, | |
ontest_complete_passing: function(event, from, to, msg) { | |
//Turn on <Test Success> LED | |
b.digitalWrite(LED_SUCCESS, b.HIGH); | |
}, | |
onenterstate: function(event, from, to, msg){ | |
console.log("Entered: " + to); | |
} | |
} | |
}); | |
var SW_LID_debounce = false; | |
var SW_TEST_debounce = false; | |
function IsDeBounceMode(debounce_flag){ | |
console.log("debounce check"); | |
if(debounce_flag) return true; | |
setTimeout(function(){debounce_flag = false;},100); | |
debounce_flag = true; | |
return false; | |
}; | |
// ---- Test Code to simulate button and switch presses ---- // | |
/* | |
setTimeout(function(){ | |
fsm.lid_closed() | |
},1000); | |
setTimeout(function(){ | |
fsm.test_button_pushed() | |
},3000); | |
*/ | |
function checkArduinoTests(){ | |
var deferred = Q.defer(); | |
//setTimeout(function(){deferred.resolve()},100); //simulate looking at test data and pass | |
var sp = new serialPort.SerialPort('/dev/ttyO1', { | |
baudrate: 115200, | |
parser: serialPort.parsers.readline('\r\n') | |
}); | |
sp.on("open", function () { | |
console.log('open'); | |
setTimeout(function(){sp.close();},5000); | |
sp.on('data', function(data) { | |
console.log('data received: ' + data); | |
if (data.substring(0, 1) !== "#") { | |
if (parseInt(data)===0) { | |
deferred.resolve(); | |
} else { | |
testnumberInProgress = parseInt(data); | |
deferred.reject(new Error('ArduinoTestFailed with code: ' + data, data )); | |
} | |
} | |
}); | |
}); | |
return deferred.promise; | |
} | |
function repatedlyBlinkLED(pin,times,speed){ | |
var _pin = pin; | |
var _pattern = []; | |
for (var i = 0;i<times;i++){ | |
_pattern.push(b.HIGH); | |
_pattern.push(b.LOW); | |
} | |
_pattern.push(b.LOW); | |
_pattern.push(b.LOW); | |
_pattern.push(b.LOW); | |
_pattern.push(b.LOW); | |
var _index = 0; | |
return setInterval(function(){ | |
b.digitalWrite(pin, _pattern[_index]); | |
_index++; | |
if (_index > _pattern.length) _index = 0; | |
},speed); | |
} | |
function runScript(script,args,options){ | |
var deferred = Q.defer(); | |
var p = spawn(script, args, options); | |
if ((options !== undefined ) && (options['timeout'] !== undefined) && (options.timeout > 0)){ | |
setTimeout(function(){ | |
if ((p.pid>0) && (p.code !== null)){ | |
proc.exec('kill -9' + p.pid); | |
proc.exec('pkill avrdude'); | |
//process.kill(p.pid); | |
deferred.reject(new Error('Timed Out: ' + script + ' ' + args)); | |
} | |
} | |
,options.timeout); | |
} | |
p.on('exit', function (code) { | |
if (code !== 0) { | |
deferred.reject(new Error('Failed: ' + script + ' ' + args + ' with code: ' + code)); | |
} else { | |
deferred.resolve(); | |
} | |
}); | |
p.on('error', function(err){ | |
deferred.reject(new Error('Failed: ' + script + ' ' + args + ' with msg: ' + err.message)); | |
}) | |
process.nextTick(function() { // Make sure the callee had a chance to add listeners | |
deferred.notify(p); | |
}); | |
return deferred.promise; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment