A 3D-printed, field-adjustable 5-element uniform circular array (UCA) for direction finding with the KrakenSDR. A symmetric pantograph linkage lets you slide the array from fully folded to fully extended, and every dipole stays perfectly plumb at every radius. Print the parts once, cut three sets of fiberglass tubes, and cover 44 MHz to 1.66 GHz.
- How it works
- Quick start
- Frequency coverage and its limits
- Choosing your strut set
- Band presets, Standard set
- Bill of materials
- Printing guide
- Assembly
- Feedline and coax routing
- Field procedure
- Regenerating the STLs
- Troubleshooting
- Roadmap
- License
Five dipoles sit on a circle at 72 degree spacing. Each arm is a symmetric two-strut pantograph: the lower strut pivots on the fixed lower hub, the upper strut pivots on a sliding upper hub, and both meet at a tip fitting that holds the dipole. Because the linkage is symmetric, the tip fitting cannot tilt. Slide the upper hub and the whole array breathes in and out with every element plumb.
Three numbers govern everything:
| Symbol | Meaning | Value |
|---|---|---|
a |
pivot offset, hub pin to mast axis | 25 mm |
L |
strut length, pin to pin | 200 / 380 / 850 mm by strut set |
t |
tip fitting pin to pin | 60 mm |
From those: r = a + L·cos(θ) where θ is the strut angle (0 degrees flat and widest, 75 degrees folded and smallest), and the element spacing is s = 2r·sin(36°) = 1.1756·r.
r is what goes into the KrakenSDR config. s is what you set with a tape measure.
Here is the mechanism in motion. This animation plays right here on the repo page:
Try it yourself, live:
- Interactive model: drag the slider to run the array from fully folded to fully extended, switch strut sets, and watch r, s, θ, and the frequency limits update live
- Array calculator: enter any frequency, get the radius, the tape-measure spacing, the KrakenSDR config value, and a verdict for every strut set
These run on GitHub Pages (Settings, then Pages, then deploy from branch, main and /docs). GitHub does not execute scripts inside a README, so the animation above is the moving preview and the links are the full interactive tools. Both also work offline by opening docs/model.html and docs/calculator.html in any browser.
- Print
stl/tenticles_tolerance_coupon.stland verify every fit (printing guide) - Print the rest of the parts (about 24 to 30 hours total)
- Cut ten fiberglass strut tubes and one mast tube for your strut set
- Epoxy the strut ends, pin the arms, mount the hubs (assembly)
- Bolt the bulkhead panel under the lower hub and run the jumpers (feedline)
- Open the calculator, set your band, measure
s, enterr, calibrate, and take bearings
The top of each strut set's range is a hard wall. Direction finding with a UCA requires s ≤ λ/2; beyond that, bearings become ambiguous and jump between values. The smallest spacing the mechanism can reach is at full fold (θ = 75 degrees), so each strut set has a hard ambiguity ceiling at f = c / (2·s_min).
The bottom of the range is soft. As spacing shrinks below the optimal 0.33 to 0.45 λ window, accuracy degrades gradually rather than failing. Usable results extend down to roughly 0.15 λ, and the chart above fades the bars over that region.
| Spacing | Behavior |
|---|---|
| 0.50 λ and above | Ambiguous, unusable |
| 0.33 to 0.45 λ | Optimal accuracy window |
| 0.25 λ | Good, slightly reduced accuracy |
| 0.15 λ | Usable, noticeably reduced accuracy |
| 0.10 λ | Marginal, phase differences small relative to noise |
No printed part changes between strut sets. L is a property of the tubes you cut, not the parts you print. Print once, buy three sets of tubes.
| Strut set | L (pin to pin) | Tube cut length ×10 | Mast length | Radius range | Ambiguity ceiling |
|---|---|---|---|---|---|
| Compact | 200 mm | 170 mm | 600 mm or more | 77 to 225 mm | 1661 MHz |
| Standard | 380 mm | 350 mm | 1000 mm or more | 123 to 405 mm | 1034 MHz |
| VHF | 850 mm | 820 mm | 1900 mm or more | 245 to 875 mm | 520 MHz |
Rules of thumb:
- Above 1 GHz (including 1090 MHz ADS-B): Compact only. The Standard set's ceiling is 1034 MHz, and ADS-B sits just past it.
- UHF workhorse bands (433, 446, 462, 868, 915 MHz): Standard. All hit the optimal window.
- VHF (air band, 2 m, marine): VHF set. Standard reaches these bands but only at reduced spacing; the VHF set puts them in the optimal window and its soft floor extends to about 44 MHz.
The mast must cover the full slider travel plus roughly 100 mm of hub body and 100 mm of mounting stub below the lower hub.
These presets are for the Standard (L = 380 mm) strut set, targeting 0.45 λ where the mechanism can reach it. For other sets the formulas are identical; only L changes. The calculator computes any of these live.
| Band | MHz | Set spacing s | Config radius r | Achieved spacing | Whip leg (λ/4 × 0.95) |
|---|---|---|---|---|---|
| Air emergency | 121.5 | 476 mm (max) | 405.0 mm | 0.19 λ | 586 mm |
| 2 m amateur | 146.0 | 476 mm (max) | 405.0 mm | 0.23 λ | 488 mm |
| Marine ch 16 | 156.8 | 476 mm (max) | 405.0 mm | 0.25 λ | 454 mm |
| 433 ISM | 433.9 | 311 mm | 264.5 mm | 0.45 λ | 164 mm |
| PMR446 / 70 cm | 446.0 | 303 mm | 257.3 mm | 0.45 λ | 160 mm |
| GMRS | 462.6 | 292 mm | 248.1 mm | 0.45 λ | 154 mm |
| 868 ISM | 868.0 | 155 mm | 132.2 mm | 0.45 λ | 82 mm |
| 915 ISM | 915.0 | 147 mm | 125.4 mm | 0.45 λ | 78 mm |
| ADS-B | 1090.0 | not reachable | not reachable | above ceiling | use Compact set |
At the VHF rows the Standard set runs out of reach before hitting 0.45 λ, so it operates at max radius with reduced spacing. Functional, with lower accuracy. The VHF strut set puts those bands in the optimal window.
Full list with quantities and notes in hardware/BOM.md. The short version:
| Qty | Item | Notes |
|---|---|---|
| 2 | Printed hub | one lower fixed, one upper flipped as the slider |
| 10 | Printed strut end | epoxied into each tube end |
| 5 | Printed tip fitting | holds the dipole boom |
| 1 | Printed mast plug | tripod interface, 3/8-16 stud |
| 1 | Printed bulkhead panel | 5 SMA ports under the lower hub |
| 10 | Ø10 mm OD fiberglass tube, 170 / 350 / 820 mm | struts; tabs add 15 mm per end to reach L |
| 1 | Ø25 mm OD fiberglass tube, 600 / 1000 / 1900 mm | mast; must cover slider travel |
| 1 | Arrow Antennas 440 MHz 5-element dipole set | or equivalent for your band |
| 5 | BNC-male to SMA-male jumper, RG316, 60 cm | one matched batch |
| 10 | SMA female to female bulkhead jack, 50 Ω | buy a 10 pack, PTFE and gold pin |
| 1 | SMA torque wrench, 5 in-lb | the cheapest accuracy upgrade there is |
| M4 bolts and nyloc nuts, M5 thumbscrews, M3 heat-set inserts and screws, epoxy | see BOM | |
| ~700 g | PETG filament | order 2 × 1 kg spools |
Fiberglass is mandatory for the mast and struts. Carbon fiber tube and carbon-filled filament are electrically conductive and will corrupt the RF performance of the array. PVC is fine on the bench for prototyping, but it sags and UV-degrades, so do not deploy it permanently outdoors.
Material: PETG or ASA. Not PLA, which creeps and embrittles under UV and heat, and dimensional creep becomes element position error. Not carbon-filled filament, for the conductivity reason above.
| Setting | Value |
|---|---|
| Layer height | 0.2 mm |
| Perimeters / walls | 4 |
| Top / bottom layers | 5 |
| Infill | 40 percent, gyroid |
| Nozzle | 0.4 mm |
| Part | Orientation | Supports |
|---|---|---|
| Hub | flat, slots facing up | none |
| Strut end | lying on its flattened underside | none |
| Tip fitting | standing upright | yes, under the fork blocks |
| Mast plug | flange down | none |
| Bulkhead panel | flat, hex pockets up | none |
| Coupon | flat | none |
The coupon carries every critical fit: the Ø25.6 mast bore, Ø16.2 boom bore, Ø4.2 pin hole, the 6.4 mm tab slot, and the Ø6.4 SMA hole with its hex counterbore. Check all of them:
- Ø25 mast tube slides through the bore with light drag, no force
- M4 bolt turns freely in the pin hole
- A printed strut tab drops into the slot with slight play, no wobble
- Dipole boom slides into the boom bore
- A real SMA bulkhead drops through the SMA hole and its nut seats in the hex pocket
If any fit is wrong, do not sand the tubes. Edit the parameter at the top of scripts/gen_tenticles.py and regenerate. Typical adjustment is plus or minus 0.2 mm.
Roughly 24 to 30 hours total. Print one strut end early and test-fit it in the coupon slot before committing to all ten.
Full walkthrough with photos and QA checks in docs/BUILD_GUIDE.md. The sequence:
- Bond the strut ends. Dry-fit first: insert a tab into each end of each tube and check the pin-to-pin distance hits your set's
L. Shim any tube that lands long or short. Matching all ten struts to within 1 mm matters more than the absolute number, because arm-to-arm variation is direct element position error. - Epoxy the tabs and let them cure fully.
- Ream the pin holes. Ø4.2 prints slightly tight on most printers; run a 4 mm drill or an M4 bolt through by hand.
- Mount the lower hub slots-up near the bottom of the mast and lock the thumbscrew. This hub is the fixed datum. For any motorized version it must be pinned through the mast, not just friction-clamped.
- Mount the upper hub flipped, slots-down, above it. It should slide freely.
- Pin one complete arm with M4 bolts and nyloc nuts, snug but not tight; these joints must rotate freely.
- Cycle the arm through its full travel and confirm the tip fitting stays plumb the whole way. Fix binding now, then pin the other four arms.
- Bolt the bulkhead panel to the underside of the lower hub with three M3 screws into the heat-set inserts. The rim notch aligns port 0 with arm 0, the dimpled arm.
- Fit the dipoles into the tip fitting boom sockets and snug the M5 clamp screws.
The rule: every arm's cable path must be a rotational copy of every other arm's. Phase repeatability is the entire game in direction finding.
- Coax exits the boom bottom into one identical service loop of about 50 mm diameter per arm. The loop absorbs the motion when you change radius.
- Velcro-tie to the lower strut at three marked points: below the tip fitting, mid-strut, above the hub tab.
- Each jumper lands on its own SMA port on the panel, straight down its own strut line.
- Below the panel, all five tails spiral once around the mast in the same direction, then run down as a taped bundle to the Kraken.
Cut or buy all five jumpers the same length within 5 mm, label both ends 0 through 4, and always connect them to the same Kraken channels. After the first calibration, the channel-to-arm mapping is part of the calibrated system. Torque every SMA connection to 5 in-lb with the torque wrench.
Every time you change bands:
- Slide the upper hub until the tape measure reads the preset
sbetween adjacent tips. Verify on two or three arm pairs; if they disagree, a pivot is binding. - Lock the hub thumbscrew.
- Extend all five dipole whips to the preset leg length. Use calipers.
- Enter the corresponding radius
rin the KrakenSDR config; array type UCA, 5 elements. - Note or set the heading offset for element 0, the dimpled arm.
- Run the noise-source calibration. Re-run it after every power cycle and after any significant temperature swing.
Siting matters more than build tolerance. Multipath from nearby structures is the dominant real-world error source, larger than anything in your printed parts. Mount as high and clear as possible, and keep whatever ground plane sits under the array symmetric.
All parts come from scripts/gen_tenticles.py. Every dimension is a named constant at the top of the file, and the script validates that every part is watertight before export.
pip install trimesh manifold3d numpy
python scripts/gen_tenticles.py| Want to change | Edit |
|---|---|
| Printer runs tight or loose | BORE_D, SLOT_W, PIN_D, SOCK_ID, BOOM_ID |
| Different mast tube | BORE_D, and PLUG_STEM_D (measure your tube ID) |
| Different radius range | Do not edit the script. Cut different strut tubes. See Choosing your strut set |
| Different tip pin spacing | TIP_T (= t), then recompute the presets table |
| Symptom | Likely cause |
|---|---|
| Bearings consistently offset by a fixed angle | Element-0 heading offset wrong in config |
| Bearings ambiguous, jumping between values | Spacing exceeds 0.5 λ. Reduce radius, and if you are already at minimum radius you are above this strut set's ceiling; switch to a shorter set |
| Bearing error varies with signal direction | Common-mode currents; check choke symmetry and cable dressing |
| Bearing accuracy poor but stable | Radius in config does not match the actual radius; re-measure and verify the chord equals 1.1756 × r |
| Tip fittings tilt off plumb | Unequal hub pivot offsets; check for burrs under the flipped upper hub |
| Arms bind mid-travel | Over-tightened nyloc nuts, or a fork slot too narrow |
| Accuracy degrades over weeks outdoors | Printed in PLA; reprint in PETG or ASA |
- Split-clamp hub rework. The current set-screw lock is not adequate for a 52 mm bore or motorized operation.
- Motorized v2. TR8×2 leadscrew, ESP32 with a TMC2209 stepper driver, controlled from the Raspberry Pi that runs the KrakenSDR software. The lower hub becomes a pinned datum.
- Starlink Mini top adapter. A printed adapter meets the 52 mm mount requirement without altering any existing mast geometry, for the remote networked listening post deployment.
MIT. Use it, fork it, improve it. If you build one, an issue with photos and your measured accuracy would be welcome.
Disclaimer: This is a receive-only antenna array. You are responsible for complying with the laws in your jurisdiction regarding radio monitoring and direction finding.
