Commit cfdcc54a authored by Jake Read's avatar Jake Read
Browse files

rm firmware typo

parent adae9790
# APA Packets
apa_end_addr_delimiter 255
apa_addr_pointer 254
apa_addr_flood 253
packet like "len,port,port,ptr,port,etc,end_addr_delimiter,package..."
package like "key:type:bytes[1-6]" to do types like byte, uint16_t, 32, long, etc
Stepper:
steps : int32_t : bytes[0-3]
speed : int32_t : bytes[0-3]
steps: 127
speed: 128
uint8_t: 0
int8_t: 1
uint32_t: 2
int32_t: 3
float: 4
double: 8
# Code for APA
Implements uartport from [mkstepper](https://gitlab.cba.mit.edu/jakeread/mkstepper/tree/master/embedded).
## Hardware | Software
Each device has hardware registers that need to be written / read in order to really 'do the business' of putting data on the UART line. My implementation is like this, per port:
Asynchronously:
- RX and TX lines both have a ringbuffer at their head.
- On an RX Interrupt, incoming data is unceremoniously dumped into the ringbuffer. There is currently no protection from an overfull buffer. Instead, they are [just very big](http://shrugguy.com).
- When there is data in the TX buffer the TX Interrupt is turned on. Whenever the transmitter is ready to put a new byte on the line, that interrupt handler fires. It polls the buffer: if there is data there, it puts it on the line. If there is no data there, it turns the TX Interrupt off.
This means that the application can be hard-at-work-doing-stuff when data is flying into *and* out of the uart peripheral. For each microcontroller, I write a **uartport.h** structure that is home to one Port with two Ringbuffers (ringbuffer.h). This library is hardware specific, and I'll write one for each micro we put on the system. API is like this:
**uart_new(device specific)** returns a new port structure
**uart_init(uartport_t * uart, device specific)** boots it up
**uart_sendchar_polled(uartport_t * uart, uint8_t byte)** circumvents buffers and puts a byte right on the port
**uart_sendchar_buffered(uartport_t * uart, uint8_t byte)** puts a byte in the tx buffer
**uart_sendchars_buffered(uartport_t * uart, uint8_t * bytes, uint8_t length)** puts an array of bytes on the tx buffer
To look for bytes in the RX Buffer, we do:
```C
if(!rb_is_empty(uartport->rbrx)){ // if non-empty ringbuffer
uint8_t newbyte = rb_get(uartport->rbrx); // get a byte
// now we can do stuff
}
```
## Packet Handling
Now I have to write an APA library. Here's some psuedocode for what I imagine that will do:
To handle packets, we call this function as often as is reasonable:
**apa_handle_packets(maxpackets, ports, num_ports);**
- maxpackets: the # of packets, per port, to handle in one call
- this is to prevent a deluge of packets suddenly appearing on the port from locking the application up for an unexpected amount of time. each packet will take some time (hopefully not a lot!) to handle.
- ports: the ports, as uartport structures, over which to search for packets
- numports: the number of ports in the array of ports to pass, so that I don't have to write a class of 'ports' that also contains a length. I could also do some size_t skullduggery and use sizeof() on the object, but no thanks.
Per port, this will loop over the ringbuffer and build packets. Packets look like this:
> {num_bytes | next_ports[], pointer, previous_ports[] | end_addr_delimiter | | message}
We loop through the bytes, and store the packet in memory.
Where we find that the pointer is right in front of the end_addr_delimiter, we know the packet is addressed to this device. We take the num_bytes_message as a counter, and decrement it as we pull through the ringbuffer. We store this packet and **raise a flag for handling it.**
Where we find the pointer is not in front of the end_addr_delimiter, we take the next byte in line to be the port we'll forward the packet on. We do the same as above, storing bytes in memory until we reach the end of the packet as per num_bytes_message. If we find the end, we put the packet on the port using uart_sendchars_buffered() (incrementing the position of the pointer, recording which port this came in on), and we're done.
If we find a 'flood pointer' in the next byte after the delimter, we get the rest of the packet (incrementing the position of the pointer, recording which port this came in on), and put send it out on all of the ports.
If we're reading from the buffer and don't get to the of a packet, we can assume the port is still collecting data, and we can exit the loop (using a state machine, next time we run this loop we'll just continue until we reach the end).
That's about it. It should be fairly simple. I'll guess that I'll build a packet_t type, giving each port one of these (I want to stick to a static memory) and clearing / re-writing it each time a packet is handled. I can use that structure to store state for looping in / out of packets as mentioned.
# Application
From APA, I'll expose:
**apa_has_packet()** should return the number of new packets, parsed during apa_handle_packets(), that the application needs to handle. I can keep those in an array of packets and simply handle them one-by-one before I call the next apa_handle_packets() loop.
**apa_packets[]** the array of packets to handle in the application, each containing a message of some length. Stored in a an apa_packet_t struct.
## Sending Inputs and Outputs
key:value ? what of values that are some # of bytes?
key:type:value where type is int32_t, uint8_t, float, double, etc
alternately, keep state of what keys are which type.
# Mods Integration
## Endpoint Enumeration
I want endpoints to be able to tell eachother (and mods) what they can do - what their inputs and outputs are. Again, I really like what Will showed me [here](https://gitlab.cba.mit.edu/langfordw/jsonMachineInterface), but writing a whole JSON object to the serial line is a lot of chars. I imagine that before asking for enumeration I'll do graph reconstruction, so I can ask one at a time.
Then I might ask each hardware endpoint for each of its inputs with some command. In this case they reply with key:type:value:strlength:strdescription where strdescription are the words we put beside the output / input, strlength the length of that description (for parsing). Then we can populate a new mod with these things, and use that description to send key:values during operation.
## Graph Reconstruction
This one's tricky.
Send a flood to all nodes, requesting that they pass the packet back (as well as flood-forwarding it) along the route it appeared. Due to the flooding, each node will receive that request multiple times. Perhaps I send a request ID as well, and have them only reply to one of these requests per second, or so. That way I should receive only one reply from each endpoint. I'll get back a graph that *probably* reflects minimum-paths to each endpoint.
Or, I'll get a list of routes to a list of endpoints. Then, perhaps, it would not actually be very hard to build a graph from these lists, combining branches of the tree recursively. There's probably a good way to loop through branches and do this, combining like paths.
Then I will have to do some mods-architecture-skullduggery to spawn and place mods.
# That's It?
Once I have these things in place, I think I'm off to the races making mods more granular, designing, building and programming example endpoints, and trying to build fun systems.
# Spirals
So, doing this all in one shot is unreasonable. Here's what I'm thinking for development spirals:
- build out APA embedded code, and send LED on / off values to stepper boards across graphs using terminal script
- pre-program key;values for stepper and bldc drivers, and use simple terminal command to tell them to go places one-at-a-time.
- pre-program virtual mods hardware objects for the above, and without any discovery, use mods to write packets to them for positioning
- do either endpoint enumeration script with existing graph structure or graph discovery first, then do the other.
- do network machine control: kinematics somewhere, motion elsewhere, using mods as interface
- races
# The Prgmeming
I'm currently just getting my head back into javascript. This required a hard reset last night, wherein I stared at the screen for a while, scratched my head, drew some things on the whoteboard, gave up.
I installed these sublime packages to make Neil's code more readable:
https://packagecontrol.io/packages/StandardFormat
and
https://packagecontrol.io/packages/HTML-CSS-JS%20Prettify
Sublime Text is rad. I paid them money.
To spiral in, I'm going to write a stepper mod that takes input from mods and outputs a packet to the serialport that tells the stepper to do that. This is a reasonable re-introduction to javascript.
Could have a kind of 'pointer' to each object, which just sends things along as packets - here is where we have network knowledge ?
Do I want a drum machine? Yes. Write text mod that does polyrhythms, on a delay, writes those to some set step sequence (also a mod?) sends packets down network...
- be satisfied with stepper endpoint that pumps to serialterm
- draw as-fungible-as-possible drummachine:
- evt to drop syncs
- per-stepper syncbits (0100110) that generates step sequence per 0 or per 1
\ No newline at end of file
## What is MKXM?
A networking technology for very-fast asynchronous message passing.
A flexible, expanding set of hardware endpoints for said network.
An IDE & Interface for distributed computing and control.
## Why do we think we want this?
Hardware is complicated. Building automation systems is expensive, requires expertise, and prevents beginners designers and entrepreneurs from meaningfully participating in the manufacturing economy.
Ibid robotics.
## Why do we think this is the answer?
Modern datacenter (hardware and software) architectures are impressive models for the management of complex tasks. As robotic systems scale, we feel that a similar approach is warranted: computation and complexity can be added all modular-like, so that systems can grow and scale and change without complete re-engineering of requisite parts. In a distributed system, parts which comprise the whole are paired off piecewise: their individual complexities become tractable for beginners.
# Two Network Candidates
## Napoleon's Messenger / TinyNets
In [this implementation of a realtime network](https://gitlab.cba.mit.edu/jakeread/tinynets/tree/master), nodes use realtime, local information to make per-packet port forwarding decisions. This is a minimal state distance-vector routing protocol that allows a highly-connected network to adaptively multipath messages and find optimal paths without much overhead or any global state. As opposed to any existing multipath network technology (many are found in existing datacenter architectures), TinyNet does not require any node to have global information about network topology, and adapts to network loads in realtime. Best case re-routing protocol for existing multipath approaches incur ~200ms minimum re-routing interrupts to service.
Nodes are somewhat intelligent and have some state. Each has a unique address.
## APA
In an Asynchronous Packet Automata network, nodes have no address and are instead located by their network graph coordinates. Rather than containing a destination address, packets contain a list of ports (a route) and are forwarded along whichever port is next in the list.
APA is dirt simple (this is good)
## Transport
Both networks can be implemented with UART transport (likely candidate, bc speed, ubiquity) or with 'ATP' - asynchronous token passing, a kind of 'collaboratively clocked' serial line. Of interest in the development of the system is the development of a very-fast ATP protocol using FPGAs. While UART can run near 6MBPS with small amounts of processor overhead (a few clock cycles per byte), ATP requires some thinking on every single bit and is limited to 1/2 of the slowest participating node's ['ring speed'](https://pub.pages.cba.mit.edu/ring/). UART transport requires predetermined agreement between endpoints on the applied bitrate, which is a bummer.
## In Either Case
Network graphs can be reconstructed or discovered by sending 'flooding' packets, which return with graph (or address) information. Flooding is tricky as it requires some method for the identification of duplicate messages (which have travelled over different routes but originate and terminate at the same nodes).
# Events for Control
In either case (so far considered), endpoints have *inputs* and *outputs.* Systems are assembled by connecting outputs to inputs.
# Representation and Interface
The hardware networks presented use asynchronous event-based message passing. [Mods](mods.cba.mit.edu) uses the same, but passes messages between small javascript programs (rather than between embedded microcontrollers). The graph of these connections is displayed, and can be edited, by a human user of Mods (or by mods itself, what a trick!).
The MKXM project seeks to mesh these systems together: we want some software representation of hardware endpoints where if a user connects an 'output' of one to another's input, or to a 'mod' (a small javascript program), or from a 'mods' output to a software-representation-of-a-hardware-object, messages are then passed reliably as expected.
An example, using software mods (red) to send tuning and command values to a hardware node (black):
![whiteboard sketch](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/whiteboard-bldc.jpg)
This is largely complicated when we want to somehow remotely program hardware endpoints to send messages to eachother.
![whiteboard sketch](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/whiteboard-hardware-ambiguity.jpg)
The implementation of this system is the key design / engineering problem here, and may require some chooching of the network design.
## Passing Messages from Mods to a TinyNet System
Every hardware actor has an address, including the computer / mods node.
We have a hardware graph, discovered. Message to each hardware mod: "pls flood to your neighbours (1 hop) and report neighbours' address".
Hardwares 'serve' virtual graph objects during / after graph discovery. These graph objects display the hardware's advertized inputs and outputs.
When we connect a wire from one hardware output to another hardware input, mods (with global knowledge of the graph) sends a message to that hardware node: *please send this output event to this address.* This is a little bit non-ideal because we have to do something 'behind the scenes' (where mods sends a message to that node to update it's event-forwarding information). Some of the beauty of Mods, and something we want to carry forward, is that everything is exposed: we see all of the possible message routes, we see events fire, etc. The 'wires are cut' to begin with.
When we connect a software-mod output to a hardware input, we simply send that message to the address of the node we have plugged it in to. Only some software outputs are viable key:values.
When we connect a hardware output to a software-mod, we send a message to the hardware node: please send this output to my address.
All of these events are, well, event based. We can write script that has outputs firing on certain intervals, etc.
* critically, the 'mods' computer *does not* need to be the one sending 'system-config' type messages: i.e. pls send this message to this address. These are standard 'system' type messages and can originate anywhere. In this way we can have the self-editing graph where software can edit system: but physical transport happens god-knows-where, we just rely on Napoleon's Messenger.
## Passing Mesages from Mods to an APA System
Oddly, while TinyNet has more embedded state, it needs less embedded knowledge to successfully pass messages between nodes. Or, nodes need to find routes to get messages to where they want them to go. We can basically do the same thing above, but rather than telling embedded hardwares to send messages to a particular address, we tell them to send messages along a particular route (from their position). This is actually, maybe, quite simple. The only caveat is that, while we mentioned above that it would be easy for some hardware node to instruct another to send a message to some other address, with APA the instructing-mod would need to know enough about the graph to construct that route.
That said, we can almost consider APA a 'bare minimum transport-routing layer' and do some level-3 stuff wherever warranted - i.e. we can do a little bit of multipathing (although without packet-local information) if we see that it's worth it to gather enough information about the graph to do so.
# SO!
## Concluding (from here) and next:
While I think the Napoleon's Messenger thing is pretty cool, and probably fits some niche for embedded computing (where we have really highly connected graphs and want to sling messages really far), APA is so dirt simple (again, this is good) and probably can be made to be quite reliable. Its simplicity makes it a good candidate for one-day-maybe implementation on FPGAs (oooooh, aaaaah) and fancy things like multipathing can be written on top of it (including the realtime-decisions thing, if we add unique endpoint identification on top [addresses]).
So next step is to write (because my head is still in embedded programming land) reliable APA-type uart handlers (I hereby choose UART because of its simplicity in implementation and ubiquity and relative speed) - a small software library I can include in whatever embedded project I want to bring it to.
Then is to think carefully about how to bridge between Mods and Hardware, most of which I think I have a handle on, save for:
- Flood / Graph discovery
- How to properly terminate an APA packet (needs a length byte, I think)
- How to implement flows (pieces of packets) in APA
- Overcoming the multiple-message-delivery from flood messages without any unique message IDs?
- How to deliver really long messages, like the json packages Will uses [here](https://gitlab.cba.mit.edu/langfordw/jsonMachineInterface) being a good candidate for how hardware mods can enumerate as javascript mods
- How to tell hardware mods to pass message to other hardware mods
So, software architecture problems abound.
# Implementation
![Notes Here](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/apaapi.md)
# An Aside on Napoleon's Messenger
This is a nod to work by Manuel DeLanda, in *One Thousand Years of Nonlinear History* and *War in the Age of Intelligent Machines*. DeLanda recounts the histories of the first *global* wars (largely during the Napoleonic Wars) where for the first time, Armies were so large and complicated that ancient / medieval tactics involving the concentration of control into a singular point (say, one general with 10,000 soldiers) failed entirely - because message-delay times from the lowest levels of the battle (a solder) to the top (a general) were so large that control was impossible. Rather, armies that adopted Geurilla Warfare (where autonomy and decision making is passed to lower and lower sub-units) were incredibly successful - as they were able to adapt quickly to changing conditions, etc.
# Machine Kit X MODS
## This Week's BLDC Experiment
I'm in the process of developing a [Brushless Motor Controller](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver). While these are OK to build, in their full expression they run closed-loop control on position and current. The loops that run in these control algorithms always need to be *tuned*. I want to turn Mods into an interface for doing this!
Here's my Motor Controller (and test motor: oooh, torquey!)
![motor-test](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/motor-test-stand.jpg)
Here's a sketch of what I want to build:
![whiteboard sketch](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/whiteboard-bldc.jpg)
I did a deal of work this week bringing the motor controller online, so this part is unfortunately abbreviated. I did, however, spend some time also thinking / considering how I plan on going forwards with this system - that's all outlined below, in some detail.
## Motor Controller UART Handling
I'm using a serial port to communicate with the motor controller. My ATSAM chip has UART ports that are differentially driven, so I had to build a bridge between my FTDI chip and the ATSAM port - that's the PCB you see in the top right.
Once the UART Character appears in on the ATSAM port, I catch it with an interrupt. I'm only going to pass values like this: {key:value} - in two chars, so that's all I'm keeping track of. Once I have both of them, I process the message - in this example, I just fire them back - I'll also add some code to actually do some business - like, update a variable that's running in my motor control loop. This is *the ultimate barebones* and is an absolute minimum for what I want to do.
```C
uint8_t d1;
uint8_t d2;
int32_t dstate;
uint32_t mready;
void UART1_Handler(){
if(UART1->UART_SR & UART_SR_RXRDY){
if(dstate){
d2 = UART1->UART_RHR;
dstate = 0;
mready = 1;
} else {
d1 = UART1->UART_RHR;
dstate = 1;
}
} else {
// bail
}
}
```
Here's the motor loop that's running - at the start, I try to catch messages that are ready, and I'll do something there with the message content. I want to do this outside of the interrupt loop.
```C
while(1){
if(mready){
tp_putchar(&tp3, d1);
tp_putchar(&tp3, d2);
mready = 0;
}
// to update, must use duty update register, not just 'duty'
phaseu ++;
phasev ++;
phasew ++;
if (phaseu > 1023){
phaseu = 0;
}
if(phasev > 1023){
phasev = 0;
}
if(phasew > 1023){
phasew = 0;
}
PWM1->PWM_CH_NUM[1].PWM_CDTYUPD = PWM_CDTY_CDTY(sinelut[phaseu] * scalar / 255 + 4);
PWM1->PWM_CH_NUM[2].PWM_CDTYUPD = PWM_CDTY_CDTY(sinelut[phasev] * scalar / 255 + 4);
PWM1->PWM_CH_NUM[3].PWM_CDTYUPD = PWM_CDTY_CDTY(sinelut[phasew] * scalar / 255 + 4);
delay_us(period * 10);
if(pin_get_state(&stlr)){ // ?
pin_clear(&stlr);
} else {
pin_set(&stlr);
}
}
```
In this simple echo-test, I'm receiving some garbage on the UART line...
![garbage uart](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/uart-garbage.jpg)
I'm not sure what's up with this. I'm suspicious of the differential signalling (complexity that, I'll admit, was probably not necessary). Here's some scope traces of characters coming through that line:
![differential uart](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/uart-differential.jpg)
It actually looks OK. This is a relief. I'll try sending some characters right from the ATSAM port...
```C
tp_putchar(&tp3, 'h');
delay_ms(1);
tp_putchar(&tp3, 'e');
delay_ms(1);
tp_putchar(&tp3, 'l');
delay_ms(1);
tp_putchar(&tp3, 'l');
delay_ms(1);
tp_putchar(&tp3, 'o');
delay_ms(1);
tp_putchar(&tp3, 0x0A);
delay_ms(1);
```
Still getting some stray characters. By my calculations I should only have a 0.04% error in the baud rate, but this is worth checking with the logic analyzer.
Ah, bless Logic Analyzers - I have a framing error.
![error uart](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/uart-framing-error.jpg)
The UART on the ATSAM configures with a parity bit - I don't want this, as the FTDI is not configured as such.
I've got this sorted now, the logic analyzer seems happy, so let's see some characters:
![hello uart](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/uart-hello.jpg)
Hello to you as well!
I've had some trouble opening a serial port (on windows) with the serial server in MODS. Rather than head way into javascript land tonight, I'm going to instead take the time to wrap this and some other documentation up to a place I like it - so that I'm not rushing to do so at the end of the term. Yikes, no interface yet, despite all this rambling! :|
# Scratch for Thoughts / Writing w/r/t MKxMODS
One of my larger goals at the CBA is to 'flatten' the layers between Hardware and Software in Engineering and Design. Or maybe I mean to pull them apart and make traversal between them easier...
## Motivation
A tangential thesis of my final project, [here](https://gitlab.cba.mit.edu/jakeread/spacecadet) is that in order to do *really good* or *really interesting* design, an individual (or group of individuals) needs to traverse a large *~ design space ~*. By this I mean that we need access to the many layers at work in any given problem - and to be able to 'move about' within those layers, fluidly. This description is intentionally vague.
I want to nod first to a few broad ideas that come out of philosophy (wow!) and then get down into a particular example (one that is close to me) to explain why I think that philosophy is relevant. Then I want to present an example of an implementation of that particular example in order to close the loop.
Deleuze and Guattari were a french philosopher and psychoanalyst who wrote a work entitled 'Capitalism and Schizophenia' - a two part work, the second of which being titled 'A Thousand Plateaus'. It's a hugely dense piece of writing that lands solidly in postmodernism and post-structuralism. Critically, they write about *Assemblages* and *Smooth and Striated Space*. These are difficult to sum up, and it's kind of blasphemous to try to reduce it, but this exerpt from wikipedia does a good job at Assemblages:
>Assemblage theory provides a bottom-up framework for analyzing social complexity by emphasizing fluidity, exchangeability, and multiple functionalities through entities and their connectivity. Assemblage theory asserts that, within a body, the relationships of component parts are not stable and fixed; rather, they can be displaced and replaced within and among other bodies, thus approaching systems through relations of exteriority
Which is to say, briefly, that *things are made up from littler things*<sup>1</sup> and that those littler things can be re-made into other things. This is a familiar concept, although tangentially, to machine or systems designers - we have assemblies, subassemblies, and heirarchies that link them. Critically, assemblages can come apart and be remade.
Their discussions on Smooth vs. Striated Spaces centers around the idea of layers within systems - that some spaces are bounded by Strata - difficult to move between - and others possess a gradient-like nature, where layers flow into one another. One interesting way to consider these types of spaces is in the distinction we make between Work and Play - Work representing Striated Space and *Play describing Smooth Space.* You might see what I'm trying to get at here - in a smooth space we are free to move in all directions, in a striated space we are bounded on a particular set of axis.
## Striation in Machine Design
To rapidly spiral back to machine design, we have seen that machines, too, are assemblages and that moving between the layers that those assemblages present can be difficult. We require expert knowledge in a few domains: mechanical engineering, software engineering, electrical engineering, interface design, and then some kind of motiviation to glue them all together. At the moment, none of this seems fluid. Play seems difficult, and learning requires real dedication.
So the simple idea is to break the assemblage of a machine up into its constituent parts<sup>3</sup>, and offer a fluid system for their reassembly / dissassembly, and orientation towards the outside world - such that they might fluidly become parts in another heirarchy of assemblage (say, an individual's life as a meaninful tool for expression and enablement, or a factory floor, or a businesses' throughput, or a distributed network of similar machines). If, by now, you're thinking 'wow this guy is really going pretty far afield in order to just explain why he wants to make easier to use machines' you're partially right. However, I present the critical difference:
>Easy-to-use implies a *'green button'<sup>4</sup>* approach, where the complexities *inherent* in machine design (or any other design, for that matter) dissappear beneath the singular layer of the 'go' switch. THIS is not what we're trying to do, rather, layers of complexity are meant to be exposed to a user or a designer, and movement between them made straightforward, while **not being reduced<sup>5, 6</sup>.**
So this lays out my design exercise (some recursion here, too, haha) - wherein I will try to design and then prototype a system that makes machine design and interface fluid.
## Basically
Mods X MachineKit is a message-passing system for hardware and software. It makes it easy to send data between a system comprised of multiple hardware devices (Machine Kit(s)) and multiple software applications (Mods Blocks) - in 'realtime' (message delivery times are <1ms) in order to do motion control, etc: general physical interaction with stuff - incl. robotics, VR x Hardware, etc. MKxMODS makes it easy to do *big computation* (available on MODS Client, easily linked thereby to *really big* datacenter-type computing) in close conjunction with the *fast computation* available, and required, for the control of physical systems<sup>7</sup>.
![whiteboard sketch](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/whiteboard-first-sketch.jpg)
In this sketch, *Black endpoints are Hardware* and *Red endpoints are Software.* The graph between hardware endpoints (black lines) represents physical network topology, and the graph between software endpoints (red lines) represents message-passing topology. We can have messages pass from software to hardware, and from hardware to hardware. Ultimately, messages passed from software to hardware go through a serialport (or similar bridge) and are distributed with the realtime network. Messages passed from hardware -> hardware are passed on the realtime network as well, but MODS (software) needs to dictate how these messages flow - this is the tricky bit.
For Example:
![whiteboard sketch](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/whiteboard-hardware-ambiguity.jpg)
There's a difference between hardware routing and message-routing. We have a hardware node sending values to another hardware node, on response from a software node... etc. This is the crux of the problem. I want an *elegant* solution, easily understood...
## Statements
What I think about when I think about Mods x MachineKit:
- Mods does not exist (Mods is everywhere)
- Layers sublimate into one another: abstraction is ultimately unfriendly and complexity is to be embraced and diffused, not wrapped up and hidden.
- Accidental Deep Dives should be available to non-experts<sup>10</sup>
## Technical Challenges
The key technical discussion is about *where we do computing* and on what timescale does computing happen.... And how much computing is available where. We have a small network of multiple small processors (on the order of 120MHz, 300MHz) with very limited RAM (1Mb on the upward limit). See Footnote<sup>7</sup>.
I'm also really interested in being able to *program* hardware chips from within mods - say, open a little C editor, build and flash chips over the network. This would really 'squish the layers' together, and open a great pathway for hardware / software prototyping. It also allows for the dives we mentioned in Footnote<sup>10</sup>. I also really appreciate that this makes it easy to see what's going on - the actual network code that's running - that's part of MKxMODS - is exposed, as well, just as Mods blocks can be opened up and edited. Some notes on some kind of system for programming are here:
- could halt program, send a hex file over the network to an .sd card, qspi flash etc, and have bootloader that reads this on startup a-la smoothieboard. this way we can also save hex files from a web IDE, built on a server, load manually on cards...
- mods is address 0, on startup or on 'who r u' message, programs are setup to enumerate their events, inputs and outputs.
- when, in mods, a user connects a flow from one piece hardware -> another, mods says 'on event X fire this output to address U' - this is state we put into the hardware.
- ? the search is for elegance - try avoiding state, but this is hard to do if we want to push some intelligence into the chips?
- an argument to be made about bottlenecks, local computing... easiest way to say it is if we want to do anything faster than 1ms we have to go into the network
## MODS as it stands
MODS is an event-based, message passing, modular kit of computation components.
![mods](https://gitlab.cba.mit.edu/jakeread/mkxmods/raw/master/images/mods-as-is.jpg)
This is an excellent framework for building arbitrary workflows. MKxMODS is an attempt to integrate these computation modules with hardware modules, and to be able to move computation, and messages, fluidly between them. Interesting prior arts for this, I think, can be found in the design of Datacenter Systems and softwares - where computation can be 'load balanced' across many, many instances of a similar server.
Other 'lit review' would be a study of other graphical programming interfaces, i.e. Grasshopper and MaxMSP / PureData.
# The Machine Kit
This is probably the best place I have to start thinking about this, and writing things down concretely.
Machine Kit is what I am tentatively calling the set-of-parts that will enable arbitrary machine and automation design and implementation (and maybe robots, too). The goals are to do with what's mentioned above, and also incorporates some work on the design of physical stuff (bearings, linear ways, oh my).
Here's a brief list of the endpoints I want to develop in the next few months:
- Brushless Motor Controller
- Stepper Motor Controller
- use motor control IC and separate 'power headers'
- use ATSAMD51--- <J><18> - J is size (G: 48 pin, J: 64 pin, N: 100 pin) 18 is Flash Size (18: 256 - 19: 512 - 20: 1024KB).
- Linear / Rotary Capacitive Encoder
- Rotary Magnetic Encoder
- 'Wheel' interface - force-feedback human interface using a dial-type wheel.
- Torque / Force Sensors
- Camera!
- Displays...
- Limit Switches
# Footnotes
1. Feynman said this about Physics.
2. Or, History as if Historians were Physicists.
3. The finer-grain bits the better! This is a project or goal which has been worked on by all manner of people, including the CBA's own Nadya Peek. Lego Mindstorms comes to mind, also, as a highly successful rendition of the work.
4. This is in reference to a discussion in [Nadya Peek's](http://infosyncratic.nl/) [PhD thesis](http://cba.mit.edu/docs/theses/16.08.Peek.pdf)
5. I am also nodding to an essay by Joichi Ito entitled ['Resisting Reduction: A Manifesto'](https://pubpub.ito.com/pub/resisting-reduction/)
6. In many cases, I find Architects trying to do weird things with machines whose solutions or questions can only really be asked by altering the very low-level motion planning or control algorithms at work in the machines they are questioning.
7. As a good benchmark for speeds-we-want-to-do-stuff-at, a [closed-loop brushless motor controller](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver) needs to: read up to 6 ADCs, one rotary encoder, perform six matrix multiplications (2x2 matricies), run a PID calculation, and write 6 PWM values, within 100us at an upper bound, within 10us on a lower bound. That's 10KHz or 100KHz. That's fast! If we comprise a physical system of six of these (say, a 6DOF robot arm<sup>8</sup>), it seems unreasonable to try compiling these and running them on one processor - not only does this eliminate our ability to re-configure them, it increases the computation necessary in that system and likely brings the total loop-time up. So, we implement a network to connect them to one another and to another chip that runs a kinematics control loop, reading all 6 positions and updating target-position values at, say, 3 - 8 KHz. Here, we're doing other maths (more matricies). It's likely that we want a user interface for this system, something we can run at 1KHz or so (to keep things feeling snappy!). In addition to that, we might be doing even bigger computation, say Computer Vision or Machine Learning - here is where MODS x Machine Kit might really shine, where we use the MODS web infrastructure to loop between datacenter-size computing and the hardware endpoints. Essentially, there's a relationship between the location of computing, the speed of computing, and the amount of computing, we can have in a system. MKxMODS is an attempt to bridge these layers. Critically, rather than concentrating the complexity of the system into a single software stack and hardware implementation, we *push autonomy into the farthest reaches of the system where it can conceivably run*, thereby reducing top-level complexity into something manageable, and malleable<sup>9</sup>.
8. ooh, aah, ooooooh
9. This is a nod to work by Manuel DeLanda, in *One Thousand Years of Nonlinear History* and *War in the Age of Intelligent Machines*. DeLanda recounts the histories of the first *global* wars (largely during the Napoleonic Wars) where for the first time, Armies were so large and complicated that ancient / medieval tactics involving the concentration of control into a singular point (say, one general with 10,000 soldiers) failed entirely - because message-delay times from the lowest levels of the battle (a solder) to the top (a general) were so large that control was impossible. Rather, armies that adopted Geurilla Warfare (where autonomy and decision making is passed to lower and lower sub-units) were incredibly successful - as they were able to adapt quickly to changing conditions, etc.
10. I accidentally learned how to write C++ while I was re-jigging a piece of machine firmware to run my [5-axis mill](http://ekswhyzee.com/index.php/project/tinyfive/)
\ No newline at end of file
# What is it?
Machine API / Distributed Machine Operating System
Parametric / Declarative Hardware
# What is it for?
Distributed / Small manufacturers who want accessible automation.
Rapidly deployable fab-labs / exponentially increasing machine networks.
Education for robotics!
Complex Realtime Robotics Systems
Instrumentation and Metrology
reinventingthefutureofwork@mit.edu
Also interesting themes: when bringing production to the people, keep in mind that mass customization is what allows production to come to the lower level -- .. so this is *critical path* to successful work
# Technically
(software)
We need a rapid message passing system for decentralized control over networks.
We make no distinction between the PC or globally connected (TCP/IP network) endpoints: they are endpoints of our distributed machine that perform computation and interface.
(systems)
We need an IDE(s) for distributed machine system: one whose representation and granularity allows the rapid development of distributed systems. The representations are faithful to ground truths, and display both message paths and physical paths of the networks.
(hardware/software)
We need a method for calibrating / commissioning / tuning machines and processes. How much machine operation, firmware, model predictive control can we learn?
# Prototype
What does a prototype of meshine kit look like?
Every hardware actor has an address, including the computer / mods node.
We have a hardware graph, discovered. Message to each hardware mod: "pls flood to your neighbours (1 hop) and report neighbours' address".
Hardwares 'serve' virtual graph objects during / after graph discovery. These graph objects display the hardware's advertized inputs and outputs.
When we connect a wire from one hardware output to another hardware input, mods (with global knowledge of the graph) sends a message to that hardware node: *please send this output event to this address.*
When we connect a software-mod output to a hardware input, we simply send that message to the address of the node we have plugged it in to. Only some software outputs are viable key:values.
When we connect a hardware output to a software-mod, we send a message to the hardware node: please send this output to my address.
All of these events are, well, event based. We can write script that has outputs firing on certain intervals, etc.
* critically, the 'mods' computer *does not* need to be the one sending 'system-config' type messages: i.e. pls send this message to this address. These are standard 'system' type messages and can originate anywhere. In this way we can have the self-editing graph where software can edit system.
# Gritty
## Network
Is multipathing distributed / napoleon's messenger type w/ local state but no global. Consider it part of the OS. Port forwarding, lookup tables. Work is shared. Greedy pathfinding.
- Windowing
- Packets out of order? So consider these per-flow. Consider bootloader.
## Hardware
UART links (for now) towards FPGAs ?
## Program-Over-Network
*shrugman*
or, we designate a neighbour to be 'the programmer'. Each network port is a UART line with a viable bootloader. The neighbouring 'programmer' issues a reset command to it's neighbor, and then while the neighbour is in reset state, we pump the new program into its memory.
Alternately, each system core runs (along with mods system) a 'bootloader' wherein if it begins receiving bootload packets, it store them in page memory, and reboots on complete. Perhaps you can successfully tear the ATSAMD51 Adafruit example apart enough to do this. Maybe you can go to Adafruit for the summer to learn how to do this. In any case, presuming, now, we do machine design without the programming in situ - but build as we have been, and develop the system as described above. 1st: a stepper, a bldc?
## Local Software
Will wrote [this](https://gitlab.cba.mit.edu/langfordw/jsonMachineInterface). It uses [this](https://arduinojson.org/) which might be a really nice way to do the 'hello' mode, before we start shipping key:values about.
** TODO
- understand GO, dig into distributed systems, write.
- plan work: what when, 1st spiral, 2nd spiral ...
# 1st Spiral
Turns on Network Bridge, sends via serial key:value w/ manually written interface object.
Writes arduinojson object -> updates virtual object
Writes / tracks nomenclature
\ No newline at end of file
# What it do
Looks like we can make some minor edits with the edit / update script to do an update from file.
no bash make
less repeated code
much better UI -> but stick to HTML5 Simple Architecture
- hover text description
- double-click search for mods:
- 'server/place/etc' with auto-correct
- pretty boxes
- expandable canvases
- 'sniffer' / panels (use panel for gcode exectution)
- improved editing ui
- graph background (tests macro-expansion)
"javascript:handler('modules/character/variable')"
- where is ground truth for mod program data structure?
- stronger distinction between what is UI and what is not?
# Notes from Reich
eal Clarity on data types / and agnosticism: 1/0, true/false, 'true' / 'false' etc ... some auto parsing routines? super simple parsing mods?
move / copy / align would be lit af
double-click and add at location
panel / notes / raw text input
things like:
- output value on any event
- if / else / then output ...
- very fungible
things tend to be stateful, having a 'reset' link on most is nice
ready to plug it in... really pesky to set up b/c of lost state, reset state etc
\ No newline at end of file
Reset Buttons are CKN10685CT-ND
Vreg AP2112K-3.3TRG1DICT-ND
for plug heads do AE10315-ND
cable do CN296-250-ND
\ No newline at end of file
......@@ -10,7 +10,7 @@ In Atmel Studio, start a new project, select 'GCC Executable Project' and set th
![atsuo-1](/images/atstudio-01.png)
On the next page, select the Device to be an ATXMEGA263A3U - this is the microcontroller most of the ATK endpoints run. This image shows a different micro, no worries. **ATXMEGA263A3U**
On the next page, select the Device to be an ATXMEGA256A3U - this is the microcontroller most of the ATK endpoints run. This image shows a different micro, no worries. **ATXMEGA263A3U**
![atsuo-2](/images/atstudio-02.png)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment