diff --git a/docs/tower-installation.md b/docs/tower-installation.md index 8ce50c3..208182a 100644 --- a/docs/tower-installation.md +++ b/docs/tower-installation.md @@ -723,7 +723,7 @@ MTU 8000): RGB (G-1236C), NIR and ACR (both G-1236B). Their firmware | Program / Alvium | Manta | |---|---| | `ExposureTime` | `ExposureTimeAbs` | -| `AcquisitionFrameRate` (+ `…Enable`) | `AcquisitionFrameRateAbs`, free-running at `AcquisitionFrameRateLimit` | +| `AcquisitionFrameRate` (+ `…Enable`) | `AcquisitionFrameRateAbs` - which a free-running Manta runs at, up to `AcquisitionFrameRateLimit` | | `IntensityControllerTarget` / `…Tolerance` | `ExposureAutoTarget` / `ExposureAutoAdjustTol` | | `DeviceLinkThroughputLimit` | `StreamBytesPerSecond` (max 124 MB/s, shared by every camera on the port) | | `BayerRG12p`, chunk data, `DeviceReset` | none | @@ -732,8 +732,9 @@ The program looks a missing feature up under its older name, so `test camera` and the telemetry work. `export_camera_profile.py` picks its `gige` recipe by itself when a camera has `ExposureTimeAbs` and no `ExposureTime`: frame trigger off (the legacy cameras booted with `TriggerMode = On`, `Line1`), `BayerRG8` on -the colour camera and `Mono8` on a mono one, 60 MB/s each, and an auto-exposure -target of 50 %. That last one matters: the keep rule waits for the frame mean +the colour camera and `Mono8` on a mono one, 60 MB/s each, the frame rate at +the camera's maximum (rietschen's RGB camera came set to 0.955 fps), and an +auto-exposure target of 50 %. That last one matters: the keep rule waits for the frame mean to reach 50 %, and at the cameras' old 25 every waypoint ran into `frame_timeout_ms`. diff --git a/scripts/export_camera_profile.py b/scripts/export_camera_profile.py index 6fd3223..58a8d9e 100755 --- a/scripts/export_camera_profile.py +++ b/scripts/export_camera_profile.py @@ -143,6 +143,13 @@ _GIGE_COMMON = [ ("Height", 100000), ("PixelFormat", ("BayerRG8", "Mono8")), ("StreamBytesPerSecond", 60000000), + # Free-running, a Manta still runs at AcquisitionFrameRateAbs, not at its + # limit: rietschen's RGB camera came with 0.955 and delivered 5 frames in + # 5.2 s. A short fixed exposure first, so the rate is not capped by the + # exposure the camera happens to hold, as in the Alvium recipe. + ("ExposureAuto", "Off"), + ("ExposureTimeAbs", 1000.0), + ("AcquisitionFrameRateAbs", 1000.0), # clamped to the camera's maximum ("ChunkModeActive", False), # The keep rule waits for the frame mean to reach the camera's target. The # host starts on its default band of 50 % - rietschen's cameras were set to @@ -290,14 +297,13 @@ def main(): refused.append(n) # What the settings actually cost per frame - the number that decides - # whether this profile can be delivered over the link at all. A - # free-running GigE camera reports its ceiling as the rate limit. + # whether this profile can be delivered over the link at all. try: w = cam.get_feature_by_name("Width").get() h = cam.get_feature_by_name("Height").get() fmt = cam.get_feature_by_name("PixelFormat").get() bpp = {"RGB8": 3, "BGR8": 3, "BayerRG12p": 1.5, "BayerRG12": 2}.get(str(fmt), 1) - rate_name = "AcquisitionFrameRateLimit" if family == "gige" else "AcquisitionFrameRate" + rate_name = "AcquisitionFrameRateAbs" if family == "gige" else "AcquisitionFrameRate" rate = cam.get_feature_by_name(rate_name).get() mb = w * h * bpp / 1e6 print(f"\nresult : {w}x{h} {fmt} {mb:.1f} MB/frame " diff --git a/src/core/TestRunner.cpp b/src/core/TestRunner.cpp index b5da229..d991185 100644 --- a/src/core/TestRunner.cpp +++ b/src/core/TestRunner.cpp @@ -1097,13 +1097,26 @@ void TestRunner::testHwEnv(TestReport& r) { } setProgress(s.id, 2, 2, "reading sensor"); + std::optional sample = hw_.env ? hw_.env->sample() : std::nullopt; + // The firmware reads its DHT11 every 10 s, the first time 2 s after it + // starts, so a run straight after the host connected may have no reading + // yet: install-tower --verify failed on rietschen 1.4 s into its run, 36 s + // after the same test had passed. Wait one read period before calling it + // missing. + if (hw_.env && !sample && on_mcu) { + const auto deadline = clock_t_::now() + 12s; + while (!sample && clock_t_::now() < deadline && !cancelled()) { + std::this_thread::sleep_for(200ms); + sample = hw_.env->sample(); + } + } CheckResult m; if (!hw_.env) { m.pass = false; m.detail = "declared as '" + hw_.declared->env + "' but no sensor was built -- check [Env] i2c_device; the declaration itself is " "what enables it"; - } else if (auto sample = hw_.env->sample()) { + } else if (sample) { m.detail = "CRC-valid reading from " + hw_.env->name(); } else if (on_mcu) { m.pass = false;