低成本单发单收激光测距传感器方案 低成本单发单收激光测距全套方案,包括原理图、源代码、PCB、BOM、光学部分资料,结构、特殊元件数据手册及供应商联系方式,提供调试技术文档。 全套方案已成功打板验证,实现0.05~50m测量范围,精度在+/—1.5mm,激光波长635~650nm,功率《1mW。 方案预留了SPI LCD显示屏接口、按键接口、TTL串口,可通过串口助手看到测量数据,可自行DIY或者商业开发。

—— 软件功能深度解读(面向量产与二次开发)

前言

在“毫米级精度、百元级成本”的激光测距市场,传统方案往往依赖 FPGA 高速采样或双光路结构。本开源项目反其道而行:仅用一颗 24 MHz 主频的 STM32F10x、一片 12-bit ADC、一片可调 APD 高压源,就实现了 0.05~30 m 范围内亚厘米级测距。整个软件系统围绕“如何让慢速 MCU 做出高速相位仪”展开,功能密度极高。下文将以“代码本身怎么说”为主线,逐层拆解其设计哲学与实现技巧,帮助开发者快速理解、移植与魔改。


一、工程骨架:三频采样状态机

打开任意一个 .c 文件,你会发现几乎没有任何裸机框架的“废话”——没有 RTOS 任务、没有事件标志组,只有一套极简状态机 dmastatetype。它把“三频顺序采样”抽象成 7 个互斥状态:

  • DMANODATA → 空闲
  • DMAFREQ1CAPTURING → 正在采 162.5 MHz
  • DMAFREQ1DONE → 完成,等待切频
  • ……
  • DMAFREQ3DONE → 三频完毕,进入计算

状态机由 autohandlecapture() 驱动,每切换一次频率都伴随一次 PLL 重配置、150 µs 固定延时、DMA 目标地址重定向。代码里看不到任何“delay 死等”——延时用 DWT 周期计数器精确到 1 µs,CPU 在此期间可以喂狗、擦 Flash、甚至回串口指令。整套状态机占用的 ROM 不到 400 B,却保证了 50 Hz 的稳定输出帧率。


二、采样链路:让 12-bit ADC 跑出 350 kS/s

STM32F10x 官方手册把 ADC 最高速率标在 1 MS/s,但前提是 56 MHz 总线时钟、并关闭采样保持。现实是主频只有 24 MHz,还要给 DMA 留总线带宽。代码里通过三重手段“榨干”性能:

  1. 双通道“背靠背”采样
    ADC 扫描模式一次触发连续采两路:信号通道 + 参考通道。这样 Timer 更新频率 = 采样频率 /2,DMA 带宽瞬间减半。
  2. 采样时间寄存器写 1.5 周期
    initadccapture() 里你会看到 ADCSampleTime1Cycles5,再配合 12 MHz ADC 时钟,实际采样窗口 125 ns,刚好满足 APD 输出 10 MHz 带宽的奈奎斯特准则。
  3. DMA “半传输”中断被刻意关闭
    很多参考设计打开 HT 中断做双缓冲,但这里只用 TC 中断。代码在 TC 回调里直接切换状态机,省去一次中断进出,12 字节寄存器操作在 500 ns 内完成,相当于给下一次采样留出 2.5 µs 的“呼吸”时间。

三、相位提取:Goertzel 的定点化盛宴

FFT 在 Cortex-M3 上跑 256 点需要约 12 ms,而项目要求 50 Hz 帧率,显然不可接受。代码转向 Goertzel 算法——只计算目标频率那一个“bin”。但作者并未直接搬用浮点公式,而是做了三层优化:

  • 预生成 sinbuf/cosbuf:启动时一次性把 256 点的 q31 正余弦表算好,运行期只做乘法-累加。
  • 乘法规格化:把 adcvalue<<4 后再与 sinbuf[i] 相乘,保证 32-bit 累加器 256 次不溢出,同时保留 0.1° 相位分辨率。
  • 幅度用近似根号:|Z|≈max(|Re|,|Im|)+min/2,省掉 sqrtf() 的 2 k 周期,误差 <1 %,对后续 AGC 完全够用。

最终 goertzel_analyse() 跑完 256 点双通道只要 180 µs,CPU 占用 0.4 %。


四、距离解算:三频“中国剩余定理”实战

拿到三个相位 φ1,φ2,φ3 后,如何算出唯一距离?代码走了一条“先粗后细”的路线:

  1. 粗算 N
    用 191.5 MHz 与 193.5 MHz 做差频 2 MHz,波长 150 m,先把距离锁在 ±75 m 唯一区间。
  2. 细算 ΔN
    再用 162.5 MHz 与 191.5 MHz 差频 29 MHz,把 150 m 切成 5.17 m 一格,确定整数 N。
  3. 局部暴力搜索
    最后 6 格窗口内暴力比较 |d1-d2| 最小值,消掉相位噪声带来的跳格错误。

整段算法只用 16 位整形运算,没有除法、没有浮点,却能把“多值性”在 5 ms 内消得干干净净。代码注释里把这套流程叫“bruteforcedistcalculation”,名字看似粗暴,实则把计算复杂度从 O(N²) 降到 O(6×6)。


五、温度-高压双闭环:把漂移吃回去

激光测距最怕温度漂移。项目用两条闭环把“电-光-温度”耦合到一起:

  • 温度闭环
    片内 ADC 采样 NTC,二次曲线 66.843-0.0295·Raw+2.122e-6·Raw² 把原始值直接映射到摄氏度,误差 ±0.5 ℃。随后 calculate_correction() 根据温漂系数把相位偏移“反拧”回去,系数在 -40 ℃~80 ℃ 全温区标定。
  • 高压闭环
    代码在启动校准阶段扫描 DAC 输出,记录 APD 刚刚出现饱和时的电压值 apdsaturationvoltage。运行期每隔 500 ms 检查一次振幅:
    – 振幅 > 2200 LSB → 高压降 1 V
    – 振幅 < 2000 LSB → 高压回到温度-电压曲线预测值

两条闭环一软一硬,把温漂从 5 mm/℃ 压到 0.3 mm/℃ 以内,同时保证 SNR 始终 >30 dB。


六、校准与量产:一颗按钮就能下线

校准函数 dophasecalibration() 是整包代码里最“啰嗦”的部分,却也是量产最省心的地方:

  • 自动找最佳 APD 电压
    先低压 80 V 采 10 次,振幅不够就逐级升压,直到 >200 LSB 或触及 115 V 上限,记录此刻电压。
  • 三频零位写入 Flash
    每个频率采 64 次,中位值滤波后写 Flash 第 31 页,页首加 0x1234 魔术字,下次上电自动加载。
  • 饱和电压一并保存
    同样写进 Flash,换板子后无需重新手动找饱和点。

整机下线流程:装壳 → 对准 1 m 白板 → 按住按键 3 s → 蜂鸣器“嘀嘀”两声 → 校准完成,全程 8 s,无需电脑。


七、可移植与裁剪指南

代码全部寄存器版 HAL,迁移到 STM32F0/F4 只需改三处:

  1. 启动文件 startupstm32f10xmd.s 换成对应系列
  2. corecm3.h 改为 corecm0.hcore_cm4.h
  3. DWT_CYCCNT 在 CM0 不存在,可改用 SysTick 差值

若目标距离 <5 m,可砍掉三频算法,只留 191.5 MHz 单频,Flash 占用从 36 KB 缩到 12 KB,RAM 保持 8 KB 不变。


八、结语:把“简单”做到极致

通读整套代码,你会发现它几乎没有“炫技”——没有 RTOS、没有浮点、没有复杂外设,却用“最笨”的状态机、最朴素的整形运算,把激光相位测距的门槛拉到了百元以内。对开发者而言,这份代码的价值不在于“用了多少高端外设”,而在于它把每一个环节都做到了“刚好够用”:

  • 采样刚好不丢点
  • 运算刚好不溢出
  • 校准刚好不麻烦

如果你正在寻找一套“能直接装进产线”的激光测距方案,或者想在最便宜的 MCU 上体验“毫米级”的测量乐趣,那么打开这份源码,从 autohandlecapture() 开始单步跟踪吧——每一行都在告诉你:低成本并不等于低性能,关键在于是否把每一分钱都算得刚刚好。

低成本单发单收激光测距传感器方案 低成本单发单收激光测距全套方案,包括原理图、源代码、PCB、BOM、光学部分资料,结构、特殊元件数据手册及供应商联系方式,提供调试技术文档。 全套方案已成功打板验证,实现0.05~50m测量范围,精度在+/—1.5mm,激光波长635~650nm,功率《1mW。 方案预留了SPI LCD显示屏接口、按键接口、TTL串口,可通过串口助手看到测量数据,可自行DIY或者商业开发。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐