Commit ab438353 authored by Jake Read's avatar Jake Read

towards ports and links, and instron utils

parent fc639ed1
......@@ -15,11 +15,6 @@ This project serves the developement environment / api we use to write and repre
## Programming Notes
- wake up planner sequence, say hello
- load program / don't during startup ?
- flow control immediately ?
- exercise to get in groove: pwm for servos & startup seq. in atkapi
- once we can plan gcode sequence, work towards more
- better hardware abstraction, i.e.
stepper.port = bridge.port('0,1')
......
// object to extend for things-that-are-hardware
// and pass f'n to call on received messages
function ATKPort(route, calls) {
var atkport = {
isAtkPort: true,
link: null, // pls, deliver 2 me a hw outlet
route: route,
calls: calls
}
atkport.send = function(msg) {
if (this.link != null) {
this.link.send(msg, this)
} else {
console.log("NO LINK NO SEND")
}
}
atkport.onMessage = function(msg){
this.calls(msg)
}
return atkport
}
module.exports = ATKPort
\ No newline at end of file
......@@ -53,6 +53,11 @@
"safe-buffer": "5.1.2"
}
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"accepts": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
......@@ -1075,11 +1080,28 @@
"semver": "5.5.0"
}
},
"node-webcam": {
"version": "0.4.5",
"resolved": "https://registry.npmjs.org/node-webcam/-/node-webcam-0.4.5.tgz",
"integrity": "sha512-ZOwSLKb2D0Ie3P4Ja5ouuwmhQs4Xsda98LANkoKJJxqa39o/pLbR/khEqvn7YQpJeoZ+CXGmHuHfTalCB7PvyQ==",
"requires": {
"nopt": "4.0.1"
}
},
"noop-logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
},
"nopt": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
"requires": {
"abbrev": "1.1.1",
"osenv": "0.1.5"
}
},
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
......@@ -1183,6 +1205,20 @@
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M="
},
"os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
},
"osenv": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
"requires": {
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"parseurl": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
......
......@@ -10,6 +10,7 @@
"express": "^4.16.3",
"http": "0.0.0",
"mathjs": "^5.1.2",
"node-webcam": "^0.4.5",
"readline": "^1.3.0",
"serialport": "^6.2.2",
"ws": "^6.0.0"
......
var test = addModule('./src/hardware/test.js')
var bridge = addModule('./src/hardware/bridge.js')
test.outputs.packet.attach(bridge.inputs.B)
bridge.outputs.B.attach(test.inputs.packet)
var yma = addModule('./src/hardware/stepper.js')
var ymb = addModule('./src/hardware/stepper.js')
var t2 = addModule('./src/hardware/test.js')
var t3 = addModule('./src/hardware/test.js')
yma.state.axis = 'Y'
yma.state.spu = 75
yma.state.rawMove = 0.25
yma.outputs.packet.attach(bridge.inputs.A)
bridge.outputs.A.attach(yma.inputs.packet)
t2.outputs.packet.attach(bridge.inputs.A)
bridge.outputs.A.attach(t2.inputs.packet)
ymb.state.axis = 'Y'
// should have to reverse this but did it with wires :|
ymb.state.spu = -75
ymb.state.rawMove = 0.25
ymb.outputs.packet.attach(bridge.inputs.F)
bridge.outputs.F.attach(ymb.inputs.packet)
t3.outputs.packet.attach(bridge.inputs.F)
bridge.outputs.F.attach(t3.inputs.packet)
/*
var serialATKLink = addModule('./src/hardware/serialATKLink.js')
/*
var rtr = addModule('./src/hardware/atkrouter.js')
rtr.port.route = '0'
serialATKLink.attach(rtr)
var bbs = addModule('./src/hardware/atkbbbs.js')
bbs.port.route = '0,2'
serialATKLink.attach(bbs.port)
*/
bridge.init()
var plCol = 1060
setUiPos(test, plCol,718 + 200)
setUiPos(t2, plCol, 850 + 200)
setUiPos(t3, plCol, 970 + 200)
var hwCol = 1629
setUiPos(yma, hwCol, 372)
setUiPos(ymb, hwCol, 626)
setUiPos(bridge, hwCol,890)
\ No newline at end of file
var gate = addModule('./src/util/gate.js')
var delay = addModule('./src/util/delay.js')
var log = addModule('./src/util/log.js')
gate.outputs.out.attach(delay.inputs.thru)
gate.outputs.out.attach(log.inputs.thru)
var andflow = addModule('./src/flowcontrol/and.js')
//delay.outputs.out.attach(gate.inputs.thru)
var cam = addModule('./src/hardware/webcam.js')
gate.outputs.out.attach(andflow.inputs.reset)
gate.outputs.out.attach(cam.inputs.trigger)
delay.outputs.out.attach(andflow.inputs.A)
cam.outputs.callback.attach(andflow.inputs.B)
andflow.outputs.out.attach(gate.inputs.thru)
var adc = addModule('./src/hardware/adc.js')
var test = addModule('./src/hardware/test.js')
var bridge = addModule('./src/hardware/bridge.js')
adc.outputs.packet.attach(bridge.inputs.B)
test.outputs.packet.attach(bridge.inputs.B)
bridge.outputs.B.attach(adc.inputs.packet)
bridge.outputs.B.attach(test.inputs.packet)
var yma = addModule('./src/hardware/stepper.js')
var ymb = addModule('./src/hardware/stepper.js')
gate.outputs.out.attach(yma.inputs.rmtrig)
gate.outputs.out.attach(ymb.inputs.rmtrig)
var t2 = addModule('./src/hardware/test.js')
var t3 = addModule('./src/hardware/test.js')
yma.state.axis = 'Y'
yma.state.spu = 75
yma.state.rawMove = 0.25
yma.outputs.packet.attach(bridge.inputs.A)
bridge.outputs.A.attach(yma.inputs.packet)
t2.outputs.packet.attach(bridge.inputs.A)
bridge.outputs.A.attach(t2.inputs.packet)
ymb.state.axis = 'Y'
// should have to reverse this but did it with wires :|
ymb.state.spu = -75
ymb.state.rawMove = 0.25
ymb.outputs.packet.attach(bridge.inputs.F)
bridge.outputs.F.attach(ymb.inputs.packet)
t3.outputs.packet.attach(bridge.inputs.F)
bridge.outputs.F.attach(t3.inputs.packet)
/*
var serialATKLink = addModule('./src/hardware/serialATKLink.js')
/*
var rtr = addModule('./src/hardware/atkrouter.js')
rtr.port.route = '0'
serialATKLink.attach(rtr)
var bbs = addModule('./src/hardware/atkbbbs.js')
bbs.port.route = '0,2'
serialATKLink.attach(bbs.port)
*/
bridge.init()
setUiPos(gate, 160, 130)
setUiPos(delay, 160, 260)
setUiPos(log, 160, 400)
setUiPos(andflow, 700, 300)
setUiPos(cam, 500, 700)
var plCol = 1060
setUiPos(test, plCol,718 + 200)
setUiPos(t2, plCol, 850 + 200)
setUiPos(t3, plCol, 970 + 200)
var hwCol = 1629
setUiPos(adc, hwCol, 180)
setUiPos(yma, hwCol, 372)
setUiPos(ymb, hwCol, 626)
setUiPos(bridge, hwCol,890)
\ No newline at end of file
// wrap require() up, appending path used to object, and giving ID
// use the same to load from browser
var term = addModule('./src/ui/terminal.js')
......@@ -88,7 +89,7 @@ bridge.state.rE = '0'
bridge.init()
multiline.load()
multiline.load('load/dogbone.gcode')
// setting data w/r/t the representations they serve
......
......@@ -12,6 +12,20 @@
/*
RULES:
modules have Ouputs() and Inputs() that connect to other software modules running on the same CPU. It's a directed graph.
modules can have ATKPort()s that use a Link() to get to remote hardware, per message-passing network. It's a physical graph of duplex connections.
this is nice because we might have two Link()s to double up on bandwidth.
alternately, Link()s could be TCP connections to other pieces of hardware, including something like us !
*/
/*
SYSTEM REQUIRES
*/
......@@ -122,168 +136,55 @@ PROGRAM AS API
var modules = new Array()
var term = addModule('./src/ui/terminal.js')
var multiline = addModule('./src/ui/multiline.js')
var goButton = addModule('./src/ui/button.js')
var numOut = addModule('./src/ui/number.js')
var delay = addModule('./src/util/delay.js')
var testButton = addModule('./src/ui/button.js')
var gcode = addModule('./src/parsing/gcode.js')
var planner = addModule('./src/motion/planner.js')
var test = addModule('./src/hardware/test.js')
var bridge = addModule('./src/hardware/bridge.js')
var servo = addModule('./src/hardware/servo.js')
test.outputs.packet.attach(bridge.inputs.B)
var xm = addModule('./src/hardware/stepper.js')
var yma = addModule('./src/hardware/stepper.js')
var ymb = addModule('./src/hardware/stepper.js')
var zm = addModule('./src/hardware/stepper.js')
bridge.outputs.B.attach(test.inputs.packet)
var t1 = addModule('./src/hardware/test.js')
var t2 = addModule('./src/hardware/test.js')
var t3 = addModule('./src/hardware/test.js')
var t4 = addModule('./src/hardware/test.js')
var t5 = addModule('./src/hardware/test.js')
//var t6 = addModule('./src/hardware/test.js')
var t7 = addModule('./src/hardware/test.js')
var bridge = addModule('./src/hardware/bridge.js')
// attaching an output to an input
term.outputs.lineOut.attach(gcode.inputs.lineIn)
multiline.outputs.lineOut.attach(gcode.inputs.lineIn)
gcode.outputs.instructionOut.attach(planner.inputs.instruction)
goButton.outputs.whammy.attach(numOut.inputs.evt)
numOut.outputs.out.attach(multiline.inputs.req)
goButton.outputs.whammy.attach(delay.inputs.thru)
delay.outputs.out.attach(planner.inputs.run)
testButton.outputs.whammy.attach(t1.inputs.trigger)
testButton.outputs.whammy.attach(t2.inputs.trigger)
testButton.outputs.whammy.attach(t3.inputs.trigger)
testButton.outputs.whammy.attach(t4.inputs.trigger)
testButton.outputs.whammy.attach(t5.inputs.trigger)
//testButton.outputs.whammy.attach(t6.inputs.trigger)
// bi-directional hook planner / motor
planner.outputs.moves.attach(xm.inputs.move)
xm.outputs.ack.attach(planner.inputs.acks)
planner.outputs.moves.attach(yma.inputs.move)
yma.outputs.ack.attach(planner.inputs.acks)
planner.outputs.moves.attach(ymb.inputs.move)
//ymb.outputs.ack.attach(planner.inputs.acks)
planner.outputs.moves.attach(zm.inputs.move)
zm.outputs.ack.attach(planner.inputs.acks)
planner.outputs.moveComplete.attach(multiline.inputs.req)
// 0,4 is NC
// 0,0 is YL
// 0,1 is Z
// 0,2 is ATKBBB
// 0,3 is X
// 0,4 is NC
// 0,5 is YR
// 0 is Router
// same motors / bridge
xm.state.axis = 'X'
xm.state.spu = 100
xm.outputs.packet.attach(bridge.inputs.A)
bridge.outputs.A.attach(xm.inputs.packet)
bridge.state.rA = '0,3'
t1.outputs.packet.attach(bridge.inputs.A)
bridge.outputs.A.attach(t1.inputs.packet)
// a, or, left
yma.state.axis = 'Y'
yma.state.spu = 100
yma.outputs.packet.attach(bridge.inputs.B)
bridge.outputs.B.attach(yma.inputs.packet)
bridge.state.rB = '0,0'
t2.outputs.packet.attach(bridge.inputs.B)
bridge.outputs.B.attach(t2.inputs.packet)
// right
ymb.state.axis = 'Y'
// should have to reverse this but did it with wires :|
ymb.state.spu = -100
ymb.outputs.packet.attach(bridge.inputs.C)
bridge.outputs.C.attach(ymb.inputs.packet)
bridge.state.rC = '0,5'
t3.outputs.packet.attach(bridge.inputs.C)
bridge.outputs.C.attach(t3.inputs.packet)
zm.state.axis = 'Z'
zm.state.spu = -100
zm.outputs.packet.attach(bridge.inputs.D)
bridge.outputs.D.attach(zm.inputs.packet)
bridge.state.rD = '0,1'
t4.outputs.packet.attach(bridge.inputs.D)
bridge.outputs.D.attach(t4.inputs.packet)
servo.outputs.packet.attach(bridge.inputs.E)
servo.state.servoVal = 30
t5.outputs.packet.attach(bridge.inputs.E)
bridge.outputs.E.attach(t5.inputs.packet)
bridge.state.rE = '0,2'
bridge.state.rF = '0,4'
/*
t6.outputs.packet.attach(bridge.inputs.F)
bridge.outputs.F.attach(t6.inputs.packet)
//bridge.state.rF = '0'
*/
t2.outputs.packet.attach(bridge.inputs.A)
bridge.outputs.A.attach(t2.inputs.packet)
t7.outputs.packet.attach(bridge.inputs.G)
bridge.outputs.G.attach(t7.inputs.packet)
bridge.init()
t3.outputs.packet.attach(bridge.inputs.F)
bridge.outputs.F.attach(t3.inputs.packet)
multiline.load('load/dogbone.gcode')
// setting data w/r/t the representations they serve
/*
var serialATKLink = addModule('./src/hardware/serialATKLink.js')
setUiPos(multiline, 10, 10)
/*
var rtr = addModule('./src/hardware/atkrouter.js')
rtr.port.route = '0'
serialATKLink.attach(rtr)
setUiPos(gcode, 450, 10)
setUiPos(term, 450, 180)
setUiPos(goButton, 450, 300)
setUiPos(numOut, 450, 400)
setUiPos(delay, 450, 520)
setUiPos(testButton, 450, 730)
var bbs = addModule('./src/hardware/atkbbbs.js')
bbs.port.route = '0,2'
serialATKLink.attach(bbs.port)
*/
var plCol = 900
bridge.init()
setUiPos(t1, plCol, 730)
setUiPos(t2, plCol, 850)
setUiPos(t3, plCol, 970)
setUiPos(t4, plCol, 1090)
setUiPos(t5, plCol, 1210)
setUiPos(t7, plCol, 1330)
//setUiPos(t7, plCol, 1450)
setUiPos(servo, plCol, 500)
setUiPos(planner, plCol, 10)
var plCol = 1060
var hwCol = 1350
setUiPos(test, plCol,718 + 200)
setUiPos(t2, plCol, 850 + 200)
setUiPos(t3, plCol, 970 + 200)
setUiPos(xm, hwCol, 10)
setUiPos(yma, hwCol, 250)
setUiPos(ymb, hwCol, 490)
setUiPos(zm, hwCol, 730)
var hwCol = 1629
setUiPos(bridge, hwCol, 970)
setUiPos(bridge, hwCol,890)
// setting ui elements / state
planner.state.isRunning = 0
/*
------------------------------------------------------
LOST FUNCTION
------------------------------------------------------
*/
function setUiPos(module, left, top){
if(module.ui == null){
function setUiPos(module, left, top) {
if (module.ui == null) {
module.ui = {}
}
module.ui.left = left
......@@ -323,7 +224,7 @@ function addModule(path) {
}
}
console.log('ADDING MODULE', mod)
console.log('ADDING MODULE', mod.description.name)
// now roll and return representable object
// first to UI
......@@ -418,18 +319,18 @@ function changeState(data) {
// that might change some state
oldState[key] = newState[key]
// to prevent quickly changing it back, we'll exit now (one state change from UI per trx)
return true
return true
}
} else if (oldState[key].isMultiLine) {
if (oldState[key].value != newState[key].value){
if (oldState[key].value != newState[key].value) {
console.log('CHANGE MULTILINE STATE', key, 'to', newState[key].value, 'in', data.id)
oldState[key].value = newState[key].value
return true
oldState[key].value = newState[key].value
return true
}
} else if (oldState[key] !== newState[key]) {
console.log('CHANGE STATE', key, 'to', newState[key], 'in', data.id)
oldState[key] = newState[key]
return true
oldState[key] = newState[key]
return true
}
}
}
......@@ -479,11 +380,11 @@ function putLink(data) {
return module.id === data.to.id
})
if(fromModule.outputs[data.from.output].isLinked(toModule.inputs[data.to.input])){
console.log("HOOKDOWN")
fromModule.outputs[data.from.output].remove(toModule.inputs[data.to.input])
if (fromModule.outputs[data.from.output].isLinked(toModule.inputs[data.to.input])) {
console.log("HOOKDOWN")
fromModule.outputs[data.from.output].remove(toModule.inputs[data.to.input])
} else {
fromModule.outputs[data.from.output].attach(toModule.inputs[data.to.input])
fromModule.outputs[data.from.output].attach(toModule.inputs[data.to.input])
}
// replace it
......
// boilerplate atkapi header
const InOut = require('../../lib/inout.js')
let Input = InOut.Input
let Output = InOut.Output
let State = InOut.State
let Button = InOut.Button
// a constructor, a fn, a javascript mess
function AndFlow() {
var andflow = {
// descriptions are used in UI
description: {
name: 'andflow',
alt: 'in ... out'
}
}
andflow.state = State()
// alias !
var state = andflow.state
state.toggle = Button("Reset")
state.onChange('toggle', onReset)
// yikes
state.A = 0
state.B = 0
andflow.inputs = {
reset: Input('any', onReset),
A: Input('any', onA),
B: Input('any', onB)
}
andflow.outputs = {
out: Output('any')
}
function onReset(evt){
state.A = 0,
state.B = 0
}
function onA(input){
state.A = 1
if(state.A && state.B){
andflow.outputs.out.emit(1)
onReset()
}
}
function onB(input){
state.B = 1
if(state.A && state.B){
andflow.outputs.out.emit(1)
onReset()
}
}
return andflow
}
// exports
module.exports = AndFlow
\ No newline at end of file
// boilerplate atkapi header
const InOut = require('../../lib/inout.js')
let Input = InOut.Input
let Output = InOut.Output
let State = InOut.State
let Button = InOut.Button
const PCKT = require('../../lib/packets.js')
// a constructor, a fn, a javascript mess
function BBADC() {
var bbadc = {
// descriptions are used in UI
description: {
name: 'Breadboard ADC Request',
alt: 'bbadc',
isHardware: true
}
}
bbadc.state = State()
// alias !
var state = bbadc.state
state.button = Button('REQUEST CONVERSION')
state.onChange('button', onButtonPress)
state.adcVal = 0 // reports val
state.onChange('bbadcVal', onButtonPress)
bbadc.inputs = {
packet: Input('headless packet', onPacketReturn) ,
request: Input('event', onButtonPress)
}
bbadc.outputs = {
packet: Output('number')
}
function onButtonPress(evt) {
var pckt = new Array()
pckt.push(142) // request has this key
bbadc.outputs.packet.emit(pckt)
}
function onPacketReturn(evt) {
console.log('ADC RETURN', evt)
}
return bbadc
}
// exports
module.exports = BBADC
\ No newline at end of file
......@@ -5,18 +5,25 @@ let Output = InOut.Output
let State = InOut.State
let Button = InOut.Button
const ATKPort = require('../../lib/atkport.js')
const PCKT = require('../../lib/packets.js')
// a constructor, a fn, a javascript mess
function ATKBreadBoardServo(port) {
function ATKBreadBoardServo() {
var atkbbs = {
// descriptions are used in UI
description: {
name: 'Breadboard Servo Signal Generator',
alt: 'servo',
isHardware: true
}
},
port: ATKPort('0', onPacket), // inputs / outputs to external hw
inputs: {
servoVal: Input('number', onServoValChange)
},
outputs: {
conf: Output('event')
},
}
atkbbs.state = State()
......@@ -24,23 +31,15 @@ function ATKBreadBoardServo(port) {
var state = atkbbs.state
state.button = Button('SEND')
state.onChange('button', onButtonPress)
state.onChange('button', onServoValChange)
state.servoVal = 0 // 0->100 does 1 -> 2ms duty on 20ms period
state.onChange('servoVal', onButtonPress)
atkbbs.inputs = {
packet: Input('headless packet', onPacketReturn) // makes anything into '1' event
}
atkbbs.outputs = {
packet: Output('number')
}
state.onChange('servoVal', onServoValChange)
function onButtonPress(evt) {
function onServoValChange(evt) {
var pwm = state.servoVal
if(pwm > 100){
if (pwm > 100) {
pwm = 100