Document EDFA max-power characterisation; restore safe pump clamp
Swept pump-1 to find real output: 1 W (30.1 dBm) at 4000 mA, 1.22 W at 4500 mA still unsaturated. External Thorlabs meter read 1.05 W vs 1.22 W internal PD -> telemetry is ~0.5-0.6 dB optimistic, path-dependent; treat amp/output*_power_dbm as indicative, not calibrated. - README: full pump-vs-output table, PD-vs-meter calibration note, >1 W output-connector warning, ramp/overshoot guidance - config.h: PUMP_CURRENT_MAX_MA back to 4000 mA (1 W rating) after the supervised over-rating sweep; added get_thresholds probe to agiltron driver
This commit is contained in:
@@ -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
|
Run the booster in **ACC (constant-current)** mode — APC stepping quantises the
|
||||||
output. Below transparency the booster erbium fibre *absorbs* the pre-amp
|
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
|
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 |
|
| 500–900 mA | −60 dBm | below transparency, signal absorbed |
|
||||||
| 1200 mA | 21.0 dBm | booster turns on |
|
| 1200 mA | 21.0 dBm | booster turns on |
|
||||||
| 1500 mA | 23.3 dBm | |
|
| 1500 mA | 23.1 dBm | |
|
||||||
| 2000 mA | 25.9 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
|
The unit (factory APC setpoint 30 dBm) comfortably exceeds 1 W: 1.22 W at
|
||||||
**ramp gradually** rather than jumping straight to the setpoint.
|
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
|
> **Internal PD vs external power meter:** at 4500 mA the internal PD reported
|
||||||
> clamps pump-1 to `PUMP_CURRENT_MAX_MA` (3000 mA) and seed current to
|
> 1.22 W while a Thorlabs meter measured **1.05 W** at the output (~0.6 dB
|
||||||
> `SEED_CURRENT_MAX_MA`, but those are not interlocks — treat the output as
|
> high / residual loss). Treat the `amp/output*_power_dbm` telemetry as
|
||||||
> hazardous unless it terminates in a power meter / beam dump / closed system.
|
> 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
|
## Hardware
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -26,7 +26,10 @@
|
|||||||
// HA number sliders are capped here. The hardware allows 8000 mA pump, but
|
// 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.
|
// 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 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) ─────
|
// ── Serial links to the instruments (wired in later increments) ─────
|
||||||
// UART0 stays the USB console. The classic ESP32 has 3 hardware UARTs.
|
// UART0 stays the USB console. The classic ESP32 has 3 hardware UARTs.
|
||||||
|
|||||||
@@ -79,6 +79,25 @@ int Agiltron::getPumpEnabled() {
|
|||||||
return (u16(r[8], r[9]) == 0) ? 1 : 0; // edfa.py: ==0 means enabled
|
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() {
|
String Agiltron::getSn() {
|
||||||
uint8_t r[64];
|
uint8_t r[64];
|
||||||
size_t n = transact(0x1F, nullptr, 0, r, sizeof(r));
|
size_t n = transact(0x1F, nullptr, 0, r, sizeof(r));
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ public:
|
|||||||
// Authoritative pump-enable from get_settings (0x2E): byte[8:9]==0 => enabled.
|
// Authoritative pump-enable from get_settings (0x2E): byte[8:9]==0 => enabled.
|
||||||
// Returns -1 on no/invalid reply, 0 = disabled, 1 = enabled.
|
// Returns -1 on no/invalid reply, 0 = disabled, 1 = enabled.
|
||||||
int getPumpEnabled();
|
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)
|
// Control (return true if the device ACKed)
|
||||||
bool pumpOn() { return cmdAck(0x20, (const uint8_t[]){0x00,0x00}, 2); }
|
bool pumpOn() { return cmdAck(0x20, (const uint8_t[]){0x00,0x00}, 2); }
|
||||||
|
|||||||
@@ -300,6 +300,7 @@ void setup() {
|
|||||||
AGILTRON_UART_NUM, AGILTRON_RX_PIN, AGILTRON_TX_PIN);
|
AGILTRON_UART_NUM, AGILTRON_RX_PIN, AGILTRON_TX_PIN);
|
||||||
String sn = agiltron.getSn(), pn = agiltron.getPn();
|
String sn = agiltron.getSn(), pn = agiltron.getPn();
|
||||||
Serial.printf(" SN=\"%s\" PN=\"%s\"\n", sn.c_str(), pn.c_str());
|
Serial.printf(" SN=\"%s\" PN=\"%s\"\n", sn.c_str(), pn.c_str());
|
||||||
|
agiltron.logThresholds();
|
||||||
if (sn.length() == 0)
|
if (sn.length() == 0)
|
||||||
Serial.println(" (no reply — Agiltron not wired? RX/TX swapped? wrong dev ID? GND?)");
|
Serial.println(" (no reply — Agiltron not wired? RX/TX swapped? wrong dev ID? GND?)");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user