Every part here was printed without a slicer. No CAD, no mesh — a Python program writes the printer's motion directly, so each shape below is the toolpath. The diagrams on this page are drawn from the exact files that printed, not sketched afterwards.
A cleated belt runs between two pulleys. Balls sit in the cleats, ride up, and fall out at the top. The frame is 1/4 inch bamboo skewers held by printed joints.
| Belt | 2.41 m | folded onto one 350 mm plate as a closed space-filling curve, then unfolded |
|---|---|---|
| Lift | 1.14 m | vertical at 90°, 0.99 m at a 60° tilt where no side wall is needed |
| Balls | 14 mm | steel, 11 g each — one per cleat: 25 on the 2.41 m loop, clustered on the straight runs (gaps 25–309 mm, not uniform) |
| Material | ~195 g | the whole machine |
Each diagram is drawn from the real printed path, seen from above — one layer, except the weighted foot, which shows its first eight so the cavity is visible.
What you turn. The bore is printed round — push it onto the motor shaft while the part is still hot and the plastic moulds itself to the shaft's flat. The shaft is the mould, so the fit is exact and can't be misaligned.
Slightly barrel-shaped — 0.6 mm fatter in the middle. A flat belt always climbs toward the widest part, so the bulge keeps it centred instead of walking off the end.
Holds the pulley axle out from a bamboo upright, with 4.7 mm of clearance so a 40 mm pulley spins past the stick. Filled with rings rather than criss-cross infill — every pass follows the load around the holes instead of cutting across it.
Joins two skewers end to end so the frame can be any height. A plain tube — two walls, one unbroken line.
Holds two uprights parallel. Use them in pairs — one plate sets the spacing but acts as a hinge, so a single spacer lets the sticks splay. Two, spread apart, fix the angle.
Motor shaft at one end, bamboo at the other. The shaft end goes at the bottom so that going up, the hole only ever gets bigger — nothing has to print over thin air.
A 1 m ladder with a belt running up it wants to walk. So the foot is printed as a shell with a floor and an open mouth — you fill it with sand and gypsum after printing. Sand alone damps well, because the grains rub and eat energy; the gypsum sets it so it stops migrating and becomes structural.
It is lighter to print and heavier to own: the shell is about a third of the plastic, and filled it beats solid PLA outright — sand+gypsum is roughly 1.8 g/cm³ against PLA's 1.24. Mass is the point, because it drags the whole structure's natural frequency down away from the belt's.
Each part used to be its own file — which meant six heat-ups, six homings, and six chances to start a print onto a plate that had not been cleared. The whole frame now goes down in one run: 15 parts across 315 mm, packed into shelves tallest-first.
The catch is the brim. Every part's brim reaches
brim_gap + brim × bead = 4.98 mm past its outline, so two neighbours need
11.16 mm between them or the brims merge and the parts come off the plate welded
together — with the join hidden underneath a brim that is supposed to snap away. The first plate
generated here used an 8 mm gap and would have done exactly that. It is now a check that
refuses to emit the file, which is the only reason it was caught before the bed and not after.
Every bore in this build is modelled at stick + 0.25 mm, because a printed hole comes out about a quarter of a millimetre smaller than modelled. That figure is confirmed at 6 mm and was extrapolated to a 6.35 mm (¼″) stick — so one part on the plate is a gauge that tests it, and it is the first thing to pick up.
| bore | modelled | expected | what it means if this is the one that fits |
|---|---|---|---|
| 1 | 6.55 | ~6.30 | shrink is smaller than 0.25 — every other part is loose, reprint with a tighter bore |
| 2 | 6.80 | ~6.55 | 0.25 is right. Every coupler, bracket and spacer on the plate is correct |
| 3 | 7.05 | ~6.80 | shrink is larger than 0.25 — the others will not accept a stick, reprint wider |
Push a real stick into each. The one that grips without splitting is the answer. Ten seconds with one stick either validates the other fourteen parts on that plate or condemns them before you have glued anything.
Why the fits differ on purpose: brackets are bored at zero clearance so they grip the upright and hold their height by friction — that is the tensioner. Spacers get 0.25 mm more so they still slide while you square the frame. Same nominal bore, opposite jobs.
The belt finished at 00:14 on 2026-07-26 — 76 minutes, 24.6 m of filament, 2.41 m of belt from a 350 mm plate.
| Belt | 2.41 m | 25 cleats — the first one |
|---|---|---|
| Longer belt | 4.57 m | 52 cleats, 2.22 m of lift from the same 350 mm plate — printed overnight in 143 min, 46 m of filament. (The cleated layers measure 4.85 m; the cleat-free rails measure 4.57 m, and it is the rails that go taut and define the loop — so 4.57 is the belt.) This is the longest that still fits a cleat: fold the curve one step further and you get 8.85 m, but the channel narrows to 10 mm and no cleat clears it, so you would have a long belt with nothing to carry a ball. |
| Rails | 3 mm | cleat-free at each edge — they run 180 mm shorter around the loop, so they take the tension and the cleats never get pulled flat |
| Cradle | 2 mm | shallower cleats mid-width, so a ball rolls to the centre instead of off the side |
| Pulleys | 2 + hub | bores confirmed a perfect fit on a 6 mm shaft |
These are the exact commands. The generator refuses to write a file it cannot verify — it will tell you why rather than hand you something that fails on the plate.
| Belt | python3 belt.py --printer k2plus --fold 3 --belt-w 20 --cleats 60 --cleat-h 8 --cleat-w 18 --dish 2 --rail 3 --flow 13 --temp 200 --bed 45 |
|---|---|
| Pulley | python3 pulley.py --printer k1c --od 40 --width 29 --bore 6 |
| Drive hub | python3 pulley.py --printer k1c --od 60 --width 16 --bore 6 --flat 0 --crown 0 --flange 0 |
| Joints | python3 solid.py --part bracket|coupler|spacer2 --stick 6.35 --height 14 --clearance 0 |
| Weighted foot | python3 solid.py --part foot --stick 6.35 --height 25 --wall 5 --cavity 2.4 --floor 2.4 --clearance 0 |
| Whole plate at once | python3 solid.py --printer k2plus --parts "coupler*6,bracket*4,foot*2,gauge,spacer2*2" --stick 6.35 --height 14 --part-gap 12 --layer-h 0.6 --flow 36 |
Every command above was executed and its output measured before being
published here — an earlier version listed --part foot with no cavity arguments,
which emits a solid 39 mm puck rather than the shell this page describes, and quoted the TPU
belt at 230 °C, which is the temperature that jammed. Note also that the belt generator
thins the requested 60 cleats to the 52 that actually fit the straight runs, and
says so on every run — the page now quotes what it places, not what it was asked for.
--flat 0 on the hub is deliberate: the bore stays round and you press it onto the motor shaft while the part is still hot, so the shaft moulds its own flat. --clearance 0 grips a stick, 0.25 slides on one.
The generator that writes these files is open:
github.com/olegmlkvorg/crackle — the
belt comes out of belt.py, the pulleys out of pulley.py, the
brackets and spacers out of solid.py. Every command printed on this page runs
against that repo unchanged. Nothing here needs a slicer, a licence, or a workshop — a
printer, a spool, and a pack of bamboo skewers.
Ideas, corrections, or a better cleat: take.senku.im