Series: Lora

Lora解调原理


Lora解调


可以把 LoRa 的解调理解成一条非常明确的流水线:

收到一条“起点被移动”的上扫啁啾 → 用标准下扫啁啾消掉扫描变化 → 得到固定频率 → FFT 判断固定频率是多少 → 恢复符号值。

一、先确定一个 LoRa 符号有多少种可能

LoRa 的扩频因子为 SF

一个符号一共有:

M=2SFM=2^{SF}

种可能取值。

因此,符号值为:

m{0,1,2,,M1}m\in\left\{0,1,2,\ldots,M-1\right\}

也就是:

m{0,1,2,,2SF1}m\in\left\{0,1,2,\ldots,2^{SF}-1\right\}

例如 SF10:

M=210=1024M=2^{10}=1024

因此一个 LoRa 调制符号的编号范围是:

m=0,1,2,,1023m=0,1,2,\ldots,1023

这里的:

mm

就是我们最终想从接收信号中识别出来的数。

二、一个符号持续多长时间

LoRa 的符号时间为:

Ts=2SFBWT_s=\frac{2^{SF}}{BW}

也可以写成:

Ts=MBWT_s=\frac{M}{BW}

其中:

  • TsT_s:一个符号持续时间;

  • BWBW:LoRa 信号带宽;

  • M=2SFM=2^{SF}

例如:

SF=10SF=10 BW=1 MHzBW=1\ \mathrm{MHz}

则:

Ts=2101000000=1.024 msT_s = \frac{2^{10}}{1\,000\,000} = 1.024\ \mathrm{ms}

也就是说,一条完整的 LoRa 啁啾持续 1.024 ms。

三、标准上扫啁啾是什么

先考虑一个标准上扫啁啾。

它的瞬时频率随着时间线性增加:

fchirp(t)=f0+ktf_{\mathrm{chirp}}(t)=f_0+kt

其中:

  • f0f_0:起始频率;

  • kk:扫频斜率;

  • tt:当前时间。

因为一条啁啾在一个符号时间内扫过整个带宽,所以:

k=BWTsk=\frac{BW}{T_s}

代入符号时间:

k=BW2SF/BWk = \frac{BW}{2^{SF}/BW}

因此:

k=BW22SFk=\frac{BW^2}{2^{SF}}

这个:

kk

表示频率变化的速度。

例如一条啁啾在 1 ms 内扫过 1 MHz,则:

k=1 MHz1 msk = \frac{1\ \mathrm{MHz}}{1\ \mathrm{ms}}

意思就是频率在 1 ms 内增加 1 MHz。

四、频率函数怎么变成真正的 IQ 信号

频率表示“复数指针旋转得多快”。

相位表示“复数指针目前累计转了多少角度”。

频率累积起来得到相位:

ϕ(t)=2π0tf(τ)dτ\phi(t) = 2\pi\int_0^t f(\tau)\,d\tau

标准上扫啁啾的频率是:

fchirp(t)=f0+ktf_{\mathrm{chirp}}(t)=f_0+kt

因此它的相位为:

ϕchirp(t)=2π0t(f0+kτ)dτ\phi_{\mathrm{chirp}}(t) = 2\pi \int_0^t \left(f_0+k\tau\right) d\tau

积分之后:

ϕchirp(t)=2π(f0t+12kt2)\phi_{\mathrm{chirp}}(t) = 2\pi \left( f_0t+\frac{1}{2}kt^2 \right)

所以标准上扫啁啾的复数 IQ 信号可以写成:

x0(t)=Aej2π(f0t+12kt2)x_0(t) = A e^{ j2\pi \left( f_0t+\frac{1}{2}kt^2 \right) }

这里:

  • AA:信号幅度;

  • f0tf_0t:由起始频率产生的相位;

  • 12kt2\frac{1}{2}kt^2:由频率不断增加产生的相位;

  • jj:表示这是复数 IQ 信号。

五、数据是怎么放进啁啾里的

LoRa 不改变啁啾的斜率。

不同符号使用的都是相同斜率,只是啁啾在带宽中的循环起点不同。

带宽被划分成:

MM

个位置:

M=2SFM=2^{SF}

相邻位置之间的频率间隔为:

Δf=BWM\Delta f=\frac{BW}{M}

也就是:

Δf=BW2SF\Delta f=\frac{BW}{2^{SF}}

如果当前符号值是:

mm

那么对应的等效频率偏移为:

fm=mΔff_m=m\Delta f

代入:

Δf\Delta f

得到:

fm=mBW2SFf_m = m\frac{BW}{2^{SF}}

因此,可以用一个简化但非常实用的形式表示符号:

mm

对应的啁啾:

xm(t)=x0(t)ej2πfmtx_m(t) = x_0(t) e^{j2\pi f_m t}

含义是:

  • x0(t)x_0(t):标准上扫啁啾;

  • ej2πfmte^{j2\pi f_m t}:符号 mm 带来的频率偏移。

把:

x0(t)x_0(t)

展开:

xm(t)=Aej2π(f0t+12kt2)ej2πfmtx_m(t) = A e^{ j2\pi \left( f_0t+\frac{1}{2}kt^2 \right) } e^{j2\pi f_m t}

指数相加:

xm(t)=Aej2π(f0t+fmt+12kt2)x_m(t) = A e^{ j2\pi \left( f_0t+f_mt+\frac{1}{2}kt^2 \right) }

如果把标准啁啾的起始频率部分暂时省略,重点观察数据偏移,可以写成:

xm(t)=Aej2π(fmt+12kt2)x_m(t) = A e^{ j2\pi \left( f_mt+\frac{1}{2}kt^2 \right) }

这里可以看出:

  • 12kt2\frac{1}{2}kt^2 是所有符号共有的啁啾扫描;

  • fmtf_mt 是符号 mm 带来的数据部分。

六、接收端收到什么

忽略噪声、时间偏差和频率误差时,接收到的一个符号可以写成:

r(t)=Aej2π(fmt+12kt2)r(t) = A e^{ j2\pi \left( f_mt+\frac{1}{2}kt^2 \right) }

它包含两个部分:

fmt符号数据+12kt2上扫啁啾\underbrace{f_mt}_{\text{符号数据}} + \underbrace{\frac{1}{2}kt^2}_{\text{上扫啁啾}}

接收端的任务就是:

把所有符号共有的啁啾部分去掉,只留下:

fmf_m

七、Dechirp:用下扫啁啾消掉上扫啁啾

接收端生成一个标准参考下扫啁啾:

xdown(t)=ej2π12kt2x_{\mathrm{down}}(t) = e^{ -j2\pi \frac{1}{2}kt^2 }

它和标准上扫啁啾的斜率完全相反。

接收信号为:

r(t)=Aej2π(fmt+12kt2)r(t) = A e^{ j2\pi \left( f_mt+\frac{1}{2}kt^2 \right) }

Dechirp 就是两者相乘:

y(t)=r(t)xdown(t)y(t) = r(t)x_{\mathrm{down}}(t)

代入:

y(t)=Aej2π(fmt+12kt2)ej2π12kt2y(t) = A e^{ j2\pi \left( f_mt+\frac{1}{2}kt^2 \right) } e^{ -j2\pi \frac{1}{2}kt^2 }

复指数相乘时,指数相加:

y(t)=Aej2π(fmt+12kt212kt2)y(t) = A e^{ j2\pi \left( f_mt + \frac{1}{2}kt^2 - \frac{1}{2}kt^2 \right) }

啁啾部分抵消:

12kt212kt2=0\frac{1}{2}kt^2 - \frac{1}{2}kt^2 = 0

最后得到:

y(t)=Aej2πfmty(t) = A e^{j2\pi f_mt}

这个结果已经不再是啁啾了。

它是一个固定频率为:

fmf_m

的复数单音。

八、为什么 Dechirp 后会变成固定频率

接收啁啾的瞬时频率是:

frx(t)=fm+ktf_{\mathrm{rx}}(t)=f_m+kt

参考下扫啁啾的瞬时频率是:

fdown(t)=ktf_{\mathrm{down}}(t)=-kt

复数信号相乘后,频率相加:

fresult(t)=frx(t)+fdown(t)f_{\mathrm{result}}(t) = f_{\mathrm{rx}}(t) + f_{\mathrm{down}}(t)

代入:

fresult(t)=(fm+kt)+(kt)f_{\mathrm{result}}(t) = \left(f_m+kt\right)+\left(-kt\right)

得到:

fresult(t)=fmf_{\mathrm{result}}(t)=f_m

也就是:

变化频率+反向变化频率=固定频率\text{变化频率} + \text{反向变化频率} = \text{固定频率}

所以 Dechirp 的本质是:

上扫啁啾×下扫啁啾=固定频率单音\boxed{ \text{上扫啁啾} \times \text{下扫啁啾} = \text{固定频率单音} }

九、固定频率如何变成 FFT bin

现在 Dechirp 后得到:

y(t)=Aej2πfmty(t) = A e^{j2\pi f_mt}

而符号频率为:

fm=mBWMf_m=m\frac{BW}{M}

因为:

M=2SFM=2^{SF}

所以:

fm=mBW2SFf_m = m\frac{BW}{2^{SF}}

为了方便说明,假设解调前已经把采样率调整为:

Fs=BWF_s=BW

一个符号内的采样点数为:

N=FsTsN=F_sT_s

代入:

Fs=BWF_s=BW

得到:

N=BW2SFBWN = BW \frac{2^{SF}}{BW}

因此:

N=2SFN=2^{SF}

也就是:

N=MN=M

一个符号刚好有:

2SF2^{SF}

个采样点。

十、把连续信号变成离散采样

采样时刻为:

tn=nFst_n=\frac{n}{F_s}

因为:

Fs=BWF_s=BW

所以:

tn=nBWt_n=\frac{n}{BW}

其中:

n=0,1,2,,N1n=0,1,2,\ldots,N-1

Dechirp 后的信号为:

y(t)=Aej2πfmty(t)=Ae^{j2\pi f_mt}

采样之后:

y[n]=Aej2πfmtny[n] = Ae^{j2\pi f_mt_n}

代入:

fm=mBWNf_m=m\frac{BW}{N}

以及:

tn=nBWt_n=\frac{n}{BW}

得到:

y[n]=Aej2π(mBWN)(nBW)y[n] = A e^{ j2\pi \left( m\frac{BW}{N} \right) \left( \frac{n}{BW} \right) }

约掉:

BWBW

得到:

y[n]=Aej2πmnNy[n] = A e^{ j2\pi \frac{mn}{N} }

这就是一个刚好落在第:

mm

个 FFT bin 上的复数单音。

十一、FFT 实际上在做什么

对:

y[n]y[n]

做:

NN

点 FFT:

Y[p]=n=0N1y[n]ej2πpnNY[p] = \sum_{n=0}^{N-1} y[n] e^{-j2\pi\frac{pn}{N}}

其中:

pp

表示 FFT 正在测试的 bin:

p=0,1,2,,N1p=0,1,2,\ldots,N-1

代入:

y[n]=Aej2πmnNy[n] = A e^{j2\pi\frac{mn}{N}}

得到:

Y[p]=n=0N1Aej2πmnNej2πpnNY[p] = \sum_{n=0}^{N-1} A e^{j2\pi\frac{mn}{N}} e^{-j2\pi\frac{pn}{N}}

指数合并:

Y[p]=An=0N1ej2π(mp)nNY[p] = A \sum_{n=0}^{N-1} e^{ j2\pi \frac{(m-p)n}{N} }

十二、为什么正确的 bin 会特别大

假设 FFT 测试的 bin 正好是符号值:

p=mp=m

那么:

mp=0m-p=0

因此:

ej2π(mp)nN=ej0=1e^{ j2\pi \frac{(m-p)n}{N} } = e^{j0} = 1

于是:

Y[m]=An=0N11Y[m] = A \sum_{n=0}^{N-1}1

一共有:

NN

项:

Y[m]=ANY[m]=AN

也就是说,所有采样点都同方向相加,能量非常大。

十三、为什么错误的 bin 会互相抵消

假设:

pmp\neq m

那么 FFT 消除掉的频率和输入频率不一致,还会留下一个旋转成分:

ej2π(mp)nNe^{ j2\pi \frac{(m-p)n}{N} }

随着:

nn

增加,这些复数点会围绕圆周旋转。

相加时大致会互相抵消:

Y[p]=An=0N1ej2π(mp)nN0Y[p] = A \sum_{n=0}^{N-1} e^{ j2\pi \frac{(m-p)n}{N} } \approx 0

所以:

  • 正确 bin:所有点方向一致,叠加后很大;

  • 错误 bin:点朝不同方向,叠加后互相抵消。

十四、找到最大峰值就是符号值

FFT 完成后,找幅度最大的 bin:

m^=arg maxpY[p]\hat{m} = \underset{p} {\operatorname{arg\,max}} \left|Y[p]\right|

也可以比较能量:

m^=arg maxpY[p]2\hat{m} = \underset{p} {\operatorname{arg\,max}} \left|Y[p]\right|^2

其中:

  • Y[p]Y[p]:第 pp 个 FFT bin;

  • Y[p]\left|Y[p]\right|:该 bin 的幅度;

  • m^\hat m:接收机估计出来的符号值。

例如 FFT 的第 300 个 bin 最大:

m^=300\hat{m}=300

那么接收机就判断该 LoRa 调制符号为 300。

十五、用 SF10 的数字例子串起来

假设:

SF=10SF=10 BW=1 MHzBW=1\ \mathrm{MHz}

那么:

M=210=1024M=2^{10}=1024

每个频率位置的间隔为:

Δf=10000001024\Delta f = \frac{1\,000\,000}{1024}

即:

Δf976.5625 Hz\Delta f \approx 976.5625\ \mathrm{Hz}

假设发送符号为:

m=300m=300

那么它对应的频率偏移是:

fm=300×976.5625f_m = 300\times976.5625

得到:

fm=292968.75 Hzf_m = 292\,968.75\ \mathrm{Hz}

发送的啁啾可以简化表示为:

x300(t)=Aej2π(292968.75t+12kt2)x_{300}(t) = A e^{ j2\pi \left( 292\,968.75t + \frac{1}{2}kt^2 \right) }

接收端乘以下扫啁啾:

xdown(t)=ej2π12kt2x_{\mathrm{down}}(t) = e^{ -j2\pi \frac{1}{2}kt^2 }

得到:

y(t)=Aej2π292968.75ty(t) = A e^{ j2\pi 292\,968.75t }

这是一个固定频率约为 292.97 kHz 的单音。

进行 1024 点 FFT:

N=1024N=1024

FFT 的频率间隔为:

ΔfFFT=FsN\Delta f_{\mathrm{FFT}} = \frac{F_s}{N}

因为:

Fs=1 MHzF_s=1\ \mathrm{MHz}

所以:

ΔfFFT=10000001024=976.5625 Hz\Delta f_{\mathrm{FFT}} = \frac{1\,000\,000}{1024} = 976.5625\ \mathrm{Hz}

单音所在的 bin 为:

p=292968.75976.5625p = \frac{292\,968.75}{976.5625}

得到:

p=300p=300

因此:

m^=300\hat m=300

整个过程就是:

  1. FFT 得到 LoRa 调制符号值
  2. 进行符号映射还原
  3. 进行去交织
  4. 进行纠错译码
  5. 进行去白化
  6. 解析 LoRa 头部和负载
  7. 进行 CRC 校验
  8. 得到原始数据

十六、恢复符号后还没有直接得到原始数据

FFT 得到的是 LoRa 的调制符号值

m^=arg maxpY[p]\hat m = \underset{p} {\operatorname{arg\,max}} \left|Y[p]\right|

它一般不能直接当成原始用户 bit。

实际 LoRa 接收链路后面还需要进行:

  1. 天线接收射频信号
  2. 接收机进行下变频,得到基带 IQ 信号
  3. 对 IQ 信号进行滤波
  4. 对 IQ 信号进行降采样
  5. 检测 LoRa 前导码
  6. 根据前导码完成时间同步
  7. 根据前导码完成频率同步
  8. 确定每个 LoRa 符号的起始位置
  9. 按照符号时间切分 IQ 采样
  10. 将每个接收符号乘以参考下扫啁啾
  11. 完成 Dechirp 解啁啾
  12. 将变化频率的啁啾变成固定频率单音
  13. 对固定频率单音进行 FFT
  14. 找到幅度或能量最大的 FFT bin
  15. 根据峰值 bin 恢复 LoRa 调制符号值
  16. 进行符号映射还原
  17. 进行去交织
  18. 进行纠错译码
  19. 进行去白化
  20. 解析 LoRa 头部和负载
  21. 进行 CRC 校验
  22. 得到最终的原始数据

最核心的一段

rm(t)=Aej2π(fmt+12kt2)r_m(t) = A e^{ j2\pi \left( f_mt+\frac{1}{2}kt^2 \right) } xdown(t)=ej2π12kt2x_{\mathrm{down}}(t) = e^{ -j2\pi \frac{1}{2}kt^2 } ym(t)=rm(t)xdown(t)y_m(t) = r_m(t)x_{\mathrm{down}}(t) ym(t)=Aej2πfmty_m(t) = A e^{j2\pi f_mt} fm=mBW2SFf_m = m\frac{BW}{2^{SF}} Y[p]=n=0N1ym[n]ej2πpnNY[p] = \sum_{n=0}^{N-1} y_m[n] e^{-j2\pi\frac{pn}{N}} m^=arg maxpY[p]\hat m = \underset{p} {\operatorname{arg\,max}} \left|Y[p]\right|

需要注意的是,不同 LoRa 实现采用的符号方向、FFT 符号和啁啾定义可能不同,因此程序中有时会得到:

m^=m\hat m=m

也可能得到:

m^=(Nm)modN\hat m=(N-m)\bmod N

这只是正负频率和 FFT 方向约定不同,核心原理没有变化:

峰值落在哪个 bin,就能反推出啁啾的循环偏移量。