Nor can we improve those jobs' productivity; we aren't developing new automation rapidly
enough.
Famco 100 (1950's)
Can we imagine re-awakening old equipment with modular controllers?
Hurco VMX42SRTi (2010's)
Can we make it easier to understand and develop machines?
Vasquez, Joshua, et al. "Jubilee Demo: An Extensible Machine for Multi-Tool Fabrication."
Extended Abstracts of the 2020 CHI Conference on Human Factors in Computing Systems. 2020.
Peek, Nadya, et al. "Making at a distance: teaching hands-on courses during the pandemic."
Extended Abstracts of the 2021 CHI Conference on Human Factors in Computing Systems. 2021.
Hack Club and Leo McElroy https://blot.hackclub.com/
G21 ; use millimeters
G28 ; run the homing routine
G92 X110 Y120 Z30 ; set current position to (110, 120, 30)
G0 X10 Y10 Z10 F6000 ; "rapid" in *units per minute*
M3 S5000 ; turn the spindle on, at 5000 RPM
G1 Z-3.5 F600 ; plunge from (10, 10, 10) to (10, 10, -3.5)
G1 X20 ; draw a square, go to the right,
G1 Y20 ; go backwards 10mm
G1 X10 ; go to the left 10mm
G1 Y10 ; go forwards 10mm
G1 Z10 ; go up to Z10, exiting the material
M5 ; stop the spindle
G0 X110 Y120 Z30 ; return to the position after homing (at 6000)
A simple GCode program, for a milling machine.
GCode was invented alongside the first CNC machine, in a milieu of computer scientists who were
developing top-down, feed-forward design patterns for system abstraction.
Noble, David. Forces of production: A social history of industrial automation. Routledge, 2017.
If machine control is a constrained optimization task, can we make that explicit?
Does machine performance improve if we do?
Can we use machine models to describe those constraints?
What types of models would enable this?
What can we learn from those models - as machine designers and users?
Can we frame entire workflows as model-based optimizations?
How can we leave room for heuristics, where models fail to capture details?
What kind of systems architecture would enable all of this?
CNC machining physics: the tool has a number of cutting edges (flutes),
that cut chips.
The size of the chip, aka chip load, is a function
of the tool's RPM and the machine's speed.
Maintaining chip load is important: if the machine slows down
too much, we risk rubbing instead of cutting.
Schmitz, Tony L, and K Scott Smith. 2009. “Machining Dynamics.” Springer.
CNC programming involves picking feeds (cut sizes)
and speeds (for motion, and spindle RPM).
As well as strategies; how tool paths will be planned.
$\Theta (rads), \omega (rads/s), \dot{\omega} (rads/s^2)$ are pos, vel, and accel.
$\tau (Nm)$ is torque.
$J (kg \cdot m^2)$ is motor rotor inertia.
$k_t$ is the magic parameter; it allows us to estimate torque $(\tau, Nm)$
using our motor controller's current measurements $(I, Amps)$.
Electrical Equations:
$$
\begin{aligned}
Z &= \sqrt{R^2 + (\omega_e L)^2} \\
\omega_e &= \omega_m p \\
V_p &= V_a - k_e\omega_m \\
\dot{I} &= (V_p - RI) / L \\
I_{ss} &= V_a / Z
\end{aligned}
$$
$R (ohms), L (Henries)$ are motor resistance and inductance
$Z (ohms)$ is impedance, $V$ are voltages (applied, potential).
$k_t, k_e, k_d$ parameters are fit on time-series data from a spin-up test (above), using a known inertia
$R, L, J$ are measured by hand.
Kinematic Models: how machines move.
Kinematic Models: Mill
Mill Kinematics are simple: each motor moves one axis.
In general, we compute the inverse kinematics:
$$
\vec{X}_{actu} = f_{IK}(\vec{X}_{cart})
$$
These map end effector states $(\vec{X}_{actu})$
to actuator states $(\vec{X}_{cart})$
and include drive ratios: how motor rotations relate to linear translations.
To model friction, I use a Coulomb approximation that includes stiction.
$$
Fc(\vec{V}, \mu_{visc}, \mu_{stick})
$$
Parameters $(\mu_{visc}, \mu_{stick})$ are fit using time-series data (right).
The workup below translates from motion states
into actuator states and actuator currents:
Table above: manufacturer $\rightarrow$ vs $\rightarrow$ model-based
for the machine's maximum velocities and accelerations $(V_{max}, A_{max}),$ per axis.
(big number good, small number bad).
Model-based selections for $(V_{max}, A_{max})$ far exceed the kit manufacturer's recommendations.
Machining the pocket toolpath, trapezoidal motion solver.
Machining the adaptive toolpath. As the machine is running, we collect data from the motor controllers...
We can use that data to make cut force estimates, *
These are generated from the pocket toolpath.
Cut force estimates, adaptive toolpath.
Models can be used in the machine design process, helping us to
make choices with data based on our particular hardware.
Software-defined controllers let us inspect toolpaths before we run them.
Motion and kinematic models, when combined with time-series data from motors and
motion controllers, can be combined to produce new measurements, like cut force.
Can we use models directly, to improve our machine's performance?
Here is force margin for our mill's $x$ axis.
These plots only show positive accelerations (speeding up).
Force margin for our mill's $x$ axis.
Here we see negative accelerations (i.e. braking, left half of plot) as well.
Model-based velocity solver. 2D Trajectory at left, solution states at right, top to bottom:
solver gradients, $v(s)$, $\Delta t(s)$, $I_{req}(s)$, $\dot{I}_{req}(s)$, $\vec{V}(t)$, and convergence.
Framing velocity control as an explicit constrained optimization problem
leads to performance improvements that can have meaningful impact on process outcomes.
Heat, squish, and extrude a thermopolymer through a nozzle.
3D printing Parameters as shown to users in PrusaSlicer
The RheoPrinter
The RheoPrinter's Extruder
Steady-State Flow Model
In steady-state:
For any temperature, what flowrates are possible?
What is the pressure required for each?
For a range of flowrates:
Heat the nozzle to its maximum temperature.
Set the extruder to drive at the test flowrate.
Disable the heater!
Until the flow stops, record:
Nozzle temperature,
Extruder motor current,
Loadcell pressure,
Continue to next test flowrate.
$$
Q = f(Fk_{lin}) ^ {k_{pow}}
$$
$Q (mm^3/s)$ is volumetric flowrate.
$F (N)$ is the loadcell reading.
$k_{lin}, k_{pow}$ are temperature-varying parameters.
| Symbol | Value | Units | Source |
| --- | --- | ---: | --- |
| $T$ | Temperature of Flow | $^\\degree C$ | Measured |
| $T_{amb}$ | Ambient Temperature | $^\\degree C$ | Known |
| $Q$ | Volmetric Flowrate | $mm^3/s$ | Measured |
| $k_{loss}$ | Heat Loss to Ambient | $({C/s})/{\Delta T}$ | Model Fit |
| $k_{flow}$ | Heat Loss per unit of Flow | $({C/s \cdot (mm^3/s)})/{\Delta T}$ | Model Fit |
This lets us simulate required layer cooling times across nozzle temperatures.
| Symbol | Value | Units | Source |
| :--- | :--- | ---: | --- |
| $H$ | Layer height | $mm$ | Part Geo. |
| $l_{iface}$ | Layer interface proportion | 0-1.0 | Part Geo. |
| $\kappa_{fil}$ | Filament conductivity | $W/m \cdot \Delta T$ | Estimated |
| $C_{fil}$ | Filament heat capacity | $J/m^2 \cdot \Delta T$ | Model Fit |
| $T_{noz}$ | Nozzle temperature | $\degree C$ | Direct Measurement |
| $T_{targ}$ | Cooling target temperature | $\degree C$ | From Flow Models |
| $T_{ambient}$ | Chamber air temperature | $\degree C$ | Known |
| $h_{air}$ | Heat transfer to air | $W/m^2 \cdot \Delta T$ | Estimated |
| $h_{layer}$ | Heat transfer to layer below | $W/m^2 \cdot \Delta T$ | Via $fil_k$ |
Planned rates can be skewed to hit target minimum layer times.
Above: FFF path plan with rates-scaling applied to enforce the minimum layer time
set by the layer cooling simulation.
Hot: slow (more skew), cold: as-planned.
We prioritize slowing hidden features, to minimize changes in appearance.
* This scaling step exists in the state-of-the-art. Estimates for filament heat capacity
from nozzle data and the layer cooling simulation formulation are my own.
We can see that small parts tend towards $T_{min}$, but temperature selection quickly increases.
~65x80mm part @ 239 C
~80x80mm @ 261 C (11% Speedup)
~80x130mm @ 279 C (50% Speedup)
But we still need to actually run the printer.
Can we include process and motion dynamics in one optimization?
Because the solver is developed using a general purpose optimization framework,
we can extend it with some flexibility.
High-resolution time-series from our workflow should allow us to continuously improve models.
The printer generates ~ 1GB/h of data.
Measured Actuator Currents
Measured Nozzle Pressure
We can process solver outputs to assess which process factor was limiting overall speed.
This type of tool helps us to understand complete interactions between process control, motion control,
and our part geometries and materials.
I developed a time-optimal workflow for FFF that explicitly frames both high- and low-level
aspects of machine control as optimization tasks.
This reduces the parameter-tuning burden on machine users, showing how model-based machines can:
Help us develop and deploy new materials and machines
Help new machine users to succeed
Support the development of tacit knowledge with real data
The time-optimal workflow is faster than the state-of-the-art, but print quality
is clearly lower.
However, I showed that areas of poor print quality are correlated with
areas where model losses are high.
If we can close the loop and re-fit flow models on machine data, we can probably
drive this approach towards improvements over the state-of-the-art on all fronts.
How does it all go together?
Modular circuits help to assemble machines from a core set of parts.
Milling Machine, Z-Axis Motor
FrankenPrusa, Extruder Motor
In a CNC Winch.
The FrankenPrusa is a neat opportunity to compare: monolithic vs. modular.
Monolithic controllers (left) vs. modular (right).
Total board area is about equal.
Everything removed from the Prusa. Modular systems simply chassis wiring.
This (plus motor encoders) is the relatively thin interface that the controllers use to sense and control the machine.
Modules help us re-deploy hardware in multiple contexts, but how do we communicate and coordinate their actions?
Messages are source routed, meaning there is no stateful network configuration to manage.
Hubs are a design convenience, but not required by the protocol. Any device can pass messages across multiple ports.
Python scripts and device firmwares are peers in the network, and message-passing is link agnostic.
Message-passing hub (one of two used) in the RheoPrinter.
Message-passing hub in the Little Guy.
OSAP synchronizes device clocks continuously, providing a basis for coordinated motion control and sensing.
In the printer, clocks typically adjust to within $500\mu\mathrm{s}$ with one another after $60s$ and within $250\mu\mathrm{s}$ after $100s$ - and get better over time.
To avoid waiting for sync every time we start machines, clock skews can be stored and restored at launch.
How is motion synchronized across actuators?
Fixed-interval basis spline segmentation means that network loads are deterministic when we run machines.
With slow intervals $(4.096ms)$ and high acceleration $(15 000mm/s^2)$ interpolation errors can reach $50\mu m.$
How do we describemachine controllers?Reconfigure them?
Firmwares contain function implementations.
// in hbridge firmware
float readAvailableVCC(void){
const float r1 = 10000.0F;
const float r2 = 470.0F;
// it's this oddball, no-init ADC stuff,
// teensy is 10-bits basically, y'all
uint16_t val = analogRead(PIN_SENSE_VCC);
// convert to voltage,
float vout = (float)(val) * (3.3F / 1024.0F);
// that's at 10k - sense - 470r - gnd,
// vout = (vcc x r2) / (r1 + r2)
// (vout * (r1 + r2)) / r2 = vcc
float vcc = (vout * (r1 + r2)) / r2;
return vcc;
}
// one line to generate an interface
BUILD_RPC(readAvailableVCC, "", "");
We can access those from other contexts
via proxy classes.
Controller for the milling machine; a mixture of python (boundary with blue top bar, left) and embedded devices (right).
PIPES / MAXL graph for the milling machine, where the trapezoid solver is deployed.
PIPES / MAXL graph for the milling machine, where the optimization-based solver is deployed.
# SETUP the Runtime and Hardware:
osap, manager = await network_tools_setup()
# we can define virtual machines,
machine = Mill(osap, manager,
MillSetupConfig(
use_motion_chirp=True,
use_x= True if test=="chirp_x" else False,
use_y= True if test=="chirp_y" else False,
use_z= True if test=="chirp_z" else False,
)
)
# this step checks that hardware in the machine definition
# is actually connected...
routers, devices = await machine.setup_devices()
# SETUP the Chirp Test
# make a data store,
collector_x = MotorMotionCollector(samps_collect_max)
# connect *most* of the machine controller,
await machine.setup_kinematics()
# connect the x motor's data output to the collector's input:
mot_x = machine.require_x_motor()
await manager.connect(mot_x._get_motion_states_proxy, collector_x.data_sink)
# and then set the PIPES function to run on a timer,
await mot_x._get_motion_states_proxy.set_input_mode('timer', hz_motor_up)
At left is the `setup` code: using OSAP and PIPES to instantiate the machine, confirm that the correct hardware is
connected, and make connections between relevant motion control blocks.
Below, using Remote Procedure Calls to task the machine.
# RUN:
# power it all up,
await machine.ready_motion()
# run a test:
# send a few trapezoid tests
for _ in range(4):
machine.dof_x.goto_pos(25)
await machine.dof_x._wait()
machine.dof_x.goto_pos(-25)
await machine.dof_x._wait()
# return to (0)
machine.dof_x.goto_pos(0)
await machine.dof_x._wait()
# send a chirp signal,
chirp_x, chirp_y, chirp_z = machine.require_chirp_inputs()
# send one-such chirp,
chirp_x.do_chirp(duration=30, f0=0.5, f1=3.0, amplitude=30.0, tukey=0.85)
while chirp_x._is_chirping():
await asyncio.sleep(0.1)
# end test, post data:
data = {
# motor params, traces,
"test_name": test,
"run_start_time": run_start_time,
# motion,
"mot_params_x": asdict(mot_x_params),
"motx": collector_x._get_dict(),
}
With re-useable machine modules, we can build new controllers in days rather than weeks or months.
Flexible software lets us develop multiple workflows on the same hardware:
for model fitting, or model use, or swapping controllers entirely in software.
Model-based controllers could help to retrofit equipment that we don't have much data on.
OK.
Acks
MIT !
Neil, Nadya, and Jon
Saul, Forrest, Sam, Ilan
You learn a lot from your peers: Quentin, Leo, Sean, Erik,
Brother
Mother
Dad
Billiam
Devo, Em,
Miranda
AZ !
Anthony, Dan, Zach, Luciano
Mole People
McMaster Carr