README.md 15.3 KB
Newer Older
Jake Read's avatar
Jake Read committed
1
# RNDMC
Jake Read's avatar
Jake Read committed
2

Jake Read's avatar
Jake Read committed
3 4 5
**Reconfigurable Numeric Dataflow Machine Controller**

*aka project 'consistent-sandbox'*
Jake Read's avatar
Jake Read committed
6

Jake Read's avatar
Jake Read committed
7 8
![img software](doc/images/atkapi.png)
![img hardware](doc/images/machine-with-atkapi.jpg)
Jake Read's avatar
Jake Read committed
9

Jake Read's avatar
Jake Read committed
10 11 12 13 14 15
This is a piece of software that is designed to help you assemble high level controllers from dataflow software elements. It serves a graphical programming interface, and is meant to live with dataflow hardware elements from [this project 'automatakit'](https://gitlab.cba.mit.edu/jakeread/automatakit).

It's in the early stages, so bear with us. Everything is going to be great. 

# Usage 

Jake Read's avatar
Jake Read committed
16
## Installing Node.js, WebSocket and SerialPort, and MathJS
Jake Read's avatar
Jake Read committed
17 18 19

To Run DMC, you'll need to install node.js, and then the packages serialport and ws (websocket).

Jake Read's avatar
Jake Read committed
20
### Install Node.js
Jake Read's avatar
Jake Read committed
21 22 23 24 25 26 27 28 29

Node.js is a runtime environment for javascript, so you can write and run js locally. [Download and install it here](https://nodejs.org/en/download/). 

To check that node is installed, you can use

``node -v``

In Windows check that in *Environment Variables, System Variables, Path* there is a path for C:\Users\yourusername\npm folder. If the folder does not exist, create it and set the path.  

Jake Read's avatar
Jake Read committed
30 31 32 33 34 35 36 37
### Packages

I've added a package.json file to the repo, which is [another cool node.js trick](https://docs.npmjs.com/files/package.json) - this means that to install everything, you should be able to (after downloading the repo and cd-ing into it) run:

```npm install```

This should install everything else. If this fails, you can install things one-by-one as listed below.

Jake Read's avatar
Jake Read committed
38
### Install Serialport
Jake Read's avatar
Jake Read committed
39 40 41 42 43 44 45 46 47

Node comes with a package controller called 'npm' - node package manager. You can use this to install dependencies for node programs. 

Serialport is a package for node that allows it to interact with a hardware serial port.

Navigate to the directory where you'll be running from (atkapi). Do

``npm install serialport``

Jake Read's avatar
Jake Read committed
48
### Install WS (WebSocket)
Jake Read's avatar
Jake Read committed
49 50 51 52 53 54

WebSockets are very simple web connections. We use them to chat between the 'server' / heap (node) and the 'view' (your browser).

To install ws, do

``npm install ws``
Jake Read's avatar
Jake Read committed
55

Jake Read's avatar
Jake Read committed
56
### Install MathJS 
Jake Read's avatar
Jake Read committed
57 58 59 60 61

MathJS is just a node package that does maths. To install, you guessed it, do

```npm install mathjs``` 

Jake Read's avatar
Jake Read committed
62 63 64 65 66 67 68 69
## Installing Serial Port Drivers

The ATKRouter uses a ```CP2102N``` USB-to-UART bridge to transmit and receive serial characters. 

[**Drivers are available for all platforms at SiLabs' Website**](https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers)

Download and install drivers, and check in your system's device manager that a 'CP210x USB to UART Bridge' appears.

Jake Read's avatar
Jake Read committed
70 71 72
# Running DMC

To run the program, we launch the main.js file with node, from the command line. One of the things this does is run a tiny HTTP server that we can use to access the UI.
Jake Read's avatar
Jake Read committed
73

Jake Read's avatar
Jake Read committed
74 75
cd to the rndmc folder and run: 

Jake Read's avatar
Jake Read committed
76
``node rundmc``
Jake Read's avatar
Jake Read committed
77 78 79

It's handy to keep a terminal window open beside a browser when running the software - it's not perfect yet - I do this:

Jake Read's avatar
Jake Read committed
80
![term](doc/images/termopen.png)
Jake Read's avatar
Jake Read committed
81 82 83 84 85 86 87 88 89 90

This way I can watch for errors, and restart it when it crashes. Hopefully not a lot of this will happen.

## Open a Browser

The program is now running a tiny HTTP server, where it will deliver an interface. It's set to show up at your local address on port 8080.

In a browser open *localhost:8080* you will see the mods and this msg in the terminal *SEND PROGRAMS TO UI* 

## Using the Browser Interface 
Jake Read's avatar
Jake Read committed
91

Jake Read's avatar
Jake Read committed
92
![img moving](doc/images/mothermother.gif)
Jake Read's avatar
Jake Read committed
93

Jake Read's avatar
Jake Read committed
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
**Words of Warning** 

This is very new software, so bear with me. It's worth having whomever on the team is in charge of controls read the section (below) on what-all is going on with the software, and understanding how to write new modules, and assemble programs. 

#### Getting Around

To navigate, you can scroll in-and-out (try this once there is actually a program loaded) and drag to pan around.

#### Loading a Program

To load a program, hit 'l' on your keyboard. This will open a menu of all of the .json program representations in the /programs directory.

There is an example program there, that will do acceleration-controlled motion with gcode as input. 

#### Loading a Module

To load a module, right-click anywhere on the screen. 

#### Deleting a Module

To delete or copy a module, right-click on its title. 

#### Connecting Outputs to Inputs

Once loaded, modules can be connected by first clicking on the *output* of one and the *input* of another. This will cause events on that output to call events associated with the input.

#### Disconnecting Outputs from Inputs

To disconnect, click the output to disconnect, and then the input to disconnect it from. 
Jake Read's avatar
Jake Read committed
123

Jake Read's avatar
Jake Read committed
124 125
# Troubleshooting

Jake Read's avatar
Jake Read committed
126 127 128 129
- ?

# RuNDMC Architecture 

Jake Read's avatar
Jake Read committed
130
![arch](doc/images/rndmc-architecture.png)
Jake Read's avatar
Jake Read committed
131

Jake Read's avatar
Jake Read committed
132 133 134 135 136 137 138
Above is a somewhat-complete representation of what-all is going on in software.

Essentially, we load tiny programs (```modules/sub/modulename.js```) using node.js's *require* function. These programs each have inputs and outputs, and some state. Each also has a description (an example of a complete module is below).

The UI serves a representation of this through a websocket.

Pardon my at-the-moment brief explanation. 
Jake Read's avatar
Jake Read committed
139

Jake Read's avatar
Jake Read committed
140 141
# Writing New Modules 

142
Whenever a menu is requested, the system searches ```modules/ * ``` for *anything*. When you write a new module, just include your newmodule.js there, and the program should find it.
Jake Read's avatar
Jake Read committed
143 144 145 146 147 148 149

These modules are written with objects inherited from ```lib/jsunit.js``` 

Here's an example. This is modules/ui/number.js. 

Besides Inputs, Outputs, a Description and State object, anything else goes. I.E. local functions, other Node.JS packages, etc.

Jake Read's avatar
try js  
Jake Read committed
150
```javascript
Jake Read's avatar
Jake Read committed
151
// boilerplate rndmc header
Jake Read's avatar
Jake Read committed
152 153 154 155 156
const JSUnit = require('../../src/jsunit.js')
let Input = JSUnit.Input
let Output = JSUnit.Output
let State = JSUnit.State
let Button = JSUnit.Button
Jake Read's avatar
Jake Read committed
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

// a constructor, a fn, a javascript mess
function uiNum() {

    // this is the tiny program-as-and-object that we'll load into rundmc 
    // description / name is required to load successfully 
    var uinum = {
        description: {
            name: 'number-output',
            alt: 'for clicking'
        }
    }

    // the State() object is what the system scrapes for ui variables / updates from the UI
    // this includes things like Button('title', callback), which are unique state variables
    // they can also be found in jsunit.js 
    uinum.state = State()
    // alias !
    var state = uinum.state 

    state.number = 10
Jake Read's avatar
Jake Read committed
178
    state.onUiChange('number', onNumberDesire)
Jake Read's avatar
Jake Read committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214

    state.button = Button('WHAM', onNumberDesire)

    // inputs are required, and must be Input('type', callback) 
    uinum.inputs = {
        thru: Input('any', onThruInput), // makes anything into num event 
        evt: Input('any', onNumberDesire)
    }

    // outputs: Output('type')
    uinum.outputs = {
        out: Output('number')
    }

    // here's our input callback, specified in the input constructor 
    function onThruInput(input){
        if(typeof input == 'number'){
            state.number = input
        } else {
            state.number = parseFloat(input)
        }
        onNumberDesire()
    }

    function onNumberDesire(){
        // here's how we fire an output. 
        uinum.outputs.out.emit(state.number)
    }

    // gotta give the program this thing we made 
    return uinum
}

// this for node.js's require() function 
module.exports = uiNum
``` 
Jake Read's avatar
Jake Read committed
215 216 217

# Writing Hardware Modules 

Jake Read's avatar
Jake Read committed
218
Hardware Modules are identical to other modules, but they inherit a class that can be found and examined at ```lib/atkunit.js``` which subsequently calls hardware-interfacing classes from ```lib/atkroute.js``` and often use tools from ```lib/packets.js``` (packets.js is mostly about packing 64-bit information into byte-size units).
Jake Read's avatar
Jake Read committed
219

220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
# Programatically Connecting and Loading Modules

We can also write and manipulate modules as software objects. This is sometimes very nice.

I.E. here is 'main.js' as configured to run the small program described.

```javascript

// business 
const Reps = require('./reps.js')
const Programs = require('./programs.js')

// the program object: real simple, just has a description, and a 'modules' 
var program = Programs.new('new program')

/* example program-like-an-api */
// load some modules
var multiline = Programs.loadModuleFromSource(program, './modules/ui/multiline.js')
var gcode = Programs.loadModuleFromSource(program, './modules/parsing/gcode.js')

// attaching: always like outputs to inputs
multiline.outputs.lineOut.attach(gcode.inputs.lineIn)

// we can move things around here as well
multiline.description.position = {
    left: 50,
    top: 50
}

gcode.description.position = {
    left: 500,
    top: 100
}

// if I have a public function in a module, I can also use that
multiline.load('./files/dogbone.gcode')

// UI 
const View = require('./views.js')
View.startHttp() 
View.startWs() 

Programs.assignSocket(View.uiSocket)
View.assignProgram(program)
```

Jake Read's avatar
Jake Read committed
266 267
# Development Notes 

Jake Read's avatar
Jake Read committed
268
## Immediately
Jake Read's avatar
Jake Read committed
269

Jake Read's avatar
mvrobot  
Jake Read committed
270 271 272 273
- nice work on generic ui classes / ui.thing.call('function', arg)
- finish robot flow: offsets, ok, 100ms updates, ok
 - forward transform object -> three.js canvas
 - do key-binding ui for robot jogging, write video 
Jake Read's avatar
Jake Read committed
274 275 276
- three robot canvas 
- set module display width 

Jake Read's avatar
Jake Read committed
277 278
- saved program doesn't save state booleans 

Jake Read's avatar
Jake Read committed
279 280 281
- ui objects ... refresh ... use state model ? 
- ui objects client drop below inputs / outputs 

Jake Read's avatar
Jake Read committed
282
- ui / button 
Jake Read's avatar
Jake Read committed
283

Jake Read's avatar
Jake Read committed
284 285
- svg doesn't display on chrome 

Jake Read's avatar
Jake Read committed
286 287
- would like to send board with new buck out to fab
- just do stepper23, bc if that's it, that's it ?
288

Jake Read's avatar
Jake Read committed
289 290
- tuning:
 - mrobot having PI, PID terms
Jake Read's avatar
Jake Read committed
291
 - probably good to do a remote-get ... 
Jake Read's avatar
Jake Read committed
292 293 294 295 296
 - having position-set input (also gets output?)
 - having position-actual output
 - graphing these things
 - use UI slider (external) to set PID terms?
 - should be able to use the same slider element directly inline 
297

Jake Read's avatar
Jake Read committed
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
- cleaning up reps 
- looking for heirarchy demonstration 
- imagining microcontrollers 
- working on robot to inform desires: i.e. ui charts and graphs 

## For Madison Park

- want that better-planner, better-stepper, better-inputs and graphic ui w/ 3js 
- want network to not blow
 - tokens w/ crc bit-level ? 
 - app does keepalive / green-when-on etc ? 
 - example of setup-for-consistent-feedback of variable, on a timer? tuning loops ... search ... 
- do axis pullout separately from stepper motor ? accel command ? deep jog desire ... architecture still messy though

- bug hunting
 - multiline change input paste doesn't work ... big state problem 
 - is load / save really consistent ? what is the state answer ? 
 - expected behavior: pressing the button on the raw move module should result in a move for every button press
 - observed behavior: to send another raw move (via the button on the raw move module), we must reset the motor drivers.
Jake Read's avatar
notes  
Jake Read committed
317

Jake Read's avatar
Jake Read committed
318
- add router for reset, test 
319

Jake Read's avatar
Jake Read committed
320 321 322 323
## Forever

- open the door, no cuffs 
- option for 'native' multithreading by opening workers on each event ?
Jake Read's avatar
Jake Read committed
324

Jake Read's avatar
Jake Read committed
325
## Questionable Moves
Jake Read's avatar
notes  
Jake Read committed
326
- module deletion seems unclean 
Jake Read's avatar
Jake Read committed
327
 - input / output objects should be able to unhook themselves: 
Jake Read's avatar
notes  
Jake Read committed
328
 - keep references of what-is-attached ? 
329
 - would like to be able to default prevent state variables from being changed by users, i.e. in 'collector' the 'count' variable 
Jake Read's avatar
Jake Read committed
330

Jake Read's avatar
Jake Read committed
331 332 333 334 335 336 337
## WRT Representations

Module have 
 Inputs
 Outputs
 State (initial states are settings)

Jake Read's avatar
notes  
Jake Read committed
338 339 340 341 342
Hardware Modules have
 routes
 connected to 
 links 

Jake Read's avatar
Jake Read committed
343 344 345 346 347 348
Also
 Names, IDs
 Paths-to-source 

To assemble a representation of these, we want to have a kind of 'netlist' that, for convenience, we'll treat like a JSON object. We want heirarchy, so consider the representation having 'top-level' outputs / inputs / state as well ? 

Jake Read's avatar
Jake Read committed
349
## Programming Notes
Jake Read's avatar
Jake Read committed
350

Jake Read's avatar
Jake Read committed
351 352 353 354
### 15 Minute Tasks 
 - @ views.js, uiRequestModuleMenu and uiRequestProgramMenu don't properly build trees from folder structure. similarly, reciprical fn's in client.js do the same 
 - @ these load / save functions could also reach into the modules' source to retrieve their proper names, as spec'd in description ... 
 - 's' for save program uses hack-asf DOM alert to ask for path
Jake Read's avatar
Jake Read committed
355

Jake Read's avatar
notes  
Jake Read committed
356
## Desires 
Jake Read's avatar
Jake Read committed
357 358 359 360 361
- reload / edit individual modules ? 
- modules spawn new inputs / outputs ? 
- big UI ? 
 - arrows catch for jogging 
- editing ? 
Jake Read's avatar
Jake Read committed
362
- heirarchy zoom 
Jake Read's avatar
notes  
Jake Read committed
363
 - architectural clarity betwixt UI and Heap 
364
- some auto load / save currently.json file so that we can restart program w/o pain ... maybe just save on new user inputs ? 
Jake Read's avatar
Jake Read committed
365 366
- state.setDefault('var', num) or etc / types
- perhaps all state objects like this ... still somehow state.var = // is a good operator ? don't really want state.var.set(num) and state.var.get() 
Jake Read's avatar
Jake Read committed
367 368 369 370 371 372 373
- states / uis / etc - one off / one-at-a-time for updates 
 - i.e. all f'n update calls are to single module-global state update
 - ! 
- states / getters / setters not applicable to sub-elements in an object within state
 - i.e. array access 
- consistent dereferencing, type checking implementation?

Jake Read's avatar
notes  
Jake Read committed
374
## UI Desires
Jake Read's avatar
Jake Read committed
375
- scroll / grab events for touchpads etc ... find a mac user and workshop this for one afternoon ? 
Jake Read's avatar
notes  
Jake Read committed
376 377 378 379 380 381
- modules have visual ways to throw errors - i.e. flashing red, popping up... 
- off-screen divs get pointers-to so that we don't get lost
  - 'h' or something to zoom-to-extents
- better module menu
- hover for alt descriptions 

Jake Read's avatar
Jake Read committed
382 383
## Planner Bugs
 - trapezoid linking doesn't account for speed changes properly, i.e. doesn't ramp down into next move if next move's cruise speed is less than our exit speed 
Jake Read's avatar
notes  
Jake Read committed
384
 - should have some stronger ideas about flow control, allowable segment size (based on time) 
Jake Read's avatar
Jake Read committed
385

Jake Read's avatar
notes  
Jake Read committed
386
## Want 
Jake Read's avatar
Jake Read committed
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
- log() for logs-from-module tagged 

## Demo Desires 
- want to show immediacy of hardware: software representation
- want to show physical reconfigurability and software reconfigurability
 - i.e. mill, add rotary tool, pull normal vector from planner moves and route to r motor 
- want to have UI elements
 - button, terminal, 
- live motor torque display, vector from accelerometer 

## Network Desires
- c improvements / dma etc, would be very cool
- flow control probably desired ... what can we model with uart and implement with fpga?
- proper speed tests
- DMA not possible / not enough channels for router implementation / not portable enough ... 
- lights displaying activity

## Bugs
- cannot connect input to output w/o backwards bezier 
Jake Read's avatar
Jake Read committed
406
- when source has changed, opening programs that have references to that source should be carefully done ... 
407

Jake Read's avatar
Jake Read committed
408 409
# The RPI

Jake Read's avatar
Jake Read committed
410 411 412 413
One of the desires here is to run programs headlessly on small embedded computers like the Raspberry Pi. The router has pogo-pins for this, so that when it's mounted beneath a Raspberry Pi the USB and Power lines are automatically hooked up - the 2A Buck Converter on the Router can also be used to power the RPI, so it can all run on one DC power bus. Nice! 

![ATKRouter](https://gitlab.cba.mit.edu/jakeread/atkrouter/raw/master/images/atkrouter.jpg)

Jake Read's avatar
Jake Read committed
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
### Setup the Raspberry Pi

 - [download raspbian](https://www.raspberrypi.org/documentation/installation/installing-images/README.md)
 - [flash and boot, setup etc](https://www.raspberrypi.org/documentation/setup/)

### Install Node on the Raspberry Pi

 - to install node, download the distro you want from nodejs.org 
 - extract the files, and hit these commands

navigate to the distribution
`` cd <distro> `` 
copy that to local space on the pi
`` sudo cp -R * /usr/local/ ``

to check that node is installed, check the version using
`` node -v ``
which should return the version number of the distro you installed.

Jake Read's avatar
Jake Read committed
433 434
However:

Jake Read's avatar
notes  
Jake Read committed
435
``` need to figure out how to get the RPI serialport to talk ``` 
Jake Read's avatar
Jake Read committed
436 437

- https://cnc.js.org/ 
Jake Read's avatar
Jake Read committed
438 439 440
- https://github.com/cncjs/cncjs/wiki/Setup-Guide:-Raspberry-Pi-%7C-Install-Node.js-via-Node-Version-Manager-(NVM)