Skip to content

Instantly share code, notes, and snippets.

@BrianAdams
Last active August 29, 2015 14:08
Show Gist options
  • Save BrianAdams/549521d7bb83b664941a to your computer and use it in GitHub Desktop.
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
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