简介:直流偏置光正交频分复用(DCO-OFDM)的MATLAB仿真资源包,面向光通信与数字信号处理领域的研究者和学习者,用于解决可见光通信中发光二极管非线性导致信号失真的问题。包内共两个脚本文件,压缩包仅三KB,其中DCO-OFDM主程序实现从符号映射、IFFT变换、添加循环前缀、加载直流偏置到接收端FFT与均衡解调的全流程,并附误码率统计;可见光信道建模脚本则涵盖光强度调制直接检测、大气吸收散射以及光电探测器响应特性,帮助还原真实传输环境。通过这套资源,读者可以快速搭建完整的DCO-OFDM可见光通信仿真链路,理解数字信号处理每一步的数学原理与实现方式,还能直接修改调制阶数、子载波数、信道参数等变量,观察对系统性能的影响。目前已有1550人浏览学习,适合作为课程设计、毕业设计或入门科研的参考代码。资源包小巧但结构清晰,便于逐行阅读和二次开发。
1. 为什么 DCO_OFDM 在可见光链路里绕不开直流偏置
接手一个 VLC 链路仿真时,最容易让人困惑的不是 OFDM 本身的调制解调,而是“发出去的光信号为什么不能直接复用射频 OFDM 波形”。原因是可见光通信走的是强度调制/直接检测(IM/DD)路径,LED 只能用光强度承载信息,所以发射信号必须是非负实数。传统 OFDM 的时域波形是双极性信号,负半周会直接落到 LED 非线性区,星座图被削得乱七八糟。DCO_OFDM 的解决思路就是加直流偏置,把波形整体抬进 LED 线性区,但偏置加多少、加在哪里、代价是什么,直接决定了最终误码率。这篇内容围绕 DFCO_OFDM_2021.m 和 VLC_channel_2021.m 两个仿真脚本展开,适合正在搭 VLC 物理层仿真平台、需要快速复现直流偏置光 OFDM 并做参数调优的工程师和研究人员。
2. DCO_OFDM 频域构造与直流偏置选取
2.1 Hermitian 对称是 DCO_OFDM 的第一步
DCO_OFDM 的信号设计是从频域开始的。要让 IFFT 输出实数序列,输入频谱必须满足共轭对称,也就是数据子载波放在正频率位置后,负频率位置要填它的共轭翻转值。MATLAB 的ifft不会主动帮你做这件事,填错位置会导致接收端星座点完全错乱。
Nfft = 256; % IFFT 点数 Ndata = Nfft/2 - 1; % 有效数据子载波数 M = 16; % 16QAM 调制 k_dc = 3; % 直流偏置系数,后面会细说 dataBits = randi([0 1], Ndata*log2(M), 1); dataSym = qammod(dataBits, M, 'InputType', 'bit', 'UnitAveragePower', true); X = zeros(Nfft, 1); X(2:1+Ndata) = dataSym; % 正频率子载波 X(Nfft/2+2:Nfft) = conj(flipud(X(2:1+Ndata))); % 负频率共轭对称 x = ifft(X, Nfft);X(1)是直流子载波,X(Nfft/2+1)是奈奎斯特子载波,这两个位置在 DCO_OFDM 里不携带数据。flipud把正向子载波反转后取共轭,目的是让X(k)和X(Nfft-k)严格配对。这样x就是实数序列,能够映射到光强度。这里最容易犯的错是直接用conj(X)填负频率,但负频率子载波的排列顺序是反向的,会导致 IFFT 输出虽然为实数,频域映射却错位,接收端解调出来完全对不上。
2.2 直流偏置怎么加,加多少
加直流偏置的目的是消除负极性,但偏置不是随便选一个固定电压值。工程上一般用偏置系数k_dc乘以 OFDM 时域信号的均方根值,把这个偏置作为信号标准差的倍数来设计,这样在不同调制阶数和子载波配置下,偏置的物理含义是一致的。
sigma_x = sqrt(mean(x.^2)); % OFDM 信号标准差 B_dc = k_dc * sigma_x; % 直流偏置幅值 x_dc = x + B_dc; % 抬升波形 x_dc(x_dc < 0) = 0; % 残余负样本底部削波 x_env = min(x_dc, 2*B_dc); % 顶部限幅,保护 LED 不进入饱和区偏置系数的典型取值范围是 2 到 4。偏置取 2 倍标准差时,负样本比例较高,底部削波带来的非线性失真会比较明显;取 4 倍标准差时线性度很好,但直流功率占掉了太多发射光功率,光功率效率下降。实际仿真里要扫k_dc看误码率曲线的最低点,不要凭经验拍脑袋。顶部限幅也是必须的,因为 LED 有最大驱动电流限制,OFDM 高峰均比特性决定了波形峰值会经常触顶,限幅噪声在高阶调制下尤其明显。
| 参数 | 典型取值 | 对链路的影响 |
|---|---|---|
Nfft | 256 | 子载波间隔变窄,频域分辨率更高,但单符号长度变大 |
Ndata | 127 | 实际承载数据的子载波数,决定频谱效率下限 |
M | 4 / 16 / 64 | 阶数越高,对偏置和削波噪声越敏感 |
k_dc | 2 ~ 4 | 偏置小则削波噪声大,偏置大则直流功率浪费严重 |
2.3 直流偏置的 dB 表示
很多论文里不写k_dc,而用B_dc相对于信号标准差的对数表示,例如“偏置 7 dB”对应的偏置系数约等于 2.24,10 dB 对应约 3.16。换算公式是10*log10((B_dc/sigma_x)^2 + 1),注意这里加 1 是把 OFDM 信号的交流功率也算进去,否则偏置电平会算偏。核对正文数据时要用同一个换算口径,否则仿真参数对不上。
3. DCO_OFDM_2021.m 发射接收链路跑通
3.1 发射端数据流向与循环前缀
DCO_OFDM_2021.m的核心逻辑可以拆成七个连续步骤:比特生成、QAM 符号映射、Hermitian 对称频域填充、IFFT、加循环前缀、直流偏置和削波、电光转换。循环前缀这段容易被人忽略,它在 VLC 信道里承担的是抵抗多径时延扩展的作用。
nSym = 100; % 发送 OFDM 符号数 cpLen = Nfft/8; % 循环前缀长度,取 1/8 符号长度 txSig = zeros(nSym*(Nfft+cpLen), 1); symIdx = 1; for idx = 1:nSym bits = randi([0 1], Ndata*log2(M), 1); sym = qammod(bits, M, 'InputType', 'bit', 'UnitAveragePower', true); X = zeros(Nfft,1); X(2:1+Ndata) = sym; X(Nfft/2+2:Nfft) = conj(flipud(sym)); x = ifft(X, Nfft); x_cp = [x(end-cpLen+1:end); x]; % 把末尾 cpLen 个样本复制到符号头部 x_dc = x_cp + B_dc; x_dc(x_dc < 0) = 0; txSig(symIdx:symIdx+length(x_dc)-1) = x_dc; symIdx = symIdx + length(x_dc); end注意这里循环前缀和直流偏置的顺序:先加 CP 再做直流偏置,这样每个 OFDM 符号的 CP 部分也带有直流分量,接收端去掉 CP 后,信号直流分量不会产生跳变。txSig是最终送入 LED 驱动电路的光强度波形,如果要加电光转换效率,可在这里乘上一个光电响应系数。
3.2 接收端均衡思路
接收端把光信号通过光电二极管转成电流后,先去掉直流分量,再按符号长度切分。频域均衡针对的是光信道对不同子载波的不同增益,通常用 LS 估计或者一阶迫零均衡就可以,VLC 信道的变化速度远慢于 OFDM 符号速率,不需要做复杂的自适应均衡。
y = awgn(txSig, SNR_dB, 'measured'); % 加噪声 rxSym = reshape(y, Nfft+cpLen, nSym); Y = fft(rxSym(cpLen+1:end, :), Nfft); % 去掉 CP 后做 FFT Yeq = Y ./ repmat(Hf, 1, nSym); % 频域迫零均衡 rxDataSym = Yeq(2:1+Ndata, :); rxBits = qamdemod(rxDataSym(:), M, 'OutputType', 'bit', 'UnitAveragePower', true);Hf是信道频响向量,在背靠背仿真中可以直接设为全 1 向量,验证发射接收链路本身没有问题后再替换成实际信道。repmat(Hf, 1, nSym)把信道频响复制到与接收矩阵相同的列数,注意Y和Hf的维度必须一致,否则 MATLAB 会直接报维度错误。在单纯背靠背排错时,可以先把Hf注释掉,直接看解调星座图是否正常。
3.3 循环前缀长度与符号同步的判断
循环前缀长度要大于信道最大时延扩展。VLC 室内链路的时延扩展通常在几十纳秒到几百纳秒,而 OFDM 符号周期取决于子载波间隔。当Nfft=256、采样率 100 MHz 时,符号周期约 2.56 微秒,CP 取 1/8 就是 320 纳秒,足够覆盖大多数漫射链路场景。同步错位一个样本,误码率会立刻抬升好几个数量级,因为 FFT 窗偏移破坏了子载波正交性。如果发现误码率曲线在低信噪比时就不平,先检查接收端的符号起点是否对准了 CP 结束位置。
4. VLC_channel_2021.m 信道模型和接收机噪声换算
4.1 朗伯辐射模型:这不是一根线就能算完的事
VLC 信道不能只用一个衰减系数描述,因为 LED 的辐射方向性和光电探测器的接收视场角共同决定了信道直流增益。VLC_channel_2021.m中最核心的是朗伯辐射模型,它把房间尺寸、LED 位置、探测器位置、辐射角和入射角全部纳入计算,输出一条非负实值的冲激响应。
function h = vlc_channel_2021(room, led, pd, fov, fs, N) m = -log(2) / log(cos(led.phiHalf)); % 朗伯阶数 d = norm(led.pos - pd.pos); cos_phi = dot(led.normal, pd.pos - led.pos) / d; cos_psi = dot(pd.normal, led.pos - pd.pos) / d; if cos_psi > cos(fov) H0 = (m+1) * pd.area / (2*pi*d^2) * cos_phi^m * cos_psi; else H0 = 0; end delay = round(d / 3e8 * fs) + 1; h = zeros(1, N); h(delay) = H0; endled.phiHalf是 LED 半功率角,朗伯阶数m越大,光束越集中。fov是探测器接收视场角,超出视场角的入射光直接丢弃。delay是根据光速和距离计算的传播延迟,采样率fs决定了延迟的量化精度。这里的输入参数N应该与 OFDM 符号长度一致,否则后续fft(h)做频域转换会长度不匹配。
4.2 信道归一化避免大数吞小信号
信道直流增益H0的计算结果通常远小于 1,比如典型室内链路在 2 米距离下只有 10^-5 量级。如果直接把这个增益乘到信号上,再叠加高斯白噪声,信号会被噪声淹没,误码率无法看出调制和偏置的影响。更合理的做法是把信道归一化,让信道对信号的增益在平均意义上为 1,再单独核算链路功率预算。
Hf = fft(h, Nfft); Hf_norm = Hf / abs(Hf(1)); % 以直流增益为基准做归一化Hf(1)是信道响应的直流分量,对应朗伯模型中的H0。归一化后,各个子载波的增益相对直流增益保留差异,信道频率选择性的影响依然存在,但整体功率水平被拉回 0 dB 量级。这样做的目的是把“信号功率”和“信道损耗”解耦,仿真结果里能直接看到 OFDM 调制和偏置参数带来的性能差异,而不是被链路衰减掩盖。
4.3 接收机噪声按电流域还是按电压域加
光电探测器输出的噪声包含了散粒噪声和热噪声,仿真中通常合并成一个加性高斯过程处理。在 MATLAB 里做awgn前,要明确信噪比定义在电域还是光域。常见做法是先把光信号乘上探测器响应度R_pd,转成电流信号,再在此电流域叠加 AWGN。
| 噪声设置项 | 推荐做法 | 说明 |
|---|---|---|
| 信噪比参考点 | SNR_dB基于电信号功率 | 与射频 OFDM 仿真口径一致 |
| 噪声带宽 | fs * (Ndata/Nfft) | 只统计有效子载波带宽内的噪声 |
响应度R_pd | 0.5 ~ 1 A/W | 只在链路功率预算分析时使用 |
| 信道归一化 | Hf / abs(Hf(1)) | 接信道后必须做,否则 BER 曲线无法对比 |
不统一换算口径,最容易出现的问题是背靠背仿真的理论 BER 曲线对得上,一接入信道就整体偏移几个 dB,那不是均衡问题,而是噪声带宽或信道增益定义不一致。
5. 用误码率和 EVM 反查偏置参数
5.1 先跑背靠背,再看星座图
验证 DCO_OFDM 链路的第一步永远是背靠背仿真,不接信道,直接让发射信号过 AWGN。此时解调出来的误码率应当接近理论值。若差距明显,先算 EVM(误差矢量幅度),它能区分不同层级的失真来源。
refSym = qammod((0:M-1)', M, 'UnitAveragePower', true); % 标准星座点 rxGrid = reshape(rxDataSym, [], 1); evm = sqrt(mean(min(abs(rxGrid - refSym.'), [], 2).^2) / mean(abs(refSym).^2));这个 EVM 指标衡量的是接收符号偏离标准星座点的整体程度。背靠背条件下 EVM 应该小于 5%,如果 EVM 在低偏置系数下急剧变大,说明底部削波产生的非线性是主导因素;如果偏置系数调到 4 以后 EVM 依然不降低,则要审视削顶限幅和高阶调制带来的峰值失真。
5.2 不同偏置系数下的表现对照
扫k_dc时记录 BER 和 EVM 的对应关系,可以帮助快速判断问题阶段。BER 在高信噪比下仍有平台期,通常是削波噪声;BER 曲线斜率正常但整体偏移,通常是信道归一化错误;星座图整体旋转但误码率接近零,属于相位参考偏移。
| 现象 | 现象 | 排查方向 |
|---|---|---|
低k_dc时 BER 恶化 | 底部削波噪声过强 | 增大k_dc,观察 EVM 是否同步下降 |
高k_dc时性能轻微回落 | 直流光功率浪费导致等效 SNR 下降 | 做功率归一化后重新计算SNR_dB |
| 星座点绕原点旋转 | 频偏或 FFT 窗起点偏移 | 检查符号同步逻辑和载波频偏补偿 |
最后一个值得实操的技巧是:把k_dc从 2 到 5 每隔 0.5 扫一遍,每次记录误码率和星座图,最后把曲线叠加在同一张图上,偏置过低和过高造成的性能损失曲线会在某个中间值附近形成一个明显的凹坑,DCO_OFDM 的最优工作点就这么确定下来,比单独盯着理论偏置公式更可靠。
本文还有配套的精品资源,点击获取