From ea9f8cdf01eadd17c20940d7636d2fc8f0e0b5b2 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 23 Oct 2026 10:34:48 +0000 Subject: [PATCH] docs(flomni): FZP how-tos as Markdown, updated for the PREEMPT_RT loop, move-ahead renamed to move-beyond Markdown versions of local_contact_only-howto_calibrate_the_fzp_scanner.pdf and local_contact_only-howto_limit_the_fzp_scanner_range.pdf (original text kept, update sections for the present flOMNI loop). New section "Move-beyond" (FAST_FZP_PID_LOOP(0) < 0 of the sample PIDs): mechanism, sizing (about half the FZP stroke), Abbe correction on the FZP side, hold (5) now reads the FZP drive incl. feedforward (flomni repo, branch fzp-move-beyond, 6a15f68). The PDFs are kept. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_019aWcwG89wi7oVyrefukXX6 --- ...ct_only-howto_calibrate_the_fzp_scanner.md | 183 ++++++++++++++++++ ..._only-howto_limit_the_fzp_scanner_range.md | 41 ++++ 2 files changed, 224 insertions(+) create mode 100644 csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_calibrate_the_fzp_scanner.md create mode 100644 csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_limit_the_fzp_scanner_range.md 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 new file mode 100644 index 00000000..3d29d0b5 --- /dev/null +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_calibrate_the_fzp_scanner.md @@ -0,0 +1,183 @@ +# How to calibrate the FZP scanner of flOMNI + +Source of `local_contact_only-howto_calibrate_the_fzp_scanner.pdf`. The original text is kept unchanged; the +section "Update 2026-10-20" at the end lists what the present flOMNI loop (PREEMPT_RT, 100 µs, branch `rt_preemt`) +needs in addition (corrected 2026-10-23: "move-ahead" → **move-beyond**, see the section at the end). + +```text +This is a description of how to calibrate the FZP scanner of flOMNI + +Rmemeber to do all modifications for both directions x and y! + +1. Align flOMNI without the FZP scanner. This implies disabling the +FZP scanner completely. To do so, in OrchestraHMI edit the parameters +of the FZP scanner as follows. +(a) Module PID_i_FZP: Set Param FAST_FZP_PID_LOOP(0) to 2. Then the FZP +will just remain +statically centered to the capacitive sensor position in closed loop. +(b) Module PID_i: Set Param FAST_FZP_PID_LOOP(0) to 0. If this is +negative, the FZP scanner will move ahead in a point-by-point scan by +that amount. +(c) Module PID_i: Set Param FAST_FZP_PID_LOOP(5) to 0. If this is +larger than zero the sample stage motion is stopped if the position is +reached by the FZP scanner (which is the case when the scanner is not +active). Zero means thus full compensation by the sample stage. + +In this state the setup can be aligned, and the affine matrix for +ptychography can be found. This refers then purely to the alignment of +the interferometer and X-ray detector. + +2. In the next step we perform a scan (with a small beam and small +range) such that only the FZP scanner is used and the sample stage +will not move. + +Before we start ensure that the Correction Matrix for the capacitive +sensors is cleared. + +To do this change the parameters of the flOMNI control +loop as follows: + +(a) Module AnalogInput_6259: Set parameter MatrixCorr to 1 0 0 1 +(b) Module PID_j_fzp: Set Param FAST_FZP_PID_LOOP(0) to 1 to re-activate +the FZP scanner. +(c) Module PID_i: Set Param FAST_FZP_PID_LOOP(5) to 10, so up to 10 +volts output of the fast PID is accepted before starting a movement of +the sample stage. +(d) Module PID_i: Param FAST_FZP_PID_LOOP(4) 0 +(e) Module PID_i: Param FAST_FZP_PID_LOOP(6) 1 + with d and e it will now stabilize the sample stage position at zero +(f) Module PID_i: Param FAST_FZP_PID_LOOP(0) remains 0 (no move ahead +in a scan) + +With these settings perform a scan. Use a field of view matching the +range of the FZP scanner. Watch the sample stage position in Orchestra +to ensure it does not change! +A good range should be 2.8 microns in x and 1.8 microns in y. +Reconstruct this scan with Michal's position refinement code and ask +for an update of the FZP matrix. This can then be put into the +AnalogInput_6259 module. +I guess one has to have the matrix found for the interferometer in the +reconsturction code, such that the new matrix of the FZP scanner will +adjust the coordinate system of the FZP scanner to the system of the +interferometer. Later these positions are used together and should +match in direction. + +3. Back to default operating values: +(a) Module PID_i: Set Param FAST_FZP_PID_LOOP(0) to -0.5, for up to +0.5 microns move ahead in a scan. +All other parameters are already as supposed to be. +Default values for the sample stage pid, fast FZP parameter are "- +0.5,0,0,0,0.1,0.5,0" +Default values for the fzp pid, fast FZP parameter are "1,0.0001,0.1,- +4,0,0,0" +``` + +Naming: "move ahead" in the text above (sample PIDs `FAST_FZP_PID_LOOP(0)` < 0) is called **move-beyond** from +2026-10-23 on: the sample stage moves *beyond* the scan point towards the next one, the FZP compensates and so sits +beyond its centre during the exposure, on the side that gives it more stroke for the next step. It is not a +"pre-move" of the FZP to the next point (that is `TargetSelect` `use_final` 1, see below). + +## Update 2026-10-20 (flOMNI loop on PREEMPT_RT, mpc2844) + +The loop has new modules since the text above was written (flOMNI `FeedbackLoop/tuning_guide.md`, +`feedback_report.md` 5.6, 6n, 6o, 6q). Parameters are changed in the web HMI (`http://mpc2844:8080`, tab +Parameters) instead of OrchestraHMI. `i` = x or y, as above. Module names now: `PID_x`, `PID_y` (sample stage), +`PID_x_fzp`, `PID_y_fzp` (FZP scanner), `AnalogInput_6289` (was `AnalogInput_6259`). + +**FAST_FZP_PID_LOOP has 7 elements** (`PID.cpp`). Sample stage PIDs: (0) move-beyond (negative, µm, point-by-point +scans only; section "Move-beyond" below), (4) FZP error threshold (µm) and (5) FZP drive limit (V) for holding the sample stage while the FZP +takes the step (5 = 0: never held), (6) 1 = hold the sample stage at 0. FZP PIDs: (0) mode (1 operation, 2 FZP +centred on its cap sensor = disabled, 3 not commissioned, 4 debug), (1)–(3) min / max / gain of the old velocity +correction (−4 before 2026-10-19, now 0: replaced by the feedforward). + +**In addition to step 1 (FZP disabled):** + +- `Feedforward`: `enable` 0,0 — the static FZP feedforward adds its drive also in FZP mode 2. +- `AbbeCorrection`: `enable` 0 (default until the signs are known). +- `TargetSelect_x`, `TargetSelect_y`: `use_final` 0; `OnTargetTrigger`: `WaitForSlew` 1 (defaults). +- `FreqGen`: `enable` 0 (excitation for measurements; default). + +**In addition to step 2 (FZP-only calibration scan):** + +- 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). + +**Step 3, default operating values (replace the values in the text above):** + +| Module | Parameter | Value | +|---|---|---| +| `PID_x`, `PID_y` | `FAST_FZP_PID_LOOP` | `0,0,0,0,0.1,0,0` (no move-beyond: −0.5 µm is larger than the ±1.5 V FZP stroke, x ≈ ±0.19 µm, y ≈ ±0.08 µm) | +| `PID_x_fzp` | `FAST_FZP_PID_LOOP`, `Ub` / `Lb` | `1,0.0001,0.1,0,0,0,0`, ±1.5 V | +| `PID_y_fzp` | `FAST_FZP_PID_LOOP`, `Ub` / `Lb` | `1,0.0005,0.02,0,0,0,0`, ±1.5 V | +| `Feedforward` | `enable`; `ff_limit`, `out_min` / `out_max` | 1,1; ±1.5 V (as the FZP `Ub` / `Lb`) | +| `OnTargetTrigger` | `WaitForSlew`, `MinDelay_ms` | 1, 15 | +| `TargetSelect_x`, `TargetSelect_y` | `use_final` | 0 | +| `AbbeCorrection` | `enable` | 0 (until the signs are known) | +| `AnalogInput_6289` | `MatrixCorr` | the new matrix from the calibration | + +Check afterwards: web HMI tab **Loop check**, level 1 (it expects these values and lists live values that differ +from the `.xmp` files); save the new values as default (Parameters → Unsaved changes) or in the `.xmp`. + +**After the calibration (per experiment): faster scans, exposure during the motion.** With the FZP calibrated +over a wider range the FZP can take the small steps alone (flOMNI `feedback_report.md` 6q, tested at ±7 V): + +- `PID_x_fzp` / `PID_y_fzp` `Ub` / `Lb` and the `Feedforward` limits to the calibrated range (e.g. ±7 V); +- `TargetSelect_x` / `_y` `use_final` 1 (the FZP aims at the new point at once, the sample stage follows its + S-curve) and `OnTargetTrigger` `WaitForSlew` 0 (trigger on the relative error only); optionally `MinDelay_ms` 0; +- optionally move-beyond, sized to the FZP stroke (≈ half of it, see below): at ±7 V (x ≈ ±0.9 µm, y ≈ ±0.36 µm) + `PID_x` (0) e.g. −0.5, `PID_y` (0) e.g. −0.2 (the values tested in `feedback_report.md` 6q). + +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. + +## 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 +TrajectoryGenerator gives the next scan point (outputs 5 / 6, PID input 9). The sample PID then aims not at the +target T but at T + m · sign(next − T), m = min(|FAST_FZP_PID_LOOP(0)|, |next − T|): the sample stage moves *beyond* +the point towards the next one, by at most the step. The FZP loop keeps its own target T (it does not see m), so the +FZP compensates the offset: during the exposure it holds the relative position at T while sitting at +m off its +centre. At the next point the FZP then has stroke R + m in the step direction instead of R (R = stroke from the centre), +so larger steps are taken by the FZP alone. Steps smaller than |FAST_FZP_PID_LOOP(0)|: the sample stage is one point +ahead, the FZP moves between 0 and +step only. The offset is not shaped (InputSlew acts on T only); the sample stage +moves to it with its own (slow) loop, i.e. partly during the exposure, and the FZP compensates that motion. + +**Is it still the same in the new loop?** Yes. The relative position is computed as before: +FZP error = Cap − (Chan − target) (mode 1), `Position sample vs FZP` = Chan − Cap (PID output 3, RT_sampler). The +sample PIDs still get the shaped target (InputSlew) + move-beyond and the raw interferometer. The FZP side now has +two additions that act on the FZP side only: `TargetSelect` (`use_final` 0 = shaped target as before, 1 = final +target) and `AbbeCorrection` (Chan corrected for the stage tilt, see below). The `Feedforward` uses the same FZP +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): + +| FZP `Ub`/`Lb` | R x / y | move-beyond x / y (≈ R/2) | +|---|---|---| +| ±1.5 V (production) | ±0.19 / ±0.08 µm | ≈ −0.1 / ≈ −0.04 µm (production: 0) | +| ±7 V (after calibration) | ±0.9 / ±0.36 µm | −0.5 / −0.2 µm (tested, 6q) | + +The original default −0.5 µm in both axes dates from the ±9 V limits of the old loop (x ≈ ±1.2 µm, about R/2; in y +±9 V ≈ ±0.45 µm, i.e. about the full stroke). When the FZP saturates while holding the offset, the relative error grows and the trigger +waits. + +**Abbe correction.** `AbbeCorrection` adds a new term to the measured sample x / y on the FZP side only: +x = Chan2_x + θz · offset_y_for_x, y = Chan1_y + θz · offset_x_for_y (θz = Chan3 / 13 mm). So yes: it is an error of +the sample x / y position (stage tilt about z, not seen by the x / y interferometer beams) that is corrected by the +FZP x / y, not by the sample stage (`PID_x` / `PID_y` keep the raw Chan, the rotZ piezo is too slow). The positions +recorded for the reconstruction (`Position sample vs FZP`) contain it as well. It uses FZP stroke (limited to +`correction_limit_um` 0.1 µm per axis; y at rest ≈ 2 nm, ≈ 30–37 nm during 20 µm x steps) — keep this in the reserve +of the move-beyond, in y it is a large part of the ±0.08 µm stroke. Keep it off (`enable` 0) during the FZP +calibration scan (step 2). + +**Notes.** +- Hold of the sample stage, (4) / (5): input 8 of `PID_x` / `PID_y` was the FZP PID output *before* the + `Feedforward` (with the feedforward on only the remainder, not the real FZP drive). Since 2026-10-23 it is the + `Feedforward` output (FZP drive incl. feedforward), so (5) again compares the real FZP drive. No change with the + feedforward off or with (5) = 0 (production). +- On the last point of a scan the next point output is 0, so the move-beyond points towards 0 (as in the old loop). +- `TargetSelect` `use_final` 1 is a different thing: the FZP aims at the new point at once while the sample stage + follows the S-curve. Both can be combined (6q, E0). 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 new file mode 100644 index 00000000..89755f1e --- /dev/null +++ b/csaxs_bec/bec_ipython_client/plugins/flomni/docs/local_contact_only-howto_limit_the_fzp_scanner_range.md @@ -0,0 +1,41 @@ +# How to limit the FZP scanner range of flOMNI + +Source of `local_contact_only-howto_limit_the_fzp_scanner_range.pdf`. The original text is kept unchanged; the +section "Update 2026-10-20" lists what the present flOMNI loop (PREEMPT_RT, 100 µs, branch `rt_preemt`) needs in +addition. "ahead movement" (element 0) is called **move-beyond** from 2026-10-23 on: the sample stage moves beyond the +scan point towards the next one, the FZP compensates and sits off-centre, which gives it stroke for the next step. + +```text +to limit the fzp scanner ranges +in PID_ FAST FZP PID LOOP +0: reduce to small ahead movement range, such as -0.05 +4: reduce error threshold, eg 0.01 +5: inform PID that FZP range is small, such as 0.1 + +in PID_ _FZP +limit the analog output LB and UB +``` + +## Update 2026-10-20 (flOMNI loop on PREEMPT_RT, mpc2844) + +The limited range is the present operating state: `PID_x_fzp` / `PID_y_fzp` `Ub` / `Lb` = ±1.5 V because the cap +sensors are calibrated over about ±2 V only (flOMNI `feedback_report.md` 6n). FZP ≈ 0.13 µm/V in x, ≈ 0.05 µm/V in y, +so ±1.5 V ≈ ±0.19 µm (x) / ±0.08 µm (y). In the sample stage PIDs (`PID_x`, `PID_y`) `FAST_FZP_PID_LOOP` is +`0,0,0,0,0.1,0,0`: no move-beyond, (5) = 0 (the sample stage always compensates fully). + +Changing the FZP range now involves, in addition to the text above: + +- **`Feedforward`** (static FZP feedforward): `ff_limit`, `out_min` / `out_max` to the same values as the FZP `Ub` / + `Lb` (they limit drive + feedforward). +- **`FreqGen`** `out_min` / `out_max` (channels 0 / 1) limit the FZP drive only while an excitation is running + (measurements). +- **`OnTargetTrigger`** `WaitForSlew` and **`TargetSelect_x` / `_y`** `use_final`: keep the defaults (1 / 0) with a + 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), + ≈ −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).