Files
sandTable/BUILD.md
T
ckochandClaude Opus 5.5 db78b1f2e6 Start Gyre from an icon: launch / quit / install-desktop
- python3 -m sandtable install-desktop puts a Gyre icon in the app grid and on
  the desktop (freedesktop .desktop entry with a "Quit Gyre" action).
- The icon runs `launch`: starts the web page in the background (no terminal,
  own session, log in .cache/server.log) if it isn't running, then opens it.
  A dialog shows the reason if it can't start.
- Quit link on the page (local computer only) and `quit`: stop any design,
  motors off, close the page.
- Gyre icon (sandtable/static/gyre.svg), also the page's tab icon.
- Simulator takes several lines per tick, so streaming tests aren't slowed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 21:25:10 -05:00

20 KiB
Raw Blame History

Gyre - build guide

This guide takes you from a pile of parts to Gyre, a sand art table, drawing in sand. It follows the order that works: case first, then the electronics, the arm on the bench, the arm into the table, a test run without sand, and finally the floor, sand and glass.

the arm, bolted to its hub, with the counterweight

Status (November 2026): the author's table is built and drawing with this software. A few v3 parts haven't been confirmed on a finished table yet:

  • the 6804 bearing hub and the parts that go with it (09, 10, 11, 26, 27);
  • the counterweight (34, 35);
  • the Uno turnaround plate (36);
  • the 12.5 mm sand ring.

They were all checked for fit in the CAD model, but print the fit tests first, and expect small adjustments.

Contents

  1. Before you start
  2. Buy the parts
  3. Print the parts
  4. Case: shell and deck
  5. Electronics
  6. Centre: bearings and spin motor
  7. The arm, on the bench
  8. Wires through the hub, hub onto the arm
  9. Arm into the table
  10. Slip ring
  11. Wiring to the CNC shield
  12. Software and the first run (no sand yet)
  13. Floor, sand, ball and glass
  14. Everyday use
  15. Troubleshooting

1. Before you start

  • Printer: the parts were designed and tuned on a Bambu Lab P1S (256 mm bed). Any printer with a bed of at least 256 × 256 mm should work; the shell quarters are the biggest parts.
  • Skills: basic 3D printing, using hex keys, crimping or plugging Dupont connectors, and running a few commands in a terminal. No soldering is needed.
  • Tools:
    • hex keys of 2, 2.5 and 4 mm;
    • a small flat screwdriver, for the drivers' current pots;
    • a multimeter, to set the driver current and match up the slip ring's wires;
    • gel superglue (CA);
    • a Dupont crimp tool, or ready-made Dupont jumper leads;
    • calipers help.
  • Computer: the table is driven from a computer over USB. The software is Python 3.11 or newer. It's tested on Linux; Windows and macOS should work but are untested.

2. Buy the parts

Part Qty Notes
Pancake NEMA17 stepper 2 About 42 × 42 × 22.5 mm, 5 mm D-shaft about 24 mm long, around 1 A. One spins the arm, one moves the magnet.
GT2 pulley, 20 teeth, 5 mm bore, for 6 mm belt 2
GT2 closed-loop belt, 200 mm, 6 mm wide 1 Spin drive
GT2 open belt, 6 mm wide about 0.5 m Arm
2020 aluminium T-slot extrusion (6 mm slot) 220 mm The arm. Cut square.
608 bearing (8 × 22 × 7 mm) 5 4 carriage rollers, 1 tip idler
6804-2RS bearing (20 × 32 × 7 mm, also sold as 61804) 2 The hub. ZZ (metal-shielded) works too.
Slip ring, 12.5 mm capsule, 6 wires, 2 A 1 Comidox or similar: flange Ø24 mm with 3 holes on an 18 mm circle, Ø5 mm centre boss. 4 wires carry the arm motor, 2 the home switch.
KW12 microswitch with a straight hinged lever 1 KW12-B (about 20 × 10.5 × 6.5 mm; the 1.1" lever is best), not the roller version
Arduino Uno + CNC shield V3 1 Or the optional ESP32 board in pcb/
Stepper drivers: DRV8825 2 A4988 also works (see step 5). TMC2208/2209 are quieter.
12 V 2 A power supply 1 For the CNC shield
USB cable for the Uno 1 A data cable; some are charge-only
Round glass, 12" (304.8 mm), 1/8" thick 1 The top
Round acrylic (plexiglass), 12", 1/8" thick, white or frosted 1 The sand floor
N52 neodymium magnets, Ø12 × 3 mm 2 Stacked
Steel ball, 3/8" 1 5/16" also works. With the 12.5 mm sand ring a 1/2" ball doesn't fit.
Fine sand a few hundred grams Fine, light-coloured decorative sand
Self-adhesive felt, about 1 mm thick small piece On top of the magnets. Furniture felt is often 3–5 mm, too thick.
Rubber feet 4 Stick-on
Dupont 2.54 mm housings and pins a 4-pin and a 2-pin pair Join the arm's wires to the slip ring's
US quarters (or steel nuts or washers) about 7 Counterweight
Optional: rubber pads about 3.5 mm thick 4–6 To raise the floor (step 13)

Screws (all metric):

Qty Screw Head Where
16 + 16 M3×8 + M3 hex nuts button Shell seams, from outside
8 M3×12 button Deck to shell
8 M3×8 button Center plate to deck
4 M3×12 socket Spin motor
4 M3×6 socket Arm motor to its bracket
5 M3×8 button Roller washers (4), idler washer (1)
3 M3×8 button Counterweight lid
2 M3×12 or M3×16 any Hub clamp collar (1), slip-ring holder (1, M3×16)
4 M3×6 button Uno turnaround plate to the deck standoffs
4 M3×6 any Uno to the turnaround plate
2 M5×12 + slot-6 drop-in T-nuts socket Hub to arm
2 M5×12 + T-nuts socket Idler bracket
2 M5×10 + T-nuts socket Arm motor bracket (with the 1 mm shim)
1 M5×8 + T-nut socket Switch mount
2 M5×10 + T-nuts socket Counterweight
2 M2×8 pan Only with the M2 switch mount; the peg version needs none

Head notes:

  • Center plate screws need low (button) heads; the arm motor bracket's bolts sweep over them.
  • M5 button heads are too wide for the 9.5 mm counterbores. Use socket heads.

3. Print the parts

All files are in print/v3/. print/README.md has the details for each part.

Bambu Studio users: print/3mf/sand-table-v3-P1S.3mf has every part on 9 plates, already oriented, with supports and settings. It takes about 23.5 hours and uses 760 g PLA plus 165 g PETG. Print plate 1, the fit tests, first.

Print the two fit tests first. The bearing fits are tuned for a P1S:

  • 00-fit-test-608: the pins should hold a 608 firmly, and a 608 should press into the pocket with a snug push. The parts use the 8.1 mm pin and the 22.2 mm pocket.
  • 00b-fit-test-6804: a 6804 should press into the 32.2 mm pocket and onto the 20.1 mm stub with a firm push.

If a different size fits better on your printer, the parts that use it need re-exporting before you print them.

Parts Qty Material How to print
01–04 shell quarters 1 each PLA Upright. No supports.
05–08 deck quarters 1 each PLA Upside down (top on the bed)
09 center plate 1 PETG or PLA Upside down
10 hub (80T pulley) 1 PETG Arm plate on the bed
11 hub clamp collar 1 PETG Flat, thin ring up
13 arm motor bracket 1 PETG Motor plate on the bed, tree supports under the T-nut plate
14 switch mount 1 PETG Flat. Pick pegs (switch glued on 2 pegs) or M2 (2 screws).
15 idler bracket, 16 idler sleeve 1 each PETG Flat as modeled
17 carriage, 18 magnet cup (short) 1 each PETG Carriage upside down
19 roller washers (4) + 19b idler washer, 20 magnet spacers 1 file each any Flat
21–24 sand ring quarters 1 each PLA Flat. Use the -12.5mm set only if you raise the floor (step 13).
25 carriage striker 1 any Flat
26 slip-ring coupler, 27 slip-ring holder 1 each PETG or PLA As modeled
30 motor bracket shim 1 PETG Flat
31 seam plate low, 32 seam plate high 4 each (one file each) PLA Flat, nut slots up
33 seam plugs 16 (one file) PLA Flat
34 counterweight, 35 lid 1 each PLA or PETG Flat, pockets up, high infill (its weight counts)
36 Uno turnaround plate 1 PLA or PETG Already turned flat side down; standoffs up

4. Case: shell and deck

seams, deck bosses and the centre in section

  1. Shell: stand the 4 shell quarters in a ring. Quarter 1 has the cable notch at the bottom.
  2. Seams: at each of the 4 seams, put an M3 nut in each slot of a high plate (32, above the deck line) and a low plate (31, below it).
    • Hold each plate against the inside of the wall and drive 4× M3×8 button heads from outside.
    • Press a plug (33) into each counterbore.
    • The low plates can also go in later from underneath, since the bottom is open.
  3. Deck: set the 4 deck quarters on the ledge and bosses inside the shell. Deck quarter 1, with the Uno standoffs, goes under shell quarter 1, the one with the notch. Fix them with 8× M3×12 straight down through the deck.
  4. Center plate: screw it to the deck with 8× M3×8 button heads.
  5. Feet: stick the rubber feet under the shell.

5. Electronics

  1. Turnaround plate: screw part 36 to the 4 Uno standoffs under deck quarter 1 with 4× M3×6 button heads, which sit flush in its counterbores. It only fits one way.
  2. Uno: screw it to the plate's standoffs, components facing down. The USB socket faces the centre of the table. That only fits one way too.
  3. CNC shield: plug it onto the Uno.
  4. Microstep jumpers: set them under the X and Y driver sockets before fitting the drivers.
    • DRV8825: fit all three (M0, M1, M2) for 1/32 steps. That matches the software's defaults.
    • A4988: fit all three for 1/16 steps. Then set theta_steps_per_deg = 35.556 and rho_steps_per_mm = 80.0 under [machine] in software/sandtable.toml.
  5. Drivers: plug them into the X and Y sockets, and stick on their heatsinks.
    • The X socket drives the spin motor (theta); the Y socket drives the arm motor (rho).
    • Check the orientation against the shield's markings (EN pin to EN). A driver plugged in backwards is destroyed.
  6. Driver current: set it before connecting the motors. On a DRV8825 the current limit is 2 × Vref.
    • Start at about 70 % of the motor's rated current. For example, a 1.0 A motor needs Vref ≈ 0.35 V.
    • Measure between the trim pot and GND with the 12 V supply on.
    • Never plug or unplug a motor while the 12 V is on.

6. Centre: bearings and spin motor

  1. Bearings: press one 6804 into the center plate's pocket from the top and one from the bottom, until each sits on the lip between them.
  2. Spin motor: put its 20T pulley on, then hang it under the center plate with 4× M3×12 socket heads from above. Leave the screws loose and slide the motor toward the centre, so the belt will go on easily later.

7. The arm, on the bench

Everything that bolts to the arm goes in from underneath, so the whole arm is built on the bench and goes into the table in one piece.

  1. Motor bracket:
    • Bolt the arm motor bracket (13) to the back end of the rail, with the 1 mm shim (30) between them. Use 2× M5×10 into T-nuts in the bottom slot.
    • Fit the arm motor with 4× M3×6 and put its 20T pulley on.
  2. Switch:
    • Fit the KW12 switch to its mount (14) with the lever facing the carriage: glue it on the pegs, or use 2× M2.
    • Bolt the mount on top of the rail's back end with an M5×8.
  3. Carriage:
    • Fit the 4 rollers: a 608 on each of the carriage's printed pins, held by a roller washer (19) and an M3×8.
    • Glue the striker (25) on top of the carriage, against its back edge.
    • Glue the magnet cup (18) into the carriage.
    • Inside the cup, stack the 3 mm spacer (20), then the 2 magnets, then the felt pad on top. Don't glue the magnets until the height has been checked in step 13.
    • Slide the carriage onto the rail from the tip end.
  4. Idler:
    • Bolt the idler bracket (15) to the tip end with 2× M5×12.
    • Fit the 608 into the idler sleeve (16) from the thick-rim side, until it sits on the ledge.
    • Put the sleeve on the bracket's pin, thin rim down, and secure it with the idler washer (19b) and an M3×8.
  5. Arm belt: loop the open belt around the motor pulley and the idler. Pull it snug and clamp both ends in the carriage's toothed slot.
  6. T-nuts for later: drop 4 into the rail's bottom slot:
    • 2 for the hub, at 63 and 97 mm from the rail's back end (17 mm either side of the hub centre, which is 80 mm from the back end);
    • 2 for the counterweight, at 146 and 182 mm.
  7. Counterweight: bolt it (34) under the far half with 2× M5×10, its pockets on the wire side (the side away from the belt).
  8. Balance:
    • Push the carriage to the middle of its travel.
    • Lay the rail across a round pencil at the hub centre, 80 mm from the back end.
    • Add quarters to the outer pocket until it sits level. Start with 7.
    • Screw on the lid (35) with 3× M3×8.

8. Wires through the hub, hub onto the arm

  1. Plugs on the arm's wires: fit Dupont plugs to the arm motor's 4 wires and the switch's 2 wires (COM and NO).
  2. Route the wires: run them along the rail's wire-side slot to the middle and lay them in the hub's top groove. Then feed the plugs down through the hub's 15 mm hole, so they hang out of the bottom of the shaft.
  3. Bolt the hub on: set it on the rail's bottom face, groove on the wire side, holes over the 2 hub T-nuts. Bolt it with 2× M5×12 socket heads from under the hub.

9. Arm into the table

  1. Spin belt: slip the 200 mm belt over the bottom of the hub shaft and onto the hub's pulley.
  2. Lower the arm in: lower the hub shaft through both bearings. On the way down, hook the belt around the spin motor's pulley. The hub's shoulder rests on the top bearing, and the plugs hang out under the center plate.
  3. Clamp collar: from below, slide the collar (11) over the hanging plugs and up the shaft, thin ring against the lower bearing and peg holes facing down. Tighten its pinch screw until it grips.
  4. Belt tension: slide the spin motor outward until the belt is snug, then tighten its 4 screws from above. Swing the arm aside to reach them.

10. Slip ring

On this slip ring, the flange and body are one fixed housing. Only the small centre boss, where the top wires come out, turns. The coupler makes the boss turn with the hub, and the holder keeps the body still.

  1. Match the wires: with a multimeter, find which bottom wire belongs to each top wire. Fit matching Dupont plugs to the top wires.
  2. Plug in: plug the slip ring's top wires into the arm's plugs, then push the joined plugs up into the hub's hole.
  3. Coupler: slide the coupler's (26) side slot over the top wires. Glue its socket onto the slip ring's turning centre boss, with gel CA on the socket wall only.
  4. Holder:
    • Set the slip ring's body in the holder (27): flange on the disc, peg in a flange hole.
    • Slide the holder's sleeve up onto the post, turning the arm so the coupler's 3 pegs go into the collar's 3 holes.
    • Fix it with an M3×16 through the sleeve into the post.
    • Leave the slip ring loose in the cup; the small play keeps its bearings from binding.

11. Wiring to the CNC shield

From To Notes
Spin motor X motor header Each coil's two wires on adjacent pins. On the reference motor: black + green, red + blue.
Arm motor (through the slip ring) Y motor header Same
Home switch (through the slip ring) Y− endstop pins COM to GND, NO to the signal pin. Y+ is the same input on the shield.
12 V supply Shield's power terminal Mind + and −. It doesn't power the Uno; USB does.
USB Uno, to the computer Out through the notch in the wall

Wrong motor directions are fixed in software (next step), so the plug orientation doesn't matter as long as each coil's pair is adjacent.

12. Software and the first run (no sand yet)

The full details are in software/README.md. In short, from the software folder:

  1. Install: pip install -r requirements.txt.
  2. USB permission (Linux): sudo usermod -aG dialout $USER, then log out and back in.
  3. Flash GRBL: with only USB connected, run python3 -m sandtable flash. It needs arduino-cli; see the software README.
  4. Settings: switch on the 12 V, then run python3 -m sandtable setup. It writes the table's GRBL settings and asks first.
  5. Directions: slide the carriage to mid-arm by hand, then run python3 -m sandtable test. It turns the arm and moves the carriage, asks whether each went the right way, and fixes the direction if not.
  6. Home: python3 -m sandtable home finds the switch.
  7. Check the scale: run python3 -m sandtable ui to open the jog panel.
    • Press +90° once: the arm should turn exactly a quarter turn.
    • Press +10 mm once: the carriage should move 10 mm outward.
    • If either goes twice as far or half as far, check the microstep jumpers (step 5). The Calibrate box can also correct it.
  8. Mirror check: python3 -m sandtable play patterns/tools/test_f.thr draws an F, which you can watch on the magnet. If it comes out mirrored, set invert_theta = true in sandtable.toml.

13. Floor, sand, ball and glass

  1. Floor: lay the acrylic disc on the shell's floor ledge.
  2. Magnet height: jog the magnet around under the floor. The felt should just touch the floor without lifting it.
    • If it lifts the floor: use a thinner felt pad, or swap the 3 mm magnet spacer for the 2 or 1 mm one. Each size down lowers the magnet 1 mm.
    • Once it's right, glue the magnets in with a drop of CA.
    • Or raise the floor: put 4–6 rubber pads, about 3.5 mm thick, evenly on the ledge, and use the 12.5 mm sand ring. The rubber also stops the floor shifting. The glass then still sits flush in the rim.
  3. Sand ring: set the 4 sand ring quarters on the floor, against the wall.
  4. Sand: pour in a thin, even layer (start with about 3 mm) and add the ball. Run an erase (step 14) and add sand until the ball leaves crisp lines.
  5. Glass: lay it on the sand ring. The two finger notches in the rim help lift it out.

14. Everyday use

Once, from the software folder, run python3 -m sandtable install-desktop. It adds a Gyre icon to your app grid and desktop (Linux). On GNOME, right-click the desktop icon once and choose Allow Launching.

From then on, click the Gyre icon. It opens a page in your browser with the design library:

  • click a design to draw it; it homes and erases the sand first;
  • Play all runs the whole list, shuffled and repeating;
  • when the designs finish (or you press Stop), the motors switch off and the page shows "Motors off". The next design homes first;
  • Upload takes .thr files (from sandify.org) and .svg line drawings.

Quit, at the bottom of the page, closes Gyre. See software/README.md for everything else, and pi/README.md to run the table from a Raspberry Pi Zero 2 W with no computer at all.

15. Troubleshooting

Symptom Likely cause Fix
"Home switch not found" The 12 V supply is off, so the motors didn't move; or the switch isn't on the Y− pins Switch the 12 V on. In the jog panel, press the switch lever by hand: "Home switch" should read "pressed".
An axis moves twice (or half) as far as it should The microstep jumpers don't match the steps setting Step 5 and step 12.7
An axis goes the wrong way Motor wiring Run python3 -m sandtable test
A motor buzzes but doesn't turn The coil pairs are mixed up Swap the middle two wires of its plug
"Home switch pressed" stop during a pattern The carriage lost its place: a slipping belt, a stall, or something blocking it Check the belts and that the carriage runs freely, then play again; it homes first
The magnet lifts the floor; the floor shifts Magnet stack too tall Step 13.2
The ball lags or drops off on fast moves Magnet too far below the floor A thicker spacer, or a slower speed on the page
The arm or hub doesn't turn freely The slip ring's flange is screwed down, or its body is glued Only the centre boss turns; leave the body loose (step 10)
Belt rubs in the arm motor bracket An old bracket with the short window Print 13 from print/v3 (the 10 mm window)
"Permission denied" on /dev/ttyACM0 Linux USB permissions sudo usermod -aG dialout $USER, then log out and back in
"USB disconnected" on the page Cable loose, or a charge-only cable Plug it back in; the page reconnects by itself and homes again before the next design

Taking the arm out later:

  1. Undo the holder screw, and lower the slip ring and coupler off the collar.
  2. Pull the joined plugs down and unplug them.
  3. Loosen the collar's pinch screw and the spin motor's 4 screws.
  4. Lift the arm and hub straight up.