3. 光模块DDM实时监控数据采集
任务说明
通过 SFF-8472 标准,光模块 DDM(数字诊断监控)数据位于 A2h 页的 96~105 字节,共 5 个 16 位大端参数:温度、电压、偏置电流、发送光功率、接收光功率。本案例实现周期性读取这 5 个参数,按物理量换算后追加写入 CSV 文件,便于后续分析。
环境与依赖
- Python 3.8+,依赖
pyserial(pip install pyserial)。 - 光模块通过 I2C 转 USB 适配器(如 CH341、FT2232)接入,本案例使用其串口命令协议:发送
R <addr_hex> <len>,返回十六进制字符串。 - 若使用其他适配器,只需替换
read_i2c函数中的串口交互部分,其余逻辑不变。
DDM 数据换算
原始值为 16 位无符号整数(大端),换算关系:
- 温度 = raw / 256.0(℃)
- 电压 = raw / 10000.0(V)
- 偏置电流 = raw × 2 / 1000.0(mA)
- 收/发光功率 = raw / 10000.0(mW)
完整代码
import serial, time, csv, struct
from datetime import datetime
PORT = "COM3" # Linux 下改为 /dev/ttyUSB0
BAUD = 9600
INTERVAL = 2.0 # 采集周期(秒)
CSV_FILE = "ddm_log.csv"
A2 = 0xA2 # DDM 页地址
DDM_OFFSET = 96 # DDM 起始字节
DDM_LEN = 10 # 5 个 16 位参数
def read_i2c(ser, dev_addr, offset, length):
"""通过适配器串口协议读取 I2C 数据,返回 bytes。"""
cmd = f"R {dev_addr:02X} {offset:02X} {length:02X}\n"
ser.reset_input_buffer()
ser.write(cmd.encode())
line = ser.readline().decode().strip()
# 适配器返回形如 "D0 01 23 ..." 的十六进制串
hexs = line.split()
if len(hexs) != length:
raise IOError(f"读取长度不符: {line!r}")
return bytes(int(h, 16) for h in hexs)
def parse_ddm(raw):
"""解析 10 字节为 5 个物理量。"""
temp, volt, bias, txp, rxp = struct.unpack(">5H", raw)
return {
"temperature_C": temp / 256.0,
"voltage_V": volt / 10000.0,
"bias_mA": bias * 2 / 1000.0,
"tx_power_mW": txp / 10000.0,
"rx_power_mW": rxp / 10000.0,
}
def main():
ser = serial.Serial(PORT, BAUD, timeout=1)
fields = ["timestamp", "temperature_C", "voltage_V",
"bias_mA", "tx_power_mW", "rx_power_mW"]
with open(CSV_FILE, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=fields)
writer.writeheader()
try:
while True:
raw = read_i2c(ser, A2, DDM_OFFSET, DDM_LEN)
row = parse_ddm(raw)
row["timestamp"] = datetime.now().isoformat(timespec="seconds")
writer.writerow(row)
f.flush()
print(row)
time.sleep(INTERVAL)
except KeyboardInterrupt:
print("采集结束")
finally:
ser.close()
if __name__ == "__main__":
main()
运行与验证
- 确认适配器串口号(Windows 设备管理器 / Linux
ls /dev/ttyUSB*),修改PORT。 - 执行
python ddm_monitor.py,终端每 2 秒打印一行字典。 - 按 Ctrl+C 停止,检查当前目录下
ddm_log.csv:
timestamp,temperature_C,voltage_V,bias_mA,tx_power_mW,rx_power_mW
2024-05-01T10:00:00,42.35,3.3012,6.512,0.5012,0.4780
2024-05-01T10:00:02,42.37,3.3010,6.514,0.5010,0.4778
通过条件:CSV 表头正确、每行时间戳递增、5 个数值落在光模块合理范围(温度 -40~100℃、电压 3.0~3.6V、偏置电流 0~100mA、光功率 0~10mW)。若读取长度不符会抛出 IOError,说明适配器协议或地址需核对。