diff --git a/client/client.js b/client/client.js
index 75985c285ec3b12f9b62b396ea8e87353cd5960f..06078eef2c618c94a8d7a3649bdf9770e333a676 100644
--- a/client/client.js
+++ b/client/client.js
@@ -316,8 +316,8 @@ function redrawLinks() {
         svg.removeChild(svg.firstChild)
     }
     // draw origin 
-    var og1 = newLine(20, 30, 40, 30, 3, false)
-    var og2 = newLine(30, 20, 30, 40, 3, false)
+    var og1 = newLine(-20, 0, 20, 0, 3, false)
+    var og2 = newLine(0, -20, 0, 20, 3, false)
     // find that link
     var lnkPt
     var nLnk = 0
diff --git a/client/index.html b/client/index.html
index 813bbb18924f601da18a8212991e02c52f182fca..3743ec9f97be8d80e5690eeeaac28740c7ab511d 100644
--- a/client/index.html
+++ b/client/index.html
@@ -10,7 +10,8 @@
     <script type="text/javascript" src="divtools.js"></script>
     <script type="text/javascript" src="client.js"></script>
     <div id = "nav">
-    	<p>'l' for load program, 's' for save program, right-click or 'm' for add module menu</p>
+    	<a href = "https://gitlab.cba.mit.edu/jakeread/rndmc">RuNDMC</a> | 
+    	'l' for load program, 's' for save program, right-click or 'm' for add module menu
     </div>
 </body>
 
diff --git a/client/style.css b/client/style.css
index a06a9b955ab4e0aa5ed53f1b5f82bdc473a98914..e6045c5d8b252eba98e3ce76eea2a4fe82d11779 100644
--- a/client/style.css
+++ b/client/style.css
@@ -97,6 +97,20 @@ textarea {
 	clear: both;
 }
 
+#nav {
+	padding: 5px;
+	padding-right: 15px;
+	background-color: #303030;
+	color: #eee;
+	font-size: 15px;
+	position:absolute;
+	z-index: 1000;
+}
+
+#nav a{
+	color: #eee;
+}
+
 ul {
 	list-style-type: none;
 	font-size: 15px;
@@ -142,8 +156,4 @@ li:active{
 	width: 80px;
 	padding: 3px;
     background-color: #303030;
-}
-
-#nav {
-	font-size: 15px;
 }
\ No newline at end of file
diff --git a/modules/hardware/atkmrobot.js b/modules/hardware/atkmrobot.js
index f80497b6a078c43b35cc1deecc8fc3fa38236b01..fb7a9cbb65269e689c38af8b04aa01339827ee4e 100644
--- a/modules/hardware/atkmrobot.js
+++ b/modules/hardware/atkmrobot.js
@@ -8,9 +8,20 @@ let Button = JSUnit.Button
 const Hardware = require('../../src/atkunit.js')
 const PCKT = require('../../src/packets.js')
 
+// interface elements
+const JSUI = require('../../src/jsui.js')
+let UI = JSUI.UI
+
 // a constructor, a fn, a javascript mess
 function ATKMathRobot() {
 
+    // TODO:
+    // add small filter to PID / D-term 
+    // add deadband option?
+    // do chart-tune 
+    // tune ... and take video
+    // do three.js 
+
     // we make the module, starting from this base 
     // '0,1' is the route to our piece of hardware
     // 'onPacket' is the function that will be called
@@ -22,6 +33,7 @@ function ATKMathRobot() {
 
     // inputs and outputs as usual 
     atkmr.inputs = {
+        tick: Input('event', onPositionTickTock),
         pc_t: Input('number', onPositionTargetInput)
     }
     atkmr.outputs = {
@@ -29,19 +41,43 @@ function ATKMathRobot() {
     }
 
     // and state as well 
-    var state = atkmr.state 
+    var state = atkmr.state
 
     state.message = 'no packet yet'
     state.pc_t = 2048
     state.onUiChange('pc_t', onPositionTargetUserChange)
     state.walk = 1024
-    state.tickButton = Button('Walk Value', onPositionTickTock)
+
+    state.pKp = 4.5
+    state.onUiChange('pKp', onKValsUpdate)
+    state.pKi = 0.0
+    state.onUiChange('pKi', onKValsUpdate)
+    state.pKd = 0.0
+    state.onUiChange('pKd', onKValsUpdate)
+    state.cKp = 4.0
+    state.onUiChange('cKp', onKValsUpdate)
+    state.cKi = 0.0
+    state.onUiChange('cKi', onKValsUpdate)
+
+    atkmr.ui = UI()
+    var ui = atkmr.ui
+    ui.addElement('walkValButton', './ui/uiButton.js', onPositionTickTock)
+    ui.walkValButton.onload = function() {
+        ui.walkValButton.setText('walk value')
+    }
 
     // to send things down the well, we can use
     // atkmr.route.send(packet) 
     // where packet is a byte array
 
-    function onPositionTargetInput(evt){
+    function onKValsUpdate() {
+        var pckt = [144]
+        pckt = pckt.concat(PCKT.packFloatTo32(state.pKp, true), PCKT.packFloatTo32(state.pKi), PCKT.packFloatTo32(state.pKd), PCKT.packFloatTo32(state.cKp), PCKT.packFloatTo32(state.cKi))
+        console.log('pckt like', pckt)
+        atkmr.route.send(pckt)
+    }
+
+    function onPositionTargetInput(evt) {
         console.log("INPUTS NOT YET BOUND", evt)
     }
 
@@ -60,11 +96,11 @@ function ATKMathRobot() {
         atkmr.route.send(pc_tpack)
     }
 
-    function onPositionTickTock(){
+    function onPositionTickTock() {
         var pc_t = state.pc_t
         pc_t += state.walk
         pc_t %= 16384
-        state.pc_t = pc_t 
+        state.pc_t = pc_t
         onPositionTargetUserChange()
     }
 
@@ -72,10 +108,12 @@ function ATKMathRobot() {
     // subscribe, where 141 (here) is the 'key' 
     // we're looking for on the network, and the 
     // msg is byte array we'll get back
-    atkmr.route.subscribe(143, function(msg){
+    atkmr.route.subscribe(143, function(msg) {
         state.message = 'packet ok'
     })
 
+    atkmr.go = onKValsUpdate
+
     return atkmr
 }
 
diff --git a/modules/hardware/atkseriallink.js b/modules/hardware/atkseriallink.js
index 4c637fe583a62452341f9ed79ab20cb51392a69f..5cbabb184af5137ad9eb457f5c73b6655945e86d 100644
--- a/modules/hardware/atkseriallink.js
+++ b/modules/hardware/atkseriallink.js
@@ -242,6 +242,10 @@ function ATKSerialLink() {
         // console.log('shifted', pckt)
     }
 
+    // make program-available
+
+    atkSerialLink.startUp = findSerialPort
+
     return atkSerialLink
 }
 
diff --git a/rundmc.js b/rundmc.js
index 0e9922f09af5127ece32d54ec1151574bb0d99b2..e1d6cbf4a7529904512b40efe19ca12d4a9767f0 100644
--- a/rundmc.js
+++ b/rundmc.js
@@ -31,6 +31,24 @@ const Programs = require('./programs.js')
 // the program object: real simple, just has a description, and a 'modules' 
 var program = Programs.new('new program')
 
+var link = Programs.loadModuleFromSource(program, './modules/hardware/atkseriallink.js')
+link.startUp()
+
+link.description.position = {
+	left: 600,
+	top: 50
+}
+
+var mrbot = Programs.loadModuleFromSource(program, './modules/hardware/atkmrobot.js')
+
+mrbot.description.position = {
+	left: 20,
+	top: 50
+}
+
+mrbot.go() 
+
+
 /*
 var stest = Programs.loadModuleFromSource(program, './modules/ui/stest.js')
 
diff --git a/src/jsunit.js b/src/jsunit.js
index f1e4f2d8b272733440a7d3baec345e817c25f766..19fa14b105c622132e5faa5fd72a5a5112100a7a 100644
--- a/src/jsunit.js
+++ b/src/jsunit.js
@@ -88,7 +88,7 @@ function State() {
     }
 
     state.pushToUI = function(key) {
-        if (this.socket) {
+        if (this.socket.send != null) {
             var data = {
                 id: this.parentId,
                 key: key,
diff --git a/src/packets.js b/src/packets.js
index ad63359112614e31333d930278a84e9f2ee26a45..53d3a22df303f5d55a3aa1aca43ede2f96135350 100644
--- a/src/packets.js
+++ b/src/packets.js
@@ -15,10 +15,34 @@ function unPack32(arr){
 	} else {
 		console.log("ERR: arr > 4 at unPack32", arr)
 	}
-	
+}
+
+function packFloatTo32(val, debug){
+	// https://www.h-schmidt.net/FloatConverter/IEEE754.html
+	var f = new Float32Array(1) 
+	f[0] = val 
+	var view = new Uint8Array(f.buffer)
+	if(debug) printViewBytes(view)
+	var pack = new Array()
+	pack[0] = view[3]
+	pack[1] = view[2]
+	pack[2] = view[1]
+	pack[3] = view[0]
+	return pack 
+}
+
+function printViewBytes(view){
+	for(i = view.length - 1; i >= 0; i --){
+		var bits = view[i].toString(2) 
+		if(bits.length < 8){
+			bits = new Array(8 - bits.length).fill('0').join('') + bits
+		}
+		console.log(bits)
+	}
 }
 
 module.exports = {
 	pack32: pack32,
-	unPack32: unPack32
+	unPack32: unPack32,
+	packFloatTo32: packFloatTo32
 }
\ No newline at end of file