Commit 19309b0e authored by Jake Read's avatar Jake Read
Browse files

doc update

parent 339b760b
...@@ -13,6 +13,8 @@ jake/ ...@@ -13,6 +13,8 @@ jake/
**/ASF/ **/ASF/
embedded/atsams70-usbcdc/ embedded/atsams70-usbcdc/
embedded/usb-adafruit/ embedded/usb-adafruit/
embedded/usb-xplained/ embedded/usb-xplained/
# AutomataKit # AutomataKit
AutomataKit is a collection of open hardware and software developed to enable non-experts (and experts) develop various machine-building, process development, and robotics projects. AutomataKit is a collection of open hardware and software developed to as a rapidly reconfigurable library for various machine-building, process development, and robotics projects.
All of these tasks require a similar subset of tools: motor control, sensor acquisition, motion coordination, power delivery, etc. AutomataKit offers solutions to most of these problems, and is always growing. Typically, designing and engineering complex systems requires knowledge across the disciplines of electrical engineering, embedded programming, mechanical design, controls engineering, and interface design. By breaking these components into reconfigurable [software and hardware objects](!/nadya-phd), AutomataKit aims to allow non-experts (and experts) to jump in to higher-level systems design.
To make these tasks modular, Automatakit uses a very simple networking scheme to deliver commands and get feedback from various hardware endpoints. Hardware endpoints recognize low-level commands from controllers which can be written in any software package that can successfully communicate over USB to a serial port. There is virtually no limit to the number of endpoints that can make up a system. !DOC - threeset: hardware objects, network topology, software
## Examples ## The Network
- reich To make individual motors and sensors modular, AutomataKit endpoints use a port-forwarding, source-routed network. Packets typically originate on the network over a usb-to-serial bridge, so you can interface with networked endpoints using any piece of software you can successfully use to open a COM port with: JavaScript, Python etc. The [AutomataKit Router]( includes one UBS-to-UART Bridge, which is treated as the 6th port on the router.
- motion
## The Network The hardware (or 'PHY' layer) of the network is simple UART. That means that all the network is, is a few UART links between microcontrollers, and some C code that listens for incoming packets and forward messages according to the instructions in the packet. Critically, there are not *addresses* in the network, instead, packets themseleves carry routes: this is 'source routing' in network nomenclature.
### The Packet
Because our UART hardwares typically operate on bytes, our packets are sets of bytes. Packets are structured like this:
![packet typ](/images/apa-networking-diagrams-packet.png)
### Port Forwarding and Route Shifting
Bytes between the Length Byte and the *Packet Header End Delimiter* define the route. As the packet moves through the network, it is forwarded on the ports in the list, in order. To keep track of the current position of the packet (which port is next in the list) we shift the list of ports along at each forwarding instance, such that the 2nd byte in the packet is always denoting the next port to forward on. We append to the end of the header the port which the packet arrived on, and that way we keep a return route in the packet. When the packet arrives on a port and the *Packet Pointer* is the next byte, the recipient knows the packet has been sent to them, and they handle it.
- port-forwarding packet automata inner life and diagrams ![packet typ](/images/apa-networking-diagrams-traversal.png)
## The Endpoints ## The Endpoints
Endpoints are designed to be very simple: they receive minimum viable commands and keep minimal state required for operation. This way, system complexity can be organized in the particular application, not distributed throughout the system. For example, steppers receive very simple trapezoid motion segements to execute, and don't do much math except for counting steps.
- [ATKRouter]( - [ATKRouter](
- [ATKStepper17]( - [ATKStepper17](
- [ATKStepper23]( - [ATKStepper23](
- [ATKBLDCDriver]( - [ATKBLDCDriver](
## Mods # Interfacing with AutomataKit
- how to plug into / use mods / serial
## Interfacing with AutomataKit Once you understand the packet structure, any program you can imagine to write that has access to a USB or Serial Port, can issue and receieve packets.
- atkterminal app and /atkterminal ## Interfacing with Mods
- command structures, general use w/ any given serial port
# Reproducing and Extending Automatakit Work [mods]( is a browser-side system for composing software workflows. A development version for mods that includes modules for use with AutomataKit lives on a branch at [/jake](
To run this branch locally, clone the repository and use ``git checkout jake`` when in the mods directory. Now you can run a local webserver, one of which is included in node - which you can install using [this guide](/reproduction/ From the mods directory, use ``http-server`` and you should see the IP address and port you can type into your browser to begin.
Because mods is browser-side, it needs some help to access hardware on your machine (i.e. the USB-to-UART bridge). To do this, we use a websocket server and an interface module.
The interface module can be opened in mods under /modules/hardware/network, or by searching for **atkbridge**.
The websocket server is a small node.js application, similar to ATKTerminal, and is located at mods/js/atkserialserver.js. To use this application, you will want to clone the mods repository, navigate to the /js folder and open atkserialserver with ``node atkserialserver <client address> <server port> <com port>`` where **client address** and **server port** are specified in the reflecting module, and the **com port** that your USB-to-UART bridge is located on, which you can find using ``serialport-list`` from the same command line.
To reproduce Automatakit Circuits and software, see the [automatakit reproduction guide](reproduction) Once this application is open, it should maintain a connection to mods and the serial hardware.
# Documentation ToDo ... how to format packets for mdos
## Interfacing with ATKTerminal
``atkterminal.js`` is a small command-line type program I wrote to quickly interface with AutomataKit firmware, mostly for debugging and testing network hardware.
ATKTerminal uses node's ``readline`` module to parse input from whatever terminal interface you're using (I use MINGW64, which installs with git on windows). It also uses the ``SerialPort`` module to chat over a suitable USB-to-UART bridge (probably the bridge that's integrated in the [atkrouter](
To run atkterminal, you'll need to [install node, and then install node's SerialPort module](/reproduction/ To check that the USB-to-UART bridge is running, you can use the ``serialport-list`` command. You should see the port enumerated with **Silicon Labs** somewhere in the name. You can then boot atkterminal with:
``node atkterminal <portname>``
Where ``<portname>`` is the name you found using ``serialport-list`` - on windows this will look something like **COM11** or on unix systems, ``tty/dev1`` etc.
To use atkterminal, try using the ``help`` command while it's running for a brief cheat sheet. The ``packet`` command is largely what you're after, and is structured like ``packet byte,byte,byte,etc..`` where the second argument is a comma-separated list of 'words' to insert into the packet.
For example, to write a Step Trapezoid command, I would write ``packet 0,1,ptr,end,trapezoid,1000,100,5000,500,550`` - this will issue a packet with the route of 0,1 and with the key for a trapezoid command, with 1000 steps to make, starting at 100 steps/s, accelerating with 5000 steps/s^2, accelerating for 500 steps and decelerating after 500 steps.
# Examples
- [*A Machine* for playing *Music for Pieces of Wood* by Steve Reich by Jake Read](
- [Modular, Networked Stepper Motor Controller](
# Reproducing and Extending Automatakit Work
- board projects should have BOMs To reproduce Automatakit Circuits and software, see the [automatakit reproduction guide](reproduction)
- network, examples, mods config \ No newline at end of file
\ No newline at end of file
//----------------------------------------- mkterminal
small program for sending apa packets along a serial line
// check that we have portname
if (process.argv.length < 3) {
if (process.argv[2] == '-h' || process.argv[2] == 'help') {
var SerialPort = require('serialport');
var ByteLengthParser = SerialPort.parsers.ByteLength;
var port = new SerialPort(process.argv[2], {
baudRate: 750000,
dataBits: 8,
parity: 'none',
flowControl: false,
//----------------------------------------- readline
key input from terminal
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
rl.on('line', parseLineIn);
function parseLineIn(data) {
packet like "packet port,port,etc,ptr,byte,byte,byte..."
does like "len,int,int,int,254?,byte,byte,byte,etc"
next do key:type:values
apa_end_addr_delimiter 255
apa_addr_pointer 254
apa_addr_flood 253
key_position_float 127
key_speed_float 128
key_position_steps 129
key_speed_steps 130
if (data.includes('packet')) {
var argstring = data.split(' ')[1]; // everything following 'packet '
var args = argstring.split(',');
var packet = new Array();
var i = 0; // args
var u = 0; // packet
while (i < args.length) {
switch (args[i]) {
case 'ptr':
packet[u] = 254;
case 'end':
packet[u] = 255;
case 'test':
packet[u] = 127;
case 'reset':
packet[u] = 128;
case 'setPos':
packet[u] = 129
var newPos = parseInt(args[i + 1])
packet[u + 1] = (newPos >> 8) & 255
packet[u + 2] = newPos & 255
i += 2
u += 3
case 'getPos':
packet[u] = 130
i ++
case 'trapezoid':
packet[u] = 131;
// a linked acceleration planned segment
// we'll be going betwee float-space for steps in the higher levels, so
var steps = parseInt(args[i + 1])
packet = packet.concat(pack32(steps))
// but accel and speeds need to be in floats
var entry = parseInt(args[i + 2])
packet = packet.concat(pack32(entry))
// pack 64 bit float to 32 bit?
var accel = parseInt(args[i + 3])
packet = packet.concat(pack32(accel))
var accelLength = parseInt(args[i + 4])
packet = packet.concat(pack32(accelLength))
var deccelLength = parseInt(args[i + 5])
packet = packet.concat(pack32(deccelLength))
i += 6
u += 21
case 'wait':
packet[u] = 132;
var steps = parseInt(args[i + 1])
packet = packet.concat(pack32(steps))
var speed = parseInt(args[i + 2])
packet = packet.concat(pack32(speed))
i += 3
u += 9
case 'speed':
packet[u] = 141;
var speed = parseInt(args[i +1])
packet = packet.concat(pack32(speed))
var duty = parseInt(args[i + 2])
packet = packet.concat(pack32(duty))
i += 3;
u += 9;
packet[u] = parseInt(args[i]);
packet.unshift(packet.length + 1); // push the length into header
// now through bytes
} else if (data.includes('dummy packet')) {
var packet = Buffer.from([12, 3, 1, 254, 4, 255, 1, 2, 3, 4, 5, 6]);
} else if (data.includes('help')) {
} else if (data.includes('exit')) {
} else {
function pack32(val) {
var pack = new Array();
pack[0] = (val >> 24) & 255;
pack[1] = (val >> 16) & 255;
pack[2] = (val >> 8) & 255;
pack[3] = val & 255;
return pack;
function packFloat(val) {
var pack; // the array of bytes
// as a view into a typed array
var view = new DataView(new ArrayBuffer(4));
view.setFloat32(0, val);
pack = Array.apply(null, { length: 4 }).map((_, i) => view.getUint8(i))
console.log('packed', val, 'as', pack)
return pack
function logAdvice() {
console.log('use serialport-list to find ports')
console.log("command line: node serialterminal portname");
console.log('test: sends byte 128 to network test')
console.log('steps: {steps uint32_t, speed steps/s float, dir uint8_t}')
console.log('block: {steps float (also dir), cruise speed steps/s float, accelleration steps/s/s float, start speed float, end speed float')
//----------------------------------------- parsing
does the business
var parser = port.pipe(new ByteLengthParser({ length: 1 }));
parser.on('data', data_in);
function data_in(data) {
function data_out(data) {
console.log('sent: ', data);
port.write(data, function(err) {
if (err) {
return console.log('port error on write: ', err.message);
port.on('open', function(err) {
console.log('port open');
port.on('error', function(err) {
console.log('port error: ', err.message);
\ No newline at end of file
# 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
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](
## 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:
- 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](
- 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:
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](, 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:
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](, 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']( 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]( 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](
This is largely complicated when we want to somehow remotely program hardware endpoints to send messages to eachother.
![whiteboard sketch](
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]( 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](
# 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]( 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!)
Here's a sketch of what I want to build:
![whiteboard sketch](
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.