From 6dbf8784fff22a322384d669c90b74965f238088 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 23 Oct 2026 12:55:32 +0000 Subject: [PATCH] docs(flomni): realtime_system in the user guide; FZP how-tos with the loop-settings profiles - user guide: detector-trigger commands under flomni.realtime_system.trigger_* (old names still work), new section "Real-time loop settings (expert)" - calibration how-to: steps 1-3 as profiles fzp_off / fzp_calibration / production (+ fast_scan); trigger values are OnTargetTrigger parameters; move-beyond sizing with the loop-settings rule (0.6 x stroke - Abbe limit) - range how-to: FZP range through the loop settings (Ub / Lb and Feedforward limits together) Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019aWcwG89wi7oVyrefukXX6 --- ...ct_only-howto_calibrate_the_fzp_scanner.md | 27 ++++++++++++-- ..._only-howto_limit_the_fzp_scanner_range.md | 7 +++- docs/user/ptychography/flomni.md | 36 +++++++++++++++---- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_calibrate_the_fzp_scanner.md b/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_calibrate_the_fzp_scanner.md index 3d29d0b5..e0214cbd 100644 --- a/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_calibrate_the_fzp_scanner.md +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_calibrate_the_fzp_scanner.md @@ -102,8 +102,9 @@ correction (−4 before 2026-10-19, now 0: replaced by the feedforward). - FZP range: `PID_x_fzp` / `PID_y_fzp` `Ub` / `Lb` are ±1.5 V in operation (the cap sensors are calibrated over about ±2 V only). For the field of view above (2.8 × 1.8 µm) widen them, e.g. to ±10 V (FZP ≈ 0.13 µm/V in x, ≈ 0.05 µm/V in y). The feedforward stays off (`enable` 0,0) during this scan. -- The detector trigger (`OnTargetTrigger`) checks the relative error sample vs FZP (tolerance / hold time from the - ConstEmitter, BEC `interferometer_trigger_*`, default 10 nm / 3 ms) and waits `MinDelay_ms` (15 ms). +- The detector trigger (`OnTargetTrigger`) checks the relative error sample vs FZP (parameters + `ontarget_tolerance_um` / `ontarget_hold_ms`, BEC `flomni.realtime_system.trigger_*`, default 10 nm / 3 ms; until + 2026-10-23 ConstEmitter lines) and waits `MinDelay_ms` (15 ms). **Step 3, default operating values (replace the values in the text above):** @@ -133,6 +134,24 @@ over a wider range the FZP can take the small steps alone (flOMNI `feedback_repo Measured with 101 ms exposures: 0.2–1 µm steps trigger after 4.5–5.8 ms instead of 17–32 ms; the error during the exposure grows with the step (1 µm: ≈ 6 nm max instead of 2.5 nm), so the setting depends on the experiment. +## With the loop settings (since 2026-10-23) + +The steps above are profiles of the loop settings (web HMI tab *Loop settings*, BEC `flomni.realtime_system`; +flOMNI `FeedbackLoop/loopsettings/`). The rules keep the modules consistent, so the individual parameters above do +not have to be set by hand: + +| Step | Profile | BEC | +|---|---|---| +| 1, FZP disabled (alignment, affine matrix) | `fzp_off` | `flomni.realtime_system.apply_profile("fzp_off")` | +| 2, FZP-only calibration scan (clear `MatrixCorr` first: not part of the settings) | `fzp_calibration` | `apply_profile("fzp_calibration")` | +| 3, back to operation | `production` | `apply_profile("production")` | +| afterwards, faster scans (calibrated over ±7 V) | `fast_scan` | `apply_profile("fast_scan")` | + +Single values: `flomni.realtime_system.set(fzp_range_V_x=7, fzp_range_V_y=7)`, +`set(move_beyond_um_x=0.3)`, `set(exposure_during_motion=1)`; refused with the reason if a rule objects +(`adjust=True` changes the dependent settings too). FZP settings only between scans. Live only until +`save_as_default()`. + ## Move-beyond (`PID_x` / `PID_y` `FAST_FZP_PID_LOOP(0)` < 0), 2026-10-23 **What it does** (`PID.cpp`, unchanged since the original loop). Only in point-by-point scans (scan state 2). The @@ -153,7 +172,9 @@ target) and `AbbeCorrection` (Chan corrected for the stage tilt, see below). The target and Chan, so it supplies the +m offset of the FZP directly (static term m / K). **Sizing.** During the exposure the FZP has to hold m + Abbe correction + noise / settling inside its stroke: -|m| ≤ R − reserve, as a rule ≈ R / 2. R per axis = `Ub` × K (K ≈ 0.13 µm/V x, ≈ 0.05 µm/V y): +|m| ≤ R − reserve, as a rule ≈ R / 2. R per axis = `Ub` × K (K ≈ 0.13 µm/V x, ≈ 0.05 µm/V y). The loop settings +refuse more than 0.6 × R minus the Abbe limit (rule `move_beyond_*_fits`, constant `move_beyond_fraction`; the +tested ±7 V values are 0.56 × R): | FZP `Ub`/`Lb` | R x / y | move-beyond x / y (≈ R/2) | |---|---|---| diff --git a/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_limit_the_fzp_scanner_range.md b/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_limit_the_fzp_scanner_range.md index 89755f1e..488462ee 100644 --- a/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_limit_the_fzp_scanner_range.md +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_limit_the_fzp_scanner_range.md @@ -33,9 +33,14 @@ Changing the FZP range now involves, in addition to the text above: small range. `use_final` 1 + `WaitForSlew` 0 ("exposure during the motion") only makes sense when the FZP range covers the scan step; steps larger than the range then still wait for the sample stage. - Move-beyond (0) must fit into the stroke: the FZP holds it during the exposure, together with the Abbe correction - (up to `correction_limit_um` 0.1 µm when enabled) and noise. Rule ≈ half the stroke: at ±1.5 V ≈ −0.1 µm (x), + (up to `correction_limit_um` 0.1 µm when enabled) and noise. Rule ≈ half the stroke (the loop settings refuse more than 0.6 × stroke minus the Abbe limit): at ±1.5 V ≈ −0.1 µm (x), ≈ −0.04 µm (y); at ±7 V −0.5 / −0.2 µm (tested). Production: 0. Details: calibration how-to, section "Move-beyond". - (5) compares the real FZP drive incl. the feedforward (input 8 of `PID_x` / `PID_y` = `Feedforward` output since 2026-10-23; before it was the FZP PID output without the feedforward). - After a change: web HMI tab **Loop check** level 1 (expected settings) and, with the beamline ready, the scan test (level 4: positioning time, stability during the exposure per step size). + +**With the loop settings (since 2026-10-23):** `flomni.realtime_system.set(fzp_range_V_x=..., fzp_range_V_y=...)` +(web HMI tab *Loop settings*) sets `PID_*_fzp` `Ub` / `Lb` and the `Feedforward` limits together; a move-beyond that +no longer fits is refused, or clamped with `adjust=True` (rule `move_beyond_*_fits`). `FreqGen` limits stay +manual (measurements only). diff --git a/docs/user/ptychography/flomni.md b/docs/user/ptychography/flomni.md index 8031e5d2..2a28802f 100644 --- a/docs/user/ptychography/flomni.md +++ b/docs/user/ptychography/flomni.md @@ -224,18 +224,19 @@ In step scans the detector is triggered when the sample is stable at the scan po sample vs FZP (interferometer minus FZP cap sensor) must stay within a tolerance in x and in y (each averaged over 0.5 ms) for a hold time. Both values are live and can be changed between scans: -- `flomni.interferometer_trigger_show()` — current tolerance and hold time -- `flomni.interferometer_trigger_set_tolerance_nm(10)` — tolerance per axis in nm: about 30 for a fast +- `flomni.realtime_system.trigger_show()` — current tolerance, hold time, minimum delay, trigger after a move +- `flomni.realtime_system.trigger_set_tolerance_nm(10)` — tolerance per axis in nm: about 30 for a fast low-resolution scan, 10 standard, 2 for the highest resolution (a few ms more per point); 0 selects the former criterion (on-target flags of the FZP loops) -- `flomni.interferometer_trigger_set_hold_ms(3)` — hold time in ms -- `flomni.interferometer_trigger_set_after_move(True)` — additionally one trigger after every position change +- `flomni.realtime_system.trigger_set_hold_ms(3)` — hold time in ms +- `flomni.realtime_system.trigger_set_after_move(True)` — additionally one trigger after every position change of the sample stage (e.g. `umv(dev.rtx, ...)`), as soon as the position is stable with the same tolerance and hold time; `False` (default): triggers at scan points only - `dev.rtx.controller.move_xyz(x, y, z)` — moves rtx, rty and rtz with one command (one trigger for the move) -- `flomni.interferometer_trigger_help()` — this list -After a restart of the control loop the start values (10 nm, 3 ms) apply again. Measured with 3 µm steps +The former names `flomni.interferometer_trigger_*` still work (they print the new name). The values are live; after +a restart of the control loop the values of the loop's parameter files (10 nm, 3 ms) apply again, unless they were +saved with `flomni.realtime_system.save_as_default()`. Measured with 3 µm steps (2026-10-20): the trigger comes about 36 ms (x) / 48 ms (y) after the step at 10 nm, 40 / 55 ms at 2 nm; after the trigger the position stays within about 4 nm even at a 30 nm tolerance. @@ -781,10 +782,31 @@ removed later. [See short version](flomni.md#sample-storage-and-transfer) +### Real-time loop settings (expert): `flomni.realtime_system` + +The operating settings of the real-time loop — FZP scanner on/off, FZP range, feedforward, move-beyond, exposure +during the motion, Abbe correction, detector trigger, laser tracker targets and thresholds — with the rules between +them. The rules and the mapping onto the loop parameters are kept on the loop machine (web HMI tab *Loop settings*, +`http://mpc2844:8080/?tab=settings`; definition in the flOMNI control repository, +`FeedbackLoop/loopsettings/flomni.json` and `README.md`); BEC and the web page use the same rules. + +- `flomni.realtime_system.show()` — all settings with live and saved value, violated rules, scan state + (`show(expert=True)` also the FZP calibration group) +- `flomni.realtime_system.set(name=value, ...)` — change; refused (with the reason) if a rule objects, e.g. the + feedforward must be off while the FZP loop is off; `set(..., adjust=True)` changes the dependent settings too +- `flomni.realtime_system.check(name=value)` — dry run +- `flomni.realtime_system.profiles()`, `apply_profile("production" | "fzp_off" | "fzp_calibration" | "fast_scan")` +- `flomni.realtime_system.unsaved()`, `save_as_default()` — the changes are live only until the next start of the + control loop; `save_as_default()` writes them into the loop's parameter files +- `flomni.realtime_system.help()` + +FZP settings can only be changed between scans. BEC needs the API token of the web HMI in `~/.flomni_webhmi_token` +(local contact; flOMNI `FeedbackLoop/loopsettings/README.md`). + ### Detector trigger and interferometer tuning The trigger tolerance and hold time: [Detector trigger: position stability](#detector-trigger-position-stability) -(`flomni.interferometer_trigger_*`). The control loops of the sample stage, the FZP scanner and the laser +(`flomni.realtime_system.trigger_*`). The control loops of the sample stage, the FZP scanner and the laser tracker were characterized and retuned in October 2026; results, the present parameters and how to retune them are documented in the flOMNI control repository (`FeedbackLoop/feedback_report.md` with PDF, `FeedbackLoop/tuning_guide.md`).