Skip to main content

A python library/GUI.

Project description

pyTriggerSync

pyTriggerSync is a Python library/GUI interface for a Teensy microcontroller running the Send_Trigger_Synced_With_External_Trigger_OnlyRemoteControl firmware. The Teensy generates an output trigger pulse synchronized to an external trigger signal received on its input pin, either continuously or in user-controlled bursts. The package is composed of two parts: a low-level driver for serial communication, and a high-level GUI written with PyQt5 that can be easily embedded into other GUIs.

The interface can work either as a stand-alone application, or as a module of ergastirio.

Table of Contents

Installation

Use the package manager pip to install,

pip install pyTriggerSync

This will install pyTriggerSync together with pyserial, which is required by the low-level driver. In order to use the GUI, it is also necessary to install

pip install abstract_instrument_interface>=0.10
pip install "PyQt5>=5.15.6"

Usage via the low-level driver

pyTriggerSync provides a low-level driver to communicate with the Teensy device over a USB serial connection.

from pyTriggerSync.driver import pyTriggerSync
device = pyTriggerSync()
available_devices = device.list_devices()
print(available_devices)
device.connect_device(port=available_devices[0].split(':')[0])
print(device.mode)
device.disconnect_device()

The method list_devices() scans all serial ports and returns a list of descriptor strings for compatible devices. Each string is in the form "<port>: <description> [<hwid>]", e.g. "COM4: USB Serial [USB VID:PID=16C0:0483 ...]". The port can be extracted from the first element by splitting on ':'.

The class pyTriggerSync exposes several properties and methods to communicate with the device and read or change its settings. All properties and methods that communicate with the device require a connection to be active; they raise RuntimeError if called while disconnected.

Creating a driver instance

pyTriggerSync(port='COM4', baudrate=115200, timeout=0.1)
Parameter Type Description
port str, optional Default serial port to connect to. Used by connect_device() when no port is explicitly specified. Default is 'COM4'.
baudrate int, optional Baud rate for the serial connection. Must match the firmware (115200). Default is 115200.
timeout float, optional Read timeout in seconds for the serial connection. Default is 0.1.

Properties

The following are implemented as Python @property, i.e. they are accessed without parentheses (e.g. device.mode) and, when settable, assigned with = (e.g. device.mode = 1). Reading or setting any of these requires a device to be connected, otherwise a RuntimeError is raised.

Property Type Description Can be set?
identity str The device's identity string (its response to idn?). No
mode int Operating mode: 0 = Continuous Trigger (every qualifying input edge fires an output pulse), 1 = Trigger Controlled by User (output pulses only fire in response to sendtrigger()). Yes — must be 0 or 1; raises ValueError otherwise.
polarity int Output pulse polarity: 0 = Negative (output idles high, pulses low), 1 = Positive (output idles low, pulses high). Yes — must be 0 or 1; raises ValueError otherwise.
delay int Delay in nanoseconds between an input trigger edge and the generated output pulse. Yes — must be a non-negative integer; raises ValueError otherwise.
triggerduration int Duration of the generated output pulse in nanoseconds. Yes — must be a positive integer; raises ValueError otherwise.
divider int Sub-sampling divider: in Continuous Trigger mode, one output pulse is emitted for every divider input edges. divider=1 passes every trigger through (no sub-sampling). Yes — must be a positive integer; raises ValueError otherwise.
number_of_triggers int Number of output pulses produced by a single sendtrigger() call. Only meaningful in mode 1. Yes — must be a positive integer; raises ValueError otherwise.

After setting a property, the driver reads the value back from the device to confirm it took effect. If the device does not acknowledge the command, or if the read-back value does not match the requested value, a RuntimeError is raised.

Other attributes

These are plain instance attributes (not @property) that are useful to inspect directly.

Attribute Type Description
connected bool True if a device is currently connected, False otherwise.
port str Serial port used for the current (or most recent) connection.
baudrate int Baud rate configured for the connection.
timeout float Read timeout (in seconds) configured for the connection.
identifier str Substring that must appear at the start of a device's identity string for it to be recognised as compatible. Default is 'Send_Trigger_Synced_With_External_Trigger'.

Methods

Method Returns Description
list_devices() list of str Scans all serial ports and returns a list of descriptor strings for compatible devices. Each string is in the form "<port>: <description> [<hwid>]". Raises RuntimeError if a device is already connected.
connect_device(port=None, baudrate=None, timeout=None) (str, int) Attempts to connect to the device on the specified serial port. If any parameter is None, the corresponding instance attribute is used. On success, queries the device for all current settings and caches them. Returns (message, 1) on success or (error, 0) on failure.
disconnect_device() (str, int) Closes the serial connection to the currently connected device. Returns (message, 1) on success or (error, 0) on failure.
check_valid_connection() None Raises RuntimeError if no device is currently connected. Called internally by all properties and sendtrigger().
query(q) str Sends the command string q to the device and returns its reply as a stripped string. Clears any stale data from the input buffer before writing.
sendtrigger() bool Sends a trg command to start a burst of output pulses. Only valid in mode 1; raises RuntimeError in mode 0. Returns True if the device acknowledged the command, False otherwise. Note: the acknowledgement confirms the burst was armed, not that it has completed — completion depends on input trigger edges arriving at the device and is reported asynchronously by the device itself (it sends "01" over serial when done).

Examples

from pyTriggerSync.driver import pyTriggerSync

device = pyTriggerSync()

# Scan for available devices
available_devices = device.list_devices()
print(available_devices)
# e.g. ['COM4: USB Serial [USB VID:PID=16C0:0483 SER=123456 LOCATION=1-1]']

# Connect to the first available device
port = available_devices[0].split(':')[0]
device.connect_device(port=port)

# Read device identity
print(device.identity)

# Set mode to "Trigger Controlled by User"
device.mode = 1

# Set output polarity to Negative (idles high, pulses low)
device.polarity = 0

# Set a 500 ns delay and a 200 ns pulse duration
device.delay = 500
device.triggerduration = 200

# Configure a burst of 5 pulses and fire
device.number_of_triggers = 5
success = device.sendtrigger()
print(f"Trigger sent: {success}")

# Switch to Continuous Trigger mode with a divider of 2
# (fires one output pulse for every 2 input edges)
device.mode = 0
device.divider = 2

# Disconnect
device.disconnect_device()

Usage as a stand-alone GUI interface

The installation sets up an entry point for the GUI. Just type

pyTriggerSync

in the command prompt to start the GUI.

Embed the GUI within another GUI

The GUI can also be easily integrated within a larger graphical interface:

import PyQt5.QtWidgets as Qt
import pyTriggerSync

app = Qt.QApplication([])
window = Qt.QWidget()

# The GUI must be contained inside a widget object
widget_containing_interface_GUI = Qt.QWidget()
widget_containing_interface_GUI.setStyleSheet(
    ".QWidget {
"
    "border: 1px solid black;
"
    "border-radius: 4px;
"
    "}"
)

# Create the interface (model) object
Interface = pyTriggerSync.interface(app=app)
Interface.verbose = False

# Signals emitted by the interface can be connected to external functions, e.g.:
#
#   Interface.sig_mode_changed.connect(my_function)
#
# my_function will be called with the new mode (0 or 1) every time the mode changes.
# Similarly, Interface.sig_external_trigger_changed, sig_polarity_changed, etc.
# can be used to react to any setting change.
#
# To fire a trigger from external code (e.g. in response to another instrument):
#
#   Interface.fire_trigger()

# Create the GUI (view + controller) and bind it to the interface
view = pyTriggerSync.gui(interface=Interface, parent=widget_containing_interface_GUI)

# Add additional GUI elements alongside the pyTriggerSync panel
gridlayoutwidget = Qt.QWidget()
gridlayout = Qt.QGridLayout()
gridlayout.addWidget(Qt.QLabel("Additional GUI 1"), 0, 0)
gridlayout.addWidget(Qt.QLabel("Additional GUI 2"), 1, 0)
gridlayoutwidget.setLayout(gridlayout)

layout = Qt.QVBoxLayout()
layout.addWidget(widget_containing_interface_GUI)
layout.addWidget(gridlayoutwidget)
layout.addStretch(1)
window.setLayout(layout)

app.aboutToQuit.connect(Interface.close)
window.show()
app.exec()

Project details


Release history Release notifications | RSS feed

This version

0.3

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pytriggersync-0.3.tar.gz (43.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pytriggersync-0.3-py3-none-any.whl (32.6 kB view details)

Uploaded Python 3

File details

Details for the file pytriggersync-0.3.tar.gz.

File metadata

  • Download URL: pytriggersync-0.3.tar.gz
  • Upload date:
  • Size: 43.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for pytriggersync-0.3.tar.gz
Algorithm Hash digest
SHA256 36859b04dd01f4396a4be9ba53e98d472c236199ec7d6e87a7d917aa2a68b828
MD5 facf2fec124d2d4064147071d7e27300
BLAKE2b-256 f764a0b748400f4f19d7146ae8acb44040cc4622c1e4837670ca2269867f509c

See more details on using hashes here.

File details

Details for the file pytriggersync-0.3-py3-none-any.whl.

File metadata

  • Download URL: pytriggersync-0.3-py3-none-any.whl
  • Upload date:
  • Size: 32.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for pytriggersync-0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 06e44c1c9e5b33149359d64281782c980eaaa42376638163f4bfda2c6140c596
MD5 c701d9e778fe26009ae5f719dc52e9fd
BLAKE2b-256 0d60a1c623dc6c838b123913f263d5a94950028618b1ad33dad1eab3f804bf6a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page