Skip to content

Repository files navigation

HelmCalib

License: MIT Platform Lazarus / FPC Delphi VCL

Magnetic-field calibration and open-loop field programming for a 3-axis Helmholtz coil system (Bartington BHC2000), with a built-in 3D view of the generated field vector.

3D view of the coil system and the field vector

The 3D view: square copper coils on a cubic aluminium frame; coils on the axes that dominate the target field are highlighted in orange. Rotatable with the mouse.

The app drives the three coil axes through HelmMagControl (TCP) and measures the resulting field with the magnetometer of a phone running SensorCast (UDP). From those samples it fits the affine model B = M·I + b and, once calibrated, computes the currents needed to generate a requested target field.

Lab tool. Primary version in Lazarus / Free Pascal (LCL), cross-platform, with no external dependencies (UI and 3D drawn on Canvas, networking on the RTL sockets, JSON via fpjson). A Delphi (VCL) port lives in delphi/ — see below.

Features

  • Connection (live): TCP client for HelmMagControl (READ ALL polling) and UDP client for SensorCast (magnetometer + K-sample averaging).
  • Calibration wizard: automatic current sweep → settle → average K samples → least-squares fit. Manual point capture, RMS residual, and profile save/load (JSON).
  • Open-loop field programming: given a target B vector (coil frame), it computes the currents with per-axis clamping, warns on saturation, and shows the actually achievable field. A nominal catalog model is available before calibrating.
  • 3D view: wireframe of the support cube and the three square Helmholtz coil pairs to scale, plus the B-vector arrow. Rotate with the mouse, zoom with the wheel, drawn on Canvas with no 3D libraries. Coils on the dominant axis of the target field are highlighted.

Calibration math

Sensor frame: B = M·I + b, with M 3×3 (µT/A) and b 3×1 (µT, ambient field).

  • Fit (least squares, normal equations): A = [M|b] = (Σ Bₖ·xₖᵀ)·(Σ xₖ·xₖᵀ)⁻¹, with xₖ = [Iₖ; 1]. Needs ≥ 4 non-coplanar points (including I = 0).
  • Polar decomposition M = R·G (Jacobi on MᵀM): R coil→sensor rotation, G symmetric gain ≈ diag(kₓ, k_y, k_z).
  • Open loop: I = G⁻¹·(B_target − Rᵀ·b), then clamp to ±I_max per axis.

Architecture

Unit Responsibility
uMatrix 3×3/4×4 linear algebra: inverses, least squares, Jacobi, polar/SVD.
uCoils TCP client for the HelmMagControl text protocol (pure protocol logic + TCoilClient).
uSensor UDP client for SensorCast (pure ParseSensorJSON + threaded TSensorClient).
uCalib B=M·I+b model: points, fit, polar decomposition, RMS residual, JSON profile, nominal/manual model.
uField Open-loop field programming: inverse + clamp + achieved field + send.
uView3D TView3DPanel: wireframe 3D view drawn on Canvas.
uMainForm Main form with the four tabs.

Application

Four tabs: Connection · Calibration · Program field · 3D view.

Connection Program field
Connection tab Program field tab

Calibration sweep

The calibration wizard drives a sequence of current combinations (0, ±I per axis, and mixes); for each point it lets the field settle and averages K magnetometer samples. The animation below shows the swept points: the energized axes light up and the resulting B vector points in the corresponding direction.

Calibration current sweep

Programming a field

Once calibrated (or with the nominal catalog model), you request a target B vector in the coil frame and the app computes the per-axis currents I = G⁻¹·(B − Rᵀ·b), clamping to the current limits. The animation shows the target B sweeping through directions and the currents computed for each one.

Program field — computed currents

Build & test

Requires Lazarus / FPC 3.2.2.

# GUI app -> lib/x86_64-win64/HelmCalib.exe
bash build.sh

# Console tests for the logic (105+ assertions, exit = number of failures)
bash tests/run.sh

build.sh generates the project resource (HelmCalib.res, with a manifest for themes/DPI) via fpcres before invoking lazbuild. You can also open HelmCalib.lpi directly in the Lazarus IDE.

Delphi (VCL) port

delphi/ contains an equivalent Delphi (VCL, Win64) version, tested with RAD Studio Athens (Delphi 37.0). Same architecture and the same units; only the platform dependencies differ:

  • Networking: Indy 10 (TIdTCPClient, TIdUDPClient) instead of the RTL sockets.
  • JSON: System.JSON instead of fpjson.
  • UI/3D: VCL (Vcl.*) with .dfm instead of LCL/.lfm.
cd delphi
bash build.sh          # GUI -> delphi/HelmCalib.exe (or open HelmCalib.dproj in the IDE)
bash tests/run.sh      # 115 logic assertions, exit = number of failures

The logic is covered by the same console tests (115 assertions); the GUI and 3D view were verified on Win64.

Remote control (TCP)

HelmCalib embeds a TCP text server (same style as HelmMagControl) so the whole system can be driven remotely from Python or any language. Enable it from the Connection tab (default port 4445) or start the app with -remote (-remote -port=NNNN for a custom port).

One line per command, responses OK ... / ERROR ..., UTF-8:

PING · STATUS · HELP
CONNECT COILS <host> <port> · CONNECT SENSOR <ip> [tx] [rx] · DISCONNECT COILS|SENSOR
GET MAG · GET MAGAVG <k> · READALL
MODEL NOMINAL A|B · LOAD PROFILE <path> · SAVE PROFILE <path> · GET MODEL
SOLVE <bx> <by> <bz> · SETFIELD <bx> <by> <bz> · SETCURRENTS <i1> <i2> <i3> · FIELDOFF
CALIB CLEAR · CALIB ADD <ix iy iz bx by bz> · CALIB COUNT · CALIB FIT

A Python client is provided in python-client-for-helmholtz-rig (HelmCalibClient):

from helmcalib_control import HelmCalibClient
c = HelmCalibClient("127.0.0.1", 4445); c.connect()
c.model_nominal("A")
print(c.solve(40, 20, 60))          # -> {'I': (1.61, 0.79, 2.39), 'saturated': False, ...}
c.connect_coils("127.0.0.1", 4444)
c.set_field(40, 20, 60)             # computes and sends the currents

Reference hardware

  • Coils: Bartington BHC2000 (3 orthogonal pairs). Model A: ~25 µT/A, 1.0 mT/axis, 40 A. Model B: ~15 µT/A, 240 µT/axis, 16 A.
  • Actuator: Wanptek power supplies via HelmMagControl, TCP text protocol (port 4444).
  • Sensor: Android phone running SensorCast at the center of the coils (UDP, JSON every 200 ms).

Status

All four tabs (Connection · Calibration · Program field · 3D view) are operational. The logic is covered by console tests with synthetic data; the network I/O compiles and the protocol/parsing logic is verified — end-to-end testing against the real hardware is left for commissioning.

See CHANGELOG.md for the per-version detail.

License

Released under the MIT License.

About

Magnetic field calibration and open-loop field programming for 3-axis Helmholtz coils (Bartington BHC2000), with 3D view. Lazarus/FPC.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages