
Int debugger
TUDSSL/DIPS
This is the official public repository for DIPS: Debugger for Intermittently-Powered Systems. The repository consists of all components that make DIPS: - Hardware - Debugger Firmware - Emulator Firmware - Emulator Host…

System to reduce the residual magnetic field inside the QUBIC lab's mu-metal shielded enclosure, allowing the QuSpin QZFM sensors to zero and lock reliably.
Low Current Driver is an open-source printed circuit board by Kayzerjali, from the Kayzerjali/FieldZero repository on GitHub. It is a 4-layer board of 127.8 × 53 mm with 73 parts on 53 nets, routed with 356 tracks and 65 vias.
It is built around the OPA2210ID, LTC6655CHLS8-2.5#PBF and RC0603FR-0710KL, with the TMK107B7105KA-T, RG1608P-2490-B-T5 and RC0603FR-071KL among its other parts. Its parts include 24 capacitors, 22 resistors, 6 ICs, 3 connectors and 1 switch. It belongs with the AVR (ATmega, ATtiny) boards of this library.
System to reduce the residual magnetic field inside the QUBIC lab's mu-metal shielded enclosure, allowing the QuSpin QZFM sensors to zero and lock reliably.
See docs/context.md for full project context.
In development — lab access pending.
docs/ Project documentation (grows as work progresses)
data/
raw/ Unmodified instrument output (write-once)
processed/ Script outputs only — never hand-edit
Hardware/ KiCad — coil-driver PCB (see Hardware/Low_Current_Driver/)
Common/ Shared symbol/footprint libraries
Software/ Python acquisition/analysis tooling
src/fieldzero/ Python package
scripts/
characterisation/ Field measurement and analysis
coil_cal/ Coil sensitivity calibration
nulling/ Nulling procedure support
figures/ All figure generation
tests/The Python setup and commands below are run from inside Software/.
Python 3.11+. A venv is created per machine — do not copy .venv between
machines, it hardcodes absolute paths and platform-specific wheels. Recreate it
instead; it takes about a minute.
py -m venv .venv
.venv\Scripts\activate
pip install -e ".[daq,dev]"[daq] pulls in nidaqmx. Drop it on a machine with no card — --mock needs
nothing else. Drop dev if you are not running the tests. The NI-DAQmx driver
itself is a separate install from National Instruments and is not a pip package.
Instrument PCs are often locked down. Build a wheelhouse before you go, on a machine that does have network:
.venv\Scripts\python.exe -m pip download -d wheels numpy scipy fastapi "uvicorn[standard]" nidaqmxCopy wheels/ across with the repo, then on the lab machine:
py -m venv .venv
.venv\Scripts\activate
pip install --no-index --find-links wheels -e ".[daq]"The front end needs no network either — uPlot is vendored into
src/fieldzero/viewer/static/vendor/ rather than loaded from a CDN.
python -m fieldzero.viewer # against the NI-DAQ
python -m fieldzero.viewer --mock # no hardware requiredOpens a browser at http://127.0.0.1:8000. Split any pane left/right or
top/bottom and choose what goes in it: time domain, frequency domain (amplitude
or ASD), or phase (any channel against any other, with Pearson r and fitted
slope). The stats table below the panes gives per-channel mean and standard
deviation, and flags any channel sitting at the input rail.
Layouts persist across reloads and can be saved to / loaded from JSON.
Run scripts/characterisation/verify_acquisition.py [--mock] on arrival at the
lab to confirm the DAQ is reading every channel before starting a measurement.
The viewer binds to loopback, so a Windows firewall prompt on first run can be
declined. Use --host 0.0.0.0 to watch from a laptop while the DAQ machine sits
in the shielded room — that one does need the firewall exception.
A plain matplotlib window. No server, no browser, no socket — a timer reads the ring buffer in-process, so there is nothing between acquisition and the screen that can stall, congest or time out. Use it if the browser viewer feels sluggish on a given machine, or when you just want a scope up in one command.
It runs the same reducers as the browser viewer, so the DSP is identical: the same windowing, the same ASD scaling, the same volts-based rail check, the same correlation maths. Only the drawing differs.
python -m fieldzero.scope # against the NI-DAQ
python -m fieldzero.scope --mock # no hardware requiredWith no --pane, you get one time-domain plot of all six channels. Close the
window to stop it.
--pane takes KIND or KIND:CH,CH,... and is repeatable — each one adds a
plot, stacked top to bottom in the order you give them.
| kind | channels | shows |
|---|---|---|
time | any number (default: all six) | rolling time trace, newest sample at t=0 |
spectrum | any number (default: all six) | amplitude spectral density, log axis |
phase | exactly two | first against second, with a least-squares fit |
Channel names are S1-X, S1-Y, S1-Z, S2-X, S2-Y, S2-Z — the same names
the stats table uses. Get one wrong and it tells you the valid ones and exits.
# one time plot of two channels, and their spectrum underneath
python -m fieldzero.scope --pane time:S1-X,S2-X --pane spectrum:S1-X,S2-X
# is sensor 2 seeing the same field as sensor 1?
python -m fieldzero.scope --pane phase:S1-X,S2-X
# what is the residual on the Z axis, in raw volts, over 10 seconds?
python -m fieldzero.scope --pane time:S1-Z,S2-Z --units V --window 10| flag | default | what it does |
|---|---|---|
--mock | off | simulated source; no DAQ needed |
--window N | 5 | seconds of history each pane shows |
--units pT|V | pT | display units. Volts are ground truth — the V/nT figure is unverified |
--fps N | 10 | redraw rate. Drop it to 5 on a slow machine |
--sample-rate N | 1000 | samples/second per channel. Startup only |
The red or grey strip along the top is the readout, updated twice a second:
A phase pane also prints its Pearson r and fitted slope into that strip: r near 1 means both channels are seeing the same field, and the slope is the gain ratio between them.
Panes are fixed at launch. There is no clicking, no splitting, no changing
channels while it runs — to change the layout, close it and relaunch with
different --pane flags. That is the trade for having nothing that can go wrong.
scope.pyRendering uses blitting, and has to. A full matplotlib redraw of three panes costs ~120 ms (~8 fps), and the cost is the redraw itself — thinning the data does not help. Blitting the traces over a cached background costs ~20 ms instead. Two consequences are load-bearing:
test_scope.py asserts steady state needs none.Sample rate is a startup parameter (--sample-rate, default 1000 Hz), not a
runtime one: changing it means rebuilding the DAQ task, and doing that mid-run is
what made the previous project's axis switching unreliable. The task is opened
once over all six channels and never reconfigured; selecting an axis is purely a
display concern.
Acquisition yields volts. The V/nT conversion is applied at display time (see below) — so saturation is detected against the known input range rather than an unverified sensitivity figure.
| Item | Status |
|---|---|
| QuSpin QZFM sensors × 2 | In lab — gen TBD |
| Cancellation coils | Not yet installed |
| Current source | TBD |
| NI-DAQ (Dev1, ai0–ai5) | In lab — model TBD, confirm in NI MAX |
Three acquisition settings in src/fieldzero/config.py need confirming against
the actual card. MEG_DSP never set them, so it silently ran on the nidaqmx
defaults:
| Setting | Value | Why it matters |
|---|---|---|
voltage_range | ±5 V | Where a channel clips. This is the nidaqmx default, never a decision. At the inherited 2.7 V/nT that is a clip at ~1.85 nT — and the residual field is believed to be nT-scale, so channels may already be railing. |
terminal_config | RSE | RSE vs differential materially changes the noise floor. |
sensitivity_v_per_nT | 2.7 | Unverified — inherited from MEG_DSP, and the QZFM generation is still unconfirmed. Volts are ground truth until this is checked against the sensor label. |
| Qty | Value | Footprint | References |
|---|---|---|---|
| 12 | 100n | Capacitor_SMD:C_0603_1608Metric_Pad1.08x0.95mm_HandSolder | C14, C19, C20, C21, C30, C31, C36, C37, C38, C39, C40, C41 |
| 12 | TestPoint_Probe | TestPoint:TestPoint_Pad_D1.0mm | 2.5V, Coil, Coil, DAC1, DAC2, GND, GND, GND, HCP, HCP, MSB, RS |
| 10 | 10k | Resistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolder | R18, R19, R26, R27, R28, R29, R30, R31, R34, R37 |
| 8 | 1u | Capacitor_SMD:C_0603_1608Metric_Pad1.08x0.95mm_HandSolder | C27, C32, C33, C34, C49, C50, C52, C53 |
| 8 | 249 | Resistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolder | R38, R39, R40, R41, R44, R45, R46, R47 |
| 4 | 1k | Resistor_SMD:R_0603_1608Metric_Pad0.98x0.95mm_HandSolder | R32, R33, R35, R36 |
| 4 | MountingHole_Pad | MountingHole:MountingHole_2.2mm_M2_DIN965_Pad | H1, H2, H3, H4 |
| 4 | OPA2210 | Package_SO:SOIC-8_3.9x4.9mm_P1.27mm | U11, U12, U13, U14 |
| 2 | 4.7u | Capacitor_SMD:C_0603_1608Metric_Pad1.08x0.95mm_HandSolder | C54, C55 |
| 2 | Conn_01x02_Socket | Connector_Molex:Molex_Micro-Fit_3.0_43650-0215_1x02_P3.00mm_Vertical | J1, J2 |
| 1 | 10n | Capacitor_SMD:C_0603_1608Metric_Pad1.08x0.95mm_HandSolder | C29 |
| 1 | 10u | Capacitor_SMD:C_1206_3216Metric_Pad1.33x1.80mm_HandSolder | C28 |
| 1 | Arduino_Nano_R4 | Module:Arduino_Nano | A1 |
| 1 | DAC8814 | Package_SO:SSOP-28_5.3x10.2mm_P0.65mm | U8 |
| 1 | LTC6655-2.5 | Package_LCC:Analog_LCC-8_5x5mm_P1.27mm | U7 |
| 1 | SW_DPST | fieldZero:DPST_RA83231100 | SW1 |
| 1 | Screw_Terminal_01x04 | TerminalBlock_Phoenix:TerminalBlock_Phoenix_MKDS-1,5-4-5.08_1x04_P5.08mm_Horizontal | J3 |
It measures 127.8 × 53 mm and has 4 copper layers, 1.6 mm thick.
73 parts, built around the OPA2210ID, LTC6655CHLS8-2.5#PBF, RC0603FR-0710KL and TMK107B7105KA-T. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the Kayzerjali/FieldZero repository on GitHub, at the commit this page was made from: the board is Hardware/Low_Current_Driver/Low_Current_Driver.kicad_pcb and its schematic Hardware/Low_Current_Driver/Channel_Outputs.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository states no licence, so its author keeps all rights: ask Kayzerjali before reusing the design.

TUDSSL/DIPS
This is the official public repository for DIPS: Debugger for Intermittently-Powered Systems. The repository consists of all components that make DIPS: - Hardware - Debugger Firmware - Emulator Firmware - Emulator Host…


Strathclyde-EQOP/Vernier-Current-Driver
The Vernier Current Driver is an ultra low noise, programmable, bi-polar current source. It comes in two flavours:



Gady159/Gadas_MSE_ELoad
Master's thesis project by Jan Gadas: STM32 firmware, Nextion HMI and KiCad hardware design files for a modular high-power electronic load.


iandchasse/silkscreen-pcb
Silkscreen: open-hardware ESP32-S3 e-paper reader mainboard (KiCad 9). Formerly the de-link hub.