Desktop application for controlling and monitoring a microfluidic laboratory setup. Active development and routine use target the v3 GUI, which uses PySide6 and Fluent Widgets. The classic PyQt5 GUI remains in the repository only as a comparison and emergency fallback while v3 is validated on the lab setup.
The controller GUI connects to laboratory hardware over Modbus TCP and serial interfaces. It can:
- set and monitor pressure
- switch pneumatic and fluidic valves
- read analog Modbus flow sensors, optional Sensirion USB/SCC1 flow sensors, and Fluigent pressure sensors
- control an AMF rotary valve
- connect an optional Ohaus-compatible serial balance as a live measurement channel
- run EtOH flow-by-mass calibration workflows
- display live plots for pressure, flow, valves, Fluigent sensors, and rotary valve activity
- export measurements to CSV
- execute JSON-defined automation programs from the integrated program editor
The current runtime starts through main_gui_v3.py and uses the ui_v3/
package. New GUI work should target v3 only; shared runtime changes should stay
compatible with v3 and should not add new orchestration to the legacy window.
start_v3.bat: recommended one-click launcher for normal lab use.main_gui_v3.py: starts the PySide6/Fluent v3 controller GUI for development runs.main_gui.py: legacy PyQt5 controller GUI, retained only for comparison and emergency fallback.editor/editor_main.py: legacy standalone editor; v3 normally opens the native editor from the controller.
modules/: shared runtime package for hardware coordination, sampling, export, calibration core, and program execution.modules/pressure/: pressure-controller adapter and shared pressure-profile math used by the editor and program runner.modules/valves/: Modbus valve adapter plus AMF rotary-valve controller, widget, and low-level serial protocol.modules/sensors/: sensor and measurement adapters, including Modbus flow, Sensirion USB/SCC1, Fluigent pressure sensors, and the Ohaus-compatible balance.ui_v3/: parallel PySide6/Fluent interface with navigation, control cards, Qt6 plot panel, plotting helpers, controller facades, calibration page, and a JSON-compatible editor shell.editor/: legacy PyQt5 editor package retained for standalone fallback and JSON-contract reference.lookup/: tracked hardware profiles plus ignored local preference data.icons/,icons/source/, andeditor/icons/: GUI icon assets and editable icon source images.packaging/pyinstaller/: optional PyInstaller build script and spec files.Measurements/: runtime CSV output folder, ignored by Git.tools/: optional hardware diagnostics and development utilities.old/: ignored local archive for historical files that are no longer active.ARCHITECTURE.md: current module and program-contract documentation.TESTING.md: manual validation checklist for the lab setup.CURRENT_STATE.md: concise handoff note for resuming development in a new thread or on a new workstation.docs/hydrogel_potentiometer_measurement.md: hydrogel potentiometer measurement workflow, chip/pore metadata, medium correction, CSV export, analysis, and plot behavior.
- v3 GUI work should stay under
ui_v3/and useV3RuntimeControllerplus the focused helpers inui_v3/controllers/*_runtime.pyinstead of adding new orchestration to legacy GUI files. ui_v3/controllers/*_runtime.pycontains small v3 helper facades for pressure, sensor detection/session sizing, balance, export, program worker-thread orchestration, and rotary program access. These helpers keep public GUI methods stable while making future modules easier to add.modules/measurement_session.pyowns live measurement buffers, generic extra measurement series, and CSV export snapshots.modules/device_catalog.pyis the preferred place to publish editor-visible runtime devices, display names, units, and profile-derived valve metadata when new hardware modules are added; existing pressure, flow, Fluigent, valve, and rotary devices use the same descriptor pattern.modules/sensors/flow_sensor_config.py,modules/sensors/sensirion_usb.py, andmodules/sensors/sensirion_scc1_dll.pycontain the optional Sensirion USB/SCC1 flow-sensor layer. Runtime labels, Modbus assignments, and enable/disable state are local lookup JSON files and are intentionally ignored by Git.modules/sensors/balance.pycontains the Ohaus-compatible serial balance adapter and PuTTY/Ohaus log parsing helpers. In v3 it is exposed as a genericBalance [g]measurement channel so CSV export can include mass data.modules/medium_calibration_core/contains GUI-independent EtOH flow-by-mass calibration logic. The v3 PySide6 page inui_v3/calibration_tab.pyuses this core without importing PyQt5 widgets.- Sensor calibration supports two explicit references: balance/gravimetric for absolute calibration and trusted flow sensor for transfer calibration. Saved JSON stores the active
calibration_reference_mode; gravimetric fields remain diagnostic data when a trusted reference sensor is used. lookup/stand1.jsondefines the full stand 1 valve setup: 12 pneumatic valves and 4 fluidic valves. The measured Modbus coil order is Valve 1-4 -> coils 0-3, Valve 5-8 -> coils 12-15, and Valve 9-12 -> coils 8-11.lookup/extended_pneumatic_setup.jsonis kept as a hidden compatibility profile.- The main GUI
Update Configbutton refreshes detected sensors and editor device lists when no measurement or program is active. modules/program_contract.pydefines the shared editor/runner step names and parameter keys.modules/program_runner.pyexecutes editor-generated JSON steps through narrow runtime methods exposed by the GUI.modules/pressure/polynomial.pycontains shared helpers for polynomial and sine pressure profiles, including clamp, slew limiting, and optional feedback correction. The editor uses these helpers for previews and parameter descriptions; the program runner uses the same helpers at runtime.- Editor task metadata is currently shared through
editor/modules/editor/task_globals.py. - Hardware-facing behavior should be changed conservatively and verified on real equipment.
For normal lab use, double-click:
start_v3.batThe launcher creates or repairs a local v3 Python environment under
%LOCALAPPDATA%\MicrofluidicSystemController by default. This keeps large Qt
packages and DLLs off the network repository path and avoids Spyder or any
currently active shell environment.
Typical classic dependencies are listed in requirements.txt; v3 dependencies
are listed in requirements-v3.txt.
For a development start from an already prepared v3 environment:
py -3 main_gui_v3.pyThe legacy GUI can still be started for comparison or emergency fallback:
py -3 main_gui.pyFor explicit setup and import checks:
setup_v3_env.bat
start_v3.batSet MF_CONTROLLER_ENV_ROOT before running the installer if another local
environment location is preferred.
On a lab computer, the repository can stay on the network drive. Only the
Python environments are created locally per Windows user in %LOCALAPPDATA%.
start_v3.bat now creates the local v3 environment automatically if it is
missing, runs a quick import check, and keeps the console open after exit so
startup errors remain visible.
start_v3.bat wraps the v3 starter in a visible console window, handles
UNC/network-drive startup, and keeps startup errors readable.
Launcher guide:
start_v3.bat: recommended v3 lab launcher that keeps the console open after errors.setup_v3_env.bat: explicit local v3 environment setup.install_all_packages.bat: package installer/repair for classic and v3 environments.tools\Test_Flow_Sensors_v3.bat: optional Sensirion USB/SCC1 flow-sensor detection and readout diagnostic.tools\Test_Balance_v3.bat: optional Ohaus-compatible serial-balance detection diagnostic.tools\analyze_hydrogel_potentiometer.py: post-processes hydrogel potentiometer EtOH ramp CSV exports into plateau summaries and plots.
If the local v3 environment exists but is incomplete, for example because
qfluentwidgets is missing after an interrupted first install, the launcher now
tries one automatic package repair before reporting the error.
If the lab computer does not provide the Windows py launcher, the installer
also looks for python.exe in common Python, Anaconda, and Spyder locations.
Set MF_PYTHON_EXE to a specific python.exe before launching if the automatic
search does not find the right interpreter.
Optional Sensirion USB/SCC1 flow-sensor support is installed with the v3 requirements. If the Windows SCC1 DLLs are missing, run:
tools\Test_Flow_Sensors_v3.bat --install-dll --probe-dllThe v3 Flow Sensors page can refresh detected serial sensors, assign labels
for plot/CSV output, and disable the default Modbus flow channels when only
serial sensors are connected. These settings are local to the measurement PC.
Serial Sensirion sensors are currently read in their H2O measurement mode; IPA
or other media should be handled through the medium-calibration workflow instead
of silently changing the sensor mode during normal water-based calibration.
CSV exports include per-flow-sensor metadata rows with serial number, medium
tag, loaded calibration file, calibration coefficients, and trusted-reference
state when available. If the optional live medium correction is enabled on the
Flow Sensors page, the CSV metadata also records the selected EtOH percentage,
applied correction parameters, calibration range, source files, and any
correction error.
The correction chain is intentionally layered: first apply the sensor-specific
water calibration for the physical Sensirion serial number, then apply the
optional EtOH/medium correction from calibration_EtOH/ through
FlowCorrector when the live medium-correction switch is explicitly enabled.
This keeps sensor health/calibration separate from fluid-medium effects and
makes both steps traceable in saved JSON and CSV metadata. With the switch off,
live values stay at the sensor-calibrated water-correction stage.
The program editor can generate a reproducible concentration-ramp program for
the hydrogel sphincter potentiometer experiment. In the editor job list, use
Hydrogel EtOH Ramp... and configure:
- rotary port map, for example
1=10, 2=12, 3=15, 4=17, 5=18, 6=20, 7=25 - ramp-up and ramp-down concentration sequences
- stability sensors, normally the upper outlet and diverted outlet flows
(
Flow 2, Flow 3unless the current setup uses different labels) - purge/exchange wait time, stability window, plateau hold time, sampling interval, feed-enable valve, bottom-feed valve, and export prefix
The generated program separates transient medium exchange from confirmed steady-state plateaus:
Set Feed Mediummoves the rotary valve to the target EtOH port, marks the sample stream astransition, and disables the previous live medium correction so the mixed exchange phase is not interpreted as a confirmed concentration.- The program waits for the configured purge/exchange time.
Wait for Multi Sensor Stabilityrequires all configured outlet-flow sensors to satisfy the stable-plateau detector.Mark Plateauconfirms the reached EtOH concentration, marks the sample stream asplateau, and enables the EtOH medium correction for that confirmed concentration.- The plateau is held for the configured duration before the next feed medium.
Measurement CSV exports include program context columns for this workflow:
Feed target EtOH, Feed confirmed EtOH, Medium state, Plateau ID,
Ramp direction, and Medium correction active. These columns allow later
analysis to exclude transition and stabilization periods while preserving the
full time trace for audit and troubleshooting.
After a run, analyze the final CSV with:
.\.venv-v3\Scripts\python.exe .\tools\analyze_hydrogel_potentiometer.py .\Measurements\YOUR_FILE.csvThe analysis writes a plateau summary CSV plus phi_3 versus EtOH and time
series plots. phi_3 = Flow 3 / (Flow 2 + Flow 3) and Q_total = Flow 2 + Flow 3 are calculated from the medium-corrected outlet-flow columns, and only
rows with Medium state = plateau and active medium correction are included in
the plateau summary.
Fluigent channels in this controller are pressure sensors only. Their readings are not switched between H2O and IPA. Fluigent SDK medium calibration tables apply to Fluigent Flow Units, which are not part of the current hardware setup.
For a quick Ohaus-compatible balance check, use:
tools\Test_Balance_v3.bat --port COM5 --timeout 5To install both the classic PyQt5 environment and the v3 PySide6 environment, use:
install_all_packages.batIf a previous v3 install produced Qt DLL import errors, rebuild only the v3 environment:
install_all_packages.bat --v3-only --resetStart the legacy standalone editor:
py -3 editor/editor_main.pyThe repository includes PyInstaller specs for the controller and standalone editor:
packaging\pyinstaller\build_all_exe.batThe build script expects the mf_controller_build conda environment and uses:
packaging/pyinstaller/uF_Controller_2_2.specpackaging/pyinstaller/uF_Editor_2_2.spec
Generated build/ and dist/ folders are ignored by Git.
Before using a changed version on the lab setup, run through the manual checks in TESTING.md.
The v3 window includes a visible SAFE STOP button in the status strip. It can
also be triggered with Ctrl+Esc or F12. Safe Stop requests program stop,
measurement stop, all valves closed, and raw pressure output set to 0 mbar.
This is a software safety helper, not a replacement for a physical emergency
stop or power-off option. Plain Esc is intentionally not used because an
accidental key press could interrupt a running lab workflow.
This project is maintained in a private GitHub repository:
https://github.com/StefanG87/Microfluidic-System-Controller
Recommended workflow:
- Commit source, profiles, icons, and documentation.
- Keep build outputs, runtime measurements, caches, and local preference files out of Git.
- Use small commits for hardware-related changes.
- Tag software versions used for important experiments or publications.
- Document any behavior-changing hardware update in
ARCHITECTURE.mdorTESTING.md.
For a quick handoff or a new development session, read CURRENT_STATE.md first.
- Keep editor parameters and runtime behavior aligned through
program_contract.py. - Register new sensors and actuators through
DeviceCatalogdescriptor helpers before wiring them into v3 cards, editor tasks, plotting, or CSV export. - Keep device display names and measurement units in
DeviceCatalogconstants/helpers instead of duplicating strings across GUI and editor modules. - For future time-series devices, follow the balance pattern: register a named extra series in
MeasurementSessionthroughRuntimeDeviceRegistryso the CSV exporter can add one stable column per device signal. - Keep advanced pressure-profile behavior documented when
PolynomialPressurechanges. - Reduce broad
try/exceptblocks where clearer logging can preserve stability without hiding root causes. - Further separate v3 GUI orchestration from hardware and automation helpers only in small, low-risk steps.
- Revisit package/resource bootstrapping if PyInstaller packaging becomes part of the regular workflow again.