diff --git a/README.md b/README.md index db37388..798580f 100644 --- a/README.md +++ b/README.md @@ -46,23 +46,47 @@ The rack is a **MOPA** (master-oscillator power-amplifier) at 1550 nm: Run the booster in **ACC (constant-current)** mode — APC stepping quantises the output. Below transparency the booster erbium fibre *absorbs* the pre-amp output, so output stays at the PD floor (−60 dBm) until the pump is high -enough. Measured 2026-06-17 with ~6 mW (7.8 dBm) seed into the EDFA: +enough. -| Pump-1 | Output-1 | note | -|-------:|---------:|------| +### Pump-1 vs output characterisation (2026-06-17) + +Two sweeps. The transparency sweep used ~6 mW (7.8 dBm) seed into the EDFA; the +high-power sweep added a 3 dB pad (input 3.2 dBm, within the ≤5 dBm benchtop +spec) and a direct output-to-power-meter connection. + +| Pump-1 | Output-1 (internal PD) | note | +|-------:|------------------------|------| | 500–900 mA | −60 dBm | below transparency, signal absorbed | | 1200 mA | 21.0 dBm | booster turns on | -| 1500 mA | 23.3 dBm | | +| 1500 mA | 23.1 dBm | | | 2000 mA | 25.9 dBm | | -| 2500 mA | 27.1 dBm | documented operating point, ~515 mW | +| 2500 mA | 27.1 dBm / 514 mW | documented 0.5 W operating point | +| 3000 mA | 28.3 dBm / 679 mW | | +| 3500 mA | 29.3 dBm / 857 mW | | +| 4000 mA | 30.1 dBm / 1026 mW | **1 W rated ceiling** | +| 4500 mA | 30.85 dBm / 1216 mW | over-rating; curve still ~linear (not saturated) | -Pump current overshoots ~2× briefly on each step up and settles in 2–4 s, so -**ramp gradually** rather than jumping straight to the setpoint. +The unit (factory APC setpoint 30 dBm) comfortably exceeds 1 W: 1.22 W at +4500 mA with the output still climbing ~0.74 dB/500 mA and module temp only +~30 °C — so its true saturated maximum is higher, but driving a 1 W-rated pump +diode past rating trades lifetime for diminishing return. Pump current +overshoots ~2× briefly on each step up and settles in 2–4 s, so **ramp +gradually** rather than jumping to the setpoint. -> **Safety:** this is a Class 4, ~1 W, invisible 1550 nm source. The firmware -> clamps pump-1 to `PUMP_CURRENT_MAX_MA` (3000 mA) and seed current to -> `SEED_CURRENT_MAX_MA`, but those are not interlocks — treat the output as -> hazardous unless it terminates in a power meter / beam dump / closed system. +> **Internal PD vs external power meter:** at 4500 mA the internal PD reported +> 1.22 W while a Thorlabs meter measured **1.05 W** at the output (~0.6 dB +> high / residual loss). Treat the `amp/output*_power_dbm` telemetry as +> indicative, ~0.5–0.6 dB optimistic, not a calibrated power reading. (The +> earlier lab notes saw the opposite sign through a different connection, so +> the offset is path-dependent.) + +> **Safety:** Class 4, >1 W, invisible 1550 nm. The firmware clamps pump-1 to +> `PUMP_CURRENT_MAX_MA` (4000 mA ≈ the 1 W rating) and seed current to +> `SEED_CURRENT_MAX_MA` — guardrails against accidental over-drive, **not +> interlocks**. Above 1 W the Agiltron manual requires matched high-power +> connectors or a splice on the output, else the output fibre/amplifier can be +> damaged. Always drop the pump to 0 before unmating any fibre. Treat the +> output as hazardous unless it terminates in a power meter / beam dump. ## Hardware diff --git a/include/config.h b/include/config.h index 9bed98d..894574f 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,10 @@ // HA number sliders are capped here. The hardware allows 8000 mA pump, but // the lab notes report ~2500 mA pump-1 -> ~27 dBm (~515 mW). Keep a margin. #define SEED_CURRENT_MAX_MA 300 // CTL200 ilmax default is 1000; seed DFB is low-power -#define PUMP_CURRENT_MAX_MA 3000 // firmware clamps amp pump-1 to this +// Pump-1 clamp = the 1 W rated operating point (~4000 mA, measured 2026-06-17). +// Raise deliberately only for supervised over-rating characterisation; it is a +// guardrail against accidental over-drive, not a safety interlock. +#define PUMP_CURRENT_MAX_MA 4000 // ── Serial links to the instruments (wired in later increments) ───── // UART0 stays the USB console. The classic ESP32 has 3 hardware UARTs. diff --git a/src/agiltron.cpp b/src/agiltron.cpp index 6026a5a..8b64be6 100644 --- a/src/agiltron.cpp +++ b/src/agiltron.cpp @@ -79,6 +79,25 @@ int Agiltron::getPumpEnabled() { return (u16(r[8], r[9]) == 0) ? 1 : 0; // edfa.py: ==0 means enabled } +long Agiltron::logThresholds() { + uint8_t r[64]; + size_t n = transact(0x5F, nullptr, 0, r, sizeof(r)); + if (!validate(r, n, 0x5F) || n < 48) return -1; + auto u32 = [&](int o) -> uint32_t { + return ((uint32_t)r[o] << 24) | ((uint32_t)r[o+1] << 16) | + ((uint32_t)r[o+2] << 8) | r[o+3]; + }; + uint32_t maxPreampI = u32(8); + uint32_t maxPump1 = u32(24); + uint32_t maxPump2 = u32(32); + uint32_t maxPumpT = u32(44); // /10 = degC + Serial.printf("[agiltron] thresholds: max_preamp=%lu mA, max_pump1=%lu mA, " + "max_pump2=%lu mA, max_pump_temp=%.1f C\n", + (unsigned long)maxPreampI, (unsigned long)maxPump1, + (unsigned long)maxPump2, maxPumpT / 10.0); + return (long)maxPump1; +} + String Agiltron::getSn() { uint8_t r[64]; size_t n = transact(0x1F, nullptr, 0, r, sizeof(r)); diff --git a/src/agiltron.h b/src/agiltron.h index b955a04..6379306 100644 --- a/src/agiltron.h +++ b/src/agiltron.h @@ -50,6 +50,9 @@ public: // Authoritative pump-enable from get_settings (0x2E): byte[8:9]==0 => enabled. // Returns -1 on no/invalid reply, 0 = disabled, 1 = enabled. int getPumpEnabled(); + // Factory safety thresholds (0x5F). Logs to Serial; returns max pump-1 mA + // (the device's own ceiling), or -1 on no/invalid reply. + long logThresholds(); // Control (return true if the device ACKed) bool pumpOn() { return cmdAck(0x20, (const uint8_t[]){0x00,0x00}, 2); } diff --git a/src/main.cpp b/src/main.cpp index 0f7baf8..d67873a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -300,6 +300,7 @@ void setup() { AGILTRON_UART_NUM, AGILTRON_RX_PIN, AGILTRON_TX_PIN); String sn = agiltron.getSn(), pn = agiltron.getPn(); Serial.printf(" SN=\"%s\" PN=\"%s\"\n", sn.c_str(), pn.c_str()); + agiltron.logThresholds(); if (sn.length() == 0) Serial.println(" (no reply — Agiltron not wired? RX/TX swapped? wrong dev ID? GND?)"); #endif