James Bateman (hp-laptop)andClaude Opus 4.8 ffadf4b37b Add bill of materials; link it from the README
Full parts list to rebuild the MOPA: seed (DFB1550LP + CTL200 + its
5.9 V/3 A supply), Agiltron M511 EYDFA booster + v1.10 adaptor board,
ESP32 bridge, fibre/attenuator/output-connector optics, and the 3V3
signal wiring table. Electrical specs not firmly in the lab notes are
flagged to confirm from the datasheet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-10-02 13:34:16 +01:00

koheron-esp32-bridge

ESP32 firmware that bridges the Butterfly EDFA Rack — a 1550 nm MOPA: a Koheron CTL200 driving a DFB seed into an Agiltron M511 EYDFA power amplifier (output up to ~1 W / 30 dBm) — to WiFi/MQTT for monitoring and control from Home Assistant (broker 192.168.0.102:1883, anonymous).

The whole rack is presented as a single HA device (butterfly_edfa_rack). Topics, mirroring the lab's EDFA→MQTT convention:

lab/laser/butterfly_edfa_rack/availability      online | offline (LWT)
lab/laser/butterfly_edfa_rack/diag/<key>        ESP/network diagnostics
lab/laser/butterfly_edfa_rack/seed/<key>        Koheron CTL200      (increment 3)
lab/laser/butterfly_edfa_rack/amp/<key>         Agiltron M511       (increment 4)
lab/laser/butterfly_edfa_rack/set/<...>         commands            (increment 5)

HA discovery configs are published under homeassistant/..., all sharing one device block so entities group under the single rack device.

Optical architecture

The rack is a MOPA (master-oscillator power-amplifier) at 1550 nm:

 Koheron CTL200            Agiltron M511 EYDFA (two-stage)
 ┌──────────────┐          ┌─────────────────────────────────────┐
 │ DFB1550LP    │  fibre   │  pre-amp stage  ──►  booster stage   │  fibre
 │ seed diode   ├─────────►│  (pump diode A)      (pump diode B,  ├────────►  output
 │ + TEC        │          │   ~170 mA, ~16 dBm    "pump-1")      │           (up to ~1 W
 └──────────────┘          └─────────────────────────────────────┘            / 30 dBm)
   ilaser, lason             input PD   preamp PD     output-1 PD

The M511 has two internal pump diodes, and the firmware reads both:

  • Pre-amp pump — runs semi-independently at ~170 mA, lifts the seed to ~16 dBm (amp/preamp_current_ma, amp/preamp_power_dbm).
  • Booster pump = "pump-1" — the controllable output stage (amp/pump1_current_ma, set via set/amp/pump1_current_ma).
  • "Pump-2" is a second booster channel that this unit leaves at 0 mA regardless of settings (per Lab/Equipment/Lasers/Agiltron EDFA); we don't drive it. It is read but not exposed as a control.

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.

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.1 dBm
2000 mA 25.9 dBm
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)

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.

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

Full parts list (seed, amplifier, supplies, fibre, wiring) is in BOM.md.

  • ESP32-D0WD-V3 dev board (WROOM-32 class), CP2102N USB bridge → /dev/ttyUSB0, MAC b0:cb:d8:8f:ba:10.

  • The ESP32 USB port is used only for flashing/console (UART0).

  • Two instrument links on separate hardware UARTs:

    ESP32 Instrument Protocol
    GPIO17 (TX2) → Koheron CTL200 RX (terminal block) ASCII, 115200 8N1, \r\n, >> prompt
    GPIO16 (RX2) ← Koheron CTL200 TX
    GPIO26 (TX1) → Agiltron M511 RX (P2 pin 3) binary 0x55AA packets, 115200 8N1
    GPIO25 (RX1) ← Agiltron M511 TX (P2 pin 7)
    GND both grounds

    All links are 3V3 logic (CTL200 is 5V-tolerant). UART1 is remapped off its default flash-clashing pins.

Network: the firmware pins a static IP 192.168.0.150 (gateway .1, /24) — see USE_STATIC_IP in include/config.h. This avoids the clash with the BKtel EDFA Pi on .101 that a DHCP lease originally caused. .150 is outside any device documented in the HA notes; move it if your DHCP pool overlaps.

Toolchain

PlatformIO (Arduino framework), pinned in a project-local .venv so nothing is installed globally.

make            # show targets
make build      # compile
make upload     # compile + flash (PORT=/dev/ttyUSB0 by default)
make monitor    # serial console at 115200
make detect     # identify the chip on the port

A fresh checkout self-bootstraps the venv on first make.

Configuration

Copy include/secrets.example.h → include/secrets.h (git-ignored) and fill in WiFi + MQTT details. Needed from increment 2 onward.

Increment roadmap

  • 1 — toolchain check. Blink + serial heartbeat; confirms build/upload/monitor.
  • 2 — WiFi + MQTT + HA discovery. Joins WiFi, connects to broker with an LWT availability topic, publishes diagnostic entities (uptime, RSSI, IP).
  • 3 — Seed telemetry (read-only). UART2 → Koheron lason/ilaser/vlaser/rtset/rtact/itec/vtec/tboard/iphd/err; published under seed/... as HA sensors. Verified live against CTL200 fw v0.21 (echo + value + >> framing, parsed correctly).
  • 4 — Amp telemetry (read-only). UART1 → Agiltron get_status (binary 0x55AA, ported from edfa.py); publishes module/pre-amp temp, pre-amp & pump-1 currents, input/pre-amp/output dBm, warnings under amp/.... Verified against the live unit (SN Y4022708, PN EDFA-1C51113331111, device ID 0x0000006F). amp/pump_enabled reads the authoritative get_settings field.
  • 5 — control. set/... for seed (lason, ilaser) and amp (pump on/off, pump-1 ACC current) as HA switch/number entities, with firmware current clamps. Verified end-to-end: MQTT command → seed lasing → booster ramp to 27 dBm. Seed TEC setpoint (rtset, in ohms) is also settable, with a read-only °C readout derived from the thermistor. (Future: seed tecon, amp APC power, Koheron save.)

MQTT interface

State topics retained under lab/laser/butterfly_edfa_rack/:

Topic suffix Meaning
availability online / offline (LWT)
diag/{uptime,rssi,ip} ESP / network diagnostics
seed/link Koheron reachable?
seed/laser_enabled seed laser on (1/0)
seed/current_ma, seed/voltage_v seed drive
seed/rt_setpoint_ohm, seed/rt_actual_ohm thermistor setpoint / actual
seed/temp_c seed diode temperature (from rt_actual via NTC β-model, indicative)
seed/tec_current_a, seed/tec_voltage_v, seed/board_temp_c seed TEC / board
seed/photodiode_ma, seed/error seed monitor PD, CTL200 error code
amp/link Agiltron reachable?
amp/module_temp_c, amp/preamp_temp_c EDFA temperatures
amp/preamp_current_ma, amp/preamp_power_dbm pre-amp stage
amp/pump1_current_ma, amp/pump1_set_ma booster pump actual / setpoint
amp/input_power_dbm, amp/output1_power_dbm, amp/output2_power_dbm optical powers
amp/pump_enabled, amp/warnings booster state, decoded warnings

Command topics (publish to lab/laser/butterfly_edfa_rack/set/):

Topic suffix Payload Action
seed/laser 1 / 0 Koheron lason
seed/current_ma mA Koheron ilaser (clamped ≤ SEED_CURRENT_MAX_MA)
seed/rt_setpoint_ohm Ω Koheron rtset, seed TEC setpoint (clamped SEED_RT_SETPOINT_MIN/MAX_OHM)
amp/pump 1 / 0 Agiltron pump on / off
amp/pump1_current_ma mA set ACC mode + pump-1 current (clamped ≤ PUMP_CURRENT_MAX_MA)
S
Description
No description provided
Readme
132 KiB
Languages
C++ 81.8%
C 14.5%
Makefile 3.7%