A motorized resin bottle roller / mixer built around the MKS Gen L V1.0 3D printer controller board (ATmega2560). Two stepper motors spin a pair of rollers that gently tumble epoxy resin bottles to keep the mix homogeneous, with a simple three-button interface and addressable LED status strip.
CAD model (OnShape): Open in OnShape
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
- Three operating modes selected by coloured push-buttons
- Red — Emergency stop (immediate motor kill + red LED flash)
- Yellow — Continuous rolling at half speed (1.5 RPM)
- Green — Timed alternating direction: 8 s forward → 8 s reverse, loops indefinitely
- Smooth exponential speed ramp — no abrupt starts or stops (τ = 400 ms)
- Hardware step generation via Timer1 CTC ISR — cycle-accurate timing, decoupled from the main loop
- Direct port writes on step pins (PORTF) for ~125 ns pulse width; supports up to ~500 kHz step rate
- Addressable LED strip (5 × WS2812B) with per-mode effects
- Idle: slow blue breathing
- Yellow: solid yellow
- Green: animated green wave that sweeps with motor direction
- Stop: 3× red flash
- Cooling fan on D9, active whenever motors are enabled
| Component | Details |
|---|---|
| Controller | MKS Gen L V1.0 (ATmega2560) |
| Motor drivers | TMC2209 (or compatible) × 2, configured for 256 µsteps |
| Motors | NEMA 17 (1.8°, 200 steps/rev) |
| LED strip | WS2812B × 5, connected to D3 |
| Buttons | Normally-open, wired to X+/Y+/Z+ endstop headers (INPUT_PULLUP) |
| Fan | 12 V cooling fan on D9 |
| Button | Colour | MKS Header | Arduino Pin |
|---|---|---|---|
| Stop | Red | X+ | D2 |
| Half speed | Yellow | Y+ | D15 |
| Timed cycle | Green | Z+ | D18 |
| Motor | Function | STEP pin | DIR pin | EN pin |
|---|---|---|---|---|
| X driver | Roller 1 | 54 (PF0) | 55 | 38 |
| Y driver | Roller 2 | 60 (PF6) | 61 | 56 |
| Library | Version |
|---|---|
| FastLED | ^3.10.3 |
Requires PlatformIO.
# Build
pio run
# Upload
pio run --target upload
# Serial monitor (115200 baud)
pio device monitorAll tuning constants are at the top of src/main.cpp:
| Constant | Default | Description |
|---|---|---|
MOTOR_STEPS_PER_REV |
200 | Steps per revolution (200 for 1.8°, 400 for 0.9°) |
MICROSTEP_COUNT |
256 | Must match MS1/MS2 jumper setting on driver |
REDUCTION_RATIO |
1.0 | Motor revs per roller rev (1.0 = direct drive) |
FULL_SPEED_ROLLER_RPM |
3.0 | RPM in green timed mode |
HALF_SPEED_ROLLER_RPM |
1.5 | RPM in yellow continuous mode |
GREEN_DIRECTION_TIME_MS |
8000 | Milliseconds per direction in green mode |
ACCEL_TAU_MS |
400 | Exponential ramp time constant (ms) |
Stepping is handled exclusively by the Timer1 CTC ISR — the main loop only updates the speed target and direction. This separation means:
- Step pulse timing is cycle-accurate regardless of main-loop duration
- LED animations, button debounce, and ramp calculations run freely in the main loop
- A direction change ramps the motor to zero first, flips DIR, then ramps back up
MIT — do whatever you want with it.





