Experiment control and others

Drivers for FPGA controllers and auxiliary devices such as ADwin, NI-FPGA and Red Pitaya, covering the full spectrum of experiment control requirements from nanosecond real-time timing to general-purpose switching logic.

Overview

FPGA controllers and auxiliary devices are an essential part of experiment automation: from nanosecond real-time timing to relay switching, Quatm provides a unified control interface. ADwin, NI-FPGA, Red Pitaya and several other brands are currently supported.


ADwin

Overview

ADwin is a family of real-time controllers from Jaeger Computergesteuerte Messtechnik, based on an FPGA/DSP architecture, that executes real-time tasks independently of the PC operating system.

ADwin Gold II / Pro II
CommunicationPCI / USB
ProcessorDSP + FPGA
Timing precisionnanosecond level
Analog input16-bit
Digital I/OTTL (5V)
Memory32 MB DRAM
It runs real-time processes compiled from ADbasic and communicates with Quatm through shared memory or register reads and writes. Typical applications include laser cooling timing, MOT magnetic field switching and photon counting acquisition.
Driver module: ADwin

How it works

PC (Quatm)                    ADwin (real-time)
┌──────────┐    PCI/USB    ┌──────────────┐
│ experiment│ ←──────────→ │ ADbasic proc │
│   .py     │  Par/Data    │ ns timing+acq│
└──────────┘               └──────────────┘

Quatm experiment scripts read and write parameters and data arrays through the ADwin driver, interacting with the ADbasic process running on the ADwin. The timing-critical parts execute on the ADwin hardware, while the Python side handles parameter setting and result readout.

Initialization

from quatm.drivers.fpga import ADwin

# Connect to ADwin (PCI bus)
adw = ADwin(device_number=1)

# Load and start the ADbasic process
adw.load_process("experiment_sequence.TB1")
adw.start_process()

# Set experiment parameters
adw.set_par(1, 100_000)     # Par_1 = 100 µs cooling time
adw.set_par(2, 50)          # Par_2 = 50 cycles
adw.set_par(3, 10_000)      # Par_3 = 10 ms detection time

# Start one experiment sequence (triggered by an event in ADbasic)
adw.trigger()

# Read acquired data
photons = adw.get_data(1, data_length=1000)  # Read photon counts from Data_1

Key methods

MethodDescription
load_process(binary_path)Load an ADbasic-compiled binary process
start_process()Start the loaded process
stop_process()Stop the running process
set_par(index, value)Write an integer parameter (1–80)
set_fpar(index, value)Write a floating-point parameter (1–80)
get_par(index)Read an integer parameter
get_data(index, data_length)Read a data array (1–200)
set_data(index, values)Write a data array
trigger()Send a software trigger event

Typical ADbasic process structure

' ADbasic code snippet — experiment timing
Init:
  Par_1 = 100000   ' Cooling time (µs)
  Par_2 = 50       ' Number of cycles
Event:
  For i = 1 To Par_2
    P2_DAC(1, 5000)   ' Set AOM power
    P2_DAC(2, 800)    ' Set magnetic field
    ' ... wait, acquire, switch ...
  Next i

Device configuration

"fpga": {
    "type": "local",
    "module": "quatm.drivers.fpga",
    "class": "ADwin",
    "arguments": {"device_number": 1},
}

Exception:

  • quatm.drivers.fpga.adwin.AdWinDriverError(message)

    class quatm.drivers.fpga.adwin.AdWinDriverError(Exception):
        pass
    

quatm.drivers.fpga.client module

Class:

  • quatm.drivers.fpga.client.AdWinClient(experiment, simulating=None)

    class quatm.drivers.fpga.client.AdWinClient(object):
        def filter_cmdlist(self, combinetime=1e-08):
            pass
    
        def push(self, time, command, value, combinetime=1e-09):
            pass
    
        def start_realtime(self, processortime=0, repetitions=1):
            pass
    
        def stop(self):
            pass
    

quatm.drivers.fpga.units module


NI-FPGA LabVIEW FPGA modular instruments

PXIe-78xxR / PCIe-78xxR series NI-FPGA
CommunicationNI-FPGA Interface Python API
FPGAXilinx Kintex/Virtex
Digital I/Oup to 1 Gb/s
Analog I/Oup to 3.2 GS/s
ProgrammingLabVIEW FPGA + Python runtime control
Controls LabVIEW FPGA bitstreams at runtime through the nifpga Python API. Suited to custom digital signal processing requiring very high throughput and deterministic timing.
Driver module: ni_fpga
from quatm.drivers.NI.ni_fpga import NIFPGA

fpga = NIFPGA(resource_name="RIO0", bitfile="custom_logic.lvbitx")
fpga.run()
fpga.write_control("pulse_width", 100)        # ns
fpga.write_control("trigger_delay", 50)
fpga.read_indicator("photon_count")

Conrad relay board

Relay Board Conrad
Communicationserial (19200 baud)
Channels8 relays per board
Supportdaisy-chain expansion
An economical multi-channel relay controller, suited to magnetic trap coil polarity switching, device power switching and laser shutter control.
Driver module: RelayBoard
from quatm.drivers.Conrad.base import RelayBoard

rb = RelayBoard(conn="/dev/ttyUSB0", start_addr=0)
rb.set_relay(relay=0, state=True)
rb.set_relay(relay=3, state=False)
rb.write_byte(0b10101010)