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)
def integrate_pos(torques, vel, pos, del_t):
params_torques = jnp.array([2000, 1000]) # motor juice per-axis
params_frictional = jnp.array([2, 2]) # damping
torques = jnp.clip(torques, -1, 1)
torques = torques * params_torques
acc = torques - params_frictional * vel
vel = vel + acc * del_t
pos = pos + vel * del_t
return acc, vel, pos
def integrate_flow(torque, inflow, pres, del_t):
k_outflow = 2.85 # outflow = pres*k_outflow
k_tq = 1 # torque scalar,
k_pushback = 10 # relates pressure to torque
k_fric = 0.2 # damping
torque = np.clip(torque, -1, 1)
# calculate force at top (inflow) and integrate for new inflow
force_in = torque * k_tq - inflow * k_fric - np.clip(pres, 0, np.inf) * k_pushback
inflow = inflow + force_in * del_t
# outflow... related to previous pressure, is just proportional
outflow = pres * k_outflow
# pressure... rises w/ each tick of inflow, drops w/ outflow,
pres = pres + inflow * del_t - outflow * del_t
# that's all for now?
return outflow, inflow, pres
Optimizing path w/ compression model for extrusion (from data) and simple motor models.
Optimizing path w/ compression model for extrusion (from data) and simple motor models.
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)









Optimizing path w/ compression model for extrusion (from data) and simple motor models.




G21
G28
G92 X110 Y120 Z30
G0 X10 Y10 Z10 F6000
M3 S5000
G1 Z-3.5 F600
G1 X20
G1 Y20
G1 X10
G1 Y10
G1 Z10
M5
G0 X110 Y120 Z30
await machine.home()
machine.set_current_position([110, 120, 30])
await machine.goto_now([10, 10, 10], target_rate = 100)
await spindle.await_rpm(5000)
await machine.goto_via_queue([10, 10, -3.5], target_rate = 10)
await machine.goto_via_queue([20, 10, -3.5], target_rate = 10)
await machine.goto_via_queue([20, 20, -3.5], target_rate = 10)
await machine.goto_via_queue([20, 10, -3.5], target_rate = 10)
await machine.goto_via_queue([10, 10, 10], target_rate = 10)
await spindle.await_rpm(0)
await machine.goto_now([110, 120, 30], target_rate = 100)
await machine.route_shape(svg = "target_file/file.svg", material = "plywood, 3.5mm")
async def home(self, switch: Callable[[], Awaitable[Tuple[int, bool]]], rate: float = 20, backoff: float = 10):
# move towards the switch at `rate`
self.goto_velocity(rate)
# await the switch signal
while True:
time, limit = await switch()
if limit:
# get the DOF's position as reconciled with the limit switch's actual trigger time
states = self.get_states_at_time(time)
pos_at_hit = states[0]
# stop once we've hit the limit
await self.halt()
break
else:
await asyncio.sleep(0)
# backoff from the switch
await self.goto_pos_and_await(pos_at_hit + backoff)
// 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, "", "");
# auto-generated proxy,
class HBridgeProxy:
# ...
async def read_available_vcc(self) -> float:
result = await self._read_available_vcc_rpc.call()
return cast(float, result)
# ...
# discover all devices
system_map = await osap.netrunner.update_map()
# build a proxy, check existence
hbridge = HbridgeSamd21DuallyProxy(osap, "hbridge_dually")
try:
await hbridge.begin()
except NameError:
print("no hbridge found, check connections...")
print("... request voltage")
await hbridge.set_pd_request_voltage(15)
print("... await voltage")
while True:
vcc_avail = await hbridge.read_available_vcc()
print(F"avail: ${vcc_avail:.2f}")
if vcc_avail > 14.0:
break
print("pulse...")
for _ in range(100):
print("...")
await hbridge.pulse_bridge(2.0, 1000)
await asyncio.sleep(1.75)
await hbridge.pulse_bridge(-1.0, 50)
await asyncio.sleep(1)
print("... done!")
