-
Notifications
You must be signed in to change notification settings - Fork 38
Mixer
The Mixer V1 doses two masterbatch/additive hoppers into a mixing chamber with a simple on/off mixing motor. Each hopper can run at a fixed manual RPM, or — when subscribed to a running Extruder — dose automatically as a percentage of the extruder's live output rate, so the mix ratio holds steady as extrusion speed changes.
| Machine ID | 18 |
| Schema | mixer_v1.yaml |
| Code | mixer_v1.rs |
Not yet merged into
jse-control-v2— links above point atmixer-v2-pr. Update them once the branch lands.
In the tables below, <hopper> stands for hopper_a or hopper_b: every dosing setting exists once per hopper.
| Role | Terminal | Purpose |
|---|---|---|
| 0 | EK1100 | Bus coupler |
| 1 | EL2002 | Mixing motor relay |
| 2 | EL7041-0052 | Hopper A stepper driver |
| 3 | EL7041-0052 | Hopper B stepper driver |
Both steppers run in DirectVelocity mode with a 2800 mA current limit, configured and DC-synced at build time. Roles are assigned in Identification.
flowchart TB
subgraph EXT["Extruder (separate machine)"]
RPM["motor.rpm measurement"]:::hardware
end
subgraph SUB["<a href='https://github.com/qitechgmbh/control/blob/mixer-v2-pr/qitech_control/src/machines/mixer_v1.rs'>Subscription</a>"]
direction LR
REM["RemoteProperty<AngularVelocity><br/>read each act() tick"]:::control
RATE["current_extruder_output_rate<br/>rpm × extruder_kg_per_rpm"]:::control
REM --> RATE
end
subgraph DOSE["Per hopper"]
direction LR
PCT["dosing_percent"]:::control
CAL["calibration_steps_per_kgh"]:::control
MIX["masterbatch kg/h = output rate × dosing_percent ÷ 100<br/>steps/s = masterbatch kg/h × calibration_steps_per_kgh"]:::control
MAN["target_rpm<br/>manual mode, no subscription"]:::control
PCT --> MIX
CAL --> MIX
end
subgraph HW["Hardware"]
direction LR
STEP["EL7041-0052<br/>StepperVelocityEL70x1Device"]:::hardware
end
RPM --> REM
RATE --> MIX
MIX -- "subscribed" --> STEP
MAN -- "not subscribed" --> STEP
classDef frontend fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef control fill:#dcfce7,stroke:#15803d,color:#14532d
classDef framework fill:#fef3c7,stroke:#b45309,color:#78350f
classDef lib fill:#ede9fe,stroke:#6d28d9,color:#4c1d95
classDef hardware fill:#f1f5f9,stroke:#475569,color:#0f172a
A plain relay, EL2002 output 0: mixing_motor.start / mixing_motor.stop commands drive mixing_motor_on directly, no regulation involved.
Each hopper (StepperVelocityEL70x1Device, 200 full steps/rev) is driven by set_speed, signed by the <hopper>.forward direction flag. hopper_<x>_rpm reports back the same value converted to RPM, before the stepper driver sees it.
Two sources can drive the stepper's step rate, and whichever last wrote wins — there is no blend:
| Mode | Trigger | Formula |
|---|---|---|
| Manual |
<hopper>.target_rpm changes |
steps/s = target_rpm × 200 ÷ 60 |
| Ratio (extruder-linked) | Every act() tick while an extruder subscription is active |
masterbatch kg/h = extruder_rpm × extruder_kg_per_rpm × dosing_percent ÷ 100steps/s = masterbatch kg/h × calibration_steps_per_kgh
|
Ratio mode re-evaluates every tick (not just on config change), so the hopper speed tracks the extruder's live RPM continuously. With no subscription, current_extruder_output_rate() returns 0, so ratio mode drives the hopper to a stop rather than falling back to the manual RPM.
| Parameter | Unit | Default | Range |
|---|---|---|---|
extruder_kg_per_rpm |
kg/h per rpm | 0.1 | ≥ 0 — converts the subscribed extruder's screw rpm into a kg/h output estimate |
<hopper>.target_rpm |
rpm | 0 | ≥ 0 |
<hopper>.forward |
bool | true |
Direction of the stepper |
<hopper>.dosing_percent |
% | 0 | 0–100 (UI step 0.1) — share of the extruder's output this hopper doses |
hopper_a.calibration_steps_per_kgh |
steps/s per kg/h | 34.47 | ≥ 0 |
hopper_b.calibration_steps_per_kgh |
steps/s per kg/h | 6.37 | ≥ 0 |
<hopper>.enable / .disable gate the stepper driver's own enable line; <hopper>_ready and <hopper>_error mirror the terminal's input word each tick.
The Settings page runs a physical collection test rather than requiring the operator to compute calibration_steps_per_kgh by hand: it drives the hopper at a chosen test RPM for a chosen duration (enable + manual target RPM, defaults 20 rpm / 60 s), the operator weighs what was collected, and the page derives:
rate_kg_per_hour = collected_grams × 3.6 ÷ duration_seconds
steps_per_second_at_test = test_rpm × 200 ÷ 60
calibration_steps_per_kgh = steps_per_second_at_test ÷ rate_kg_per_hour
Save Calibration writes the result to <hopper>.calibration_steps_per_kgh; only one hopper can run a calibration test at a time.
The Mixer subscribes directly to another machine's live measurement using the framework's cross-machine subscription mechanism (SubscribeMachine / UnsubscribeMachine runtime requests), rather than polling a REST endpoint. subscribe() stores a RemoteProperty<AngularVelocity> bound to the provider's motor.rpm measurement; unsubscribe() clears it if the unsubscribing identity matches. The adapter resolves which machine is currently subscribed by scanning instance.subscriptions for an Extruder V1/V2 identity, so the frontend's "connected machine" selector reflects the real subscription state rather than a locally-cached choice.
Unsubscribing must go through UnsubscribeMachine rather than simply clearing the reference client-side — doing the latter leaves the subscriber holding a now-invalid lifetime token, which panics on the next read. (This was a real bug, fixed upstream in qitech_framework: unsubscribe() is now called on the machine before its token is invalidated.)
QiTech Control · GitHub · Framework wiki · Lib wiki · Report a docs problem
Getting Started
Guides
Machines
Developers
Related