- 从事信号链设计的工作久了,对这个纯粹的应用特别感兴趣,首先是够精密,然后还可以在边缘做计算,另外还有现实的含义;那这次就设计了振动分析仪。
现在振动传感器有两个路线一个是分立的:
需要使用复杂的调理电路,而且体积较大,没有办法做到很灵活。
体积较大,不灵活;多路采集的话还得需要同步 ADC,整体数据量对于 MCU的接口和处理都是难以接受。
第二种选项就是使用 MEMS传感器,对整个系统做数字化处理;在 ADI 的产品库里面专门找到了 ADXL382,其定位非常明确:低噪声、宽带、三轴数字 MEMS 加速度计,主要面向机械振动、状态监测、结构健康监测等应用。

官方列出的典型应用就包括 Condition-Based Monitoring、Structural Health Monitoring、Seismic Imaging 和 Robotics。
在内部已经集成了完整的数字信号链系统:
先看 ADXL382 最核心的性能,指标包括:
这里有四个参数特别重要:参数
ADXL382
轴数
3
量程
±15 g, ±30 g, ±60 g
HP 模式输出
16 bit
低功耗路径
12 bit
HP X/Y 噪声密度
44 μg/√Hz
HP Z 噪声密度
55 μg/√Hz
最大默认带宽
8 kHz
HP 默认 ODR
16 kHz
HP 功耗
520 μA
ULP 功耗
33 μA
Standby
6.8 μA
FIFO
320 word
SPI
有
I2C
有另一型号
I2S/TDM
有
PDM
有
温度传感器
内置
外部同步
支持
Self-Test
支持
冲击耐受
10,000 g
工作温度
-40 °C~125 °C
44 μg/√Hz、8 kHz、16 bit
以及:
±15 g/±30 g/±60 g
这四者基本确定了它是一个宽带机械振动传感器。可测高频振动
例如:
100 Hz、1 kHz、5 kHz
机械振动。冲击
因为量程最高:
±60 g
而机械耐冲击达到:
10000 g为什么共振频率这么重要?
从手册里面查到机械共振频率:
因为一个机械加速度计本质上是二阶系统,幅频响应大致表现为:轴
共振频率
X/Y
8.3 kHz
Z
6.2 kHz

如果工作频率逼近机械共振:
f → f_r
传感器自身结构会明显放大某些频率,所以:
特别是 Z 轴机械共振:不能只看到“8 kHz bandwidth”,就把 0~8 kHz 所有点都当成天然完全平坦。
f_r,Z ≈ 6.2 kHz
而目标:
f_max = 5 kHz
已经比较接近,这就是为什么 ADXL382 内部专门做了 Equalizer。
另外在官方技术文章里面也看到:
有机械设计的一些指南,底座需要设计成金属:
所以这里传感器需要放置一个硬质,平面的座子上。
传感器的机械结构由铝制底座、金属外壳侧壁和顶部 ABS 塑料盖组成,其中金属底座负责提供足够的刚度并将被测设备的振动尽可能完整地传递到 MEMS 传感器,而 ABS 顶盖则主要用于减小金属外壳对内部 BLE 天线的屏蔽影响。
MEMS 传感器及其电源 PCB 直接布置在底座附近,使其尽可能靠近振动源,BLE 与边缘 AI 微控制器 PCB 则采用垂直安装方式,电池通过独立支架固定;底座同时预留 M6 螺纹孔,可通过螺柱或粘接方式安装到电机等被测设备上。对于这类宽带振动传感器,机械结构本身也是测量信号链的一部分,因此设计时必须重点避免结构谐振:当外部振动频率接近外壳或底座的固有频率时,结构会产生明显的共振放大,从而使 MEMS 实际测得的振动不再等同于机器本身的真实振动。
Voyager4 的目标测量带宽达到 8 kHz,因此要求机械结构在 8 kHz 以下尽量不出现明显的固有模态和共振峰;实际设计中可以通过降低外壳高度、提高结构刚度、减小不必要的悬臂和质量等方式提高固有频率,使机械共振远离目标测量频段。
(有同学复现的时候,可以从这里的结论做一些修改)简单仿真一下
我用 Python 编写一个轻量级的一维有限元(FEA)悬臂梁模型,来模拟传感器外壳的共振计算;根据文档,Voyager4 传感器的最小高度为 77 mm,直径为 46 mm,底座采用 3003 铝合金,并且底部通过 M6 螺柱刚性固定;可以将其等效为一个固定在底部的圆柱形悬臂梁。
这段代码使用了numpy和scipy,直接求解了文档中提到的核心模态方程:([K] - ωi²[M]){φi} = {0}。=== 传感器结构模态分析结果 ===
模式 1 (Mode 1) 固有频率: 5456.71 Hz
模式 2 (Mode 2) 固有频率: 34196.66 Hz
模式 3 (Mode 3) 固有频率: 95753.00 Hz
这建立了质量矩阵 [M](代表外壳和组件的质量分布)与刚度矩阵 [K](代表 3003 铝合金的结构抗变形能力)。调用eigh(K, M)实际上就是在求解特征值 ω²。
后期设计的话,可以在公式 ω = √([K]/[M]) 的指导下,改动代码里的参数来“优化”设计;将高度可以看到输出的“模式 1”频率;正如文档指出,设计人员面临的挑战是,固有频率必须大于 MEMS 加速度计测量的振动频率(8 kHz 带宽)。如果这段代码跑出来的 Mode 1 小于 8000 Hz,就意味着发生低频共振。
L = 0.077降低到0.050(50 mm);将铝合金的弹性模量E换成更硬的材料(比如钢:200 GPa),运行后发现,由于刚度提升、质量减轻,固有频率大幅上升,可以避开了机器的运行频率。FreeCAD登场
做了仿真就好了,知道了一些规律,那就使用 FreeCAD 设计一下(MAC 上面也没啥靠谱的工业设计软件):

设计一个底座先,使用 CNC。使用嘉立创 CNC平台下单

还是太方便了~详细仿真
思路是按照 Voyager4 做了一轮初步机械有限元近似(我的背景不是专业搞有限元分析的),仿真真实的目的是:
机器的真实振动,能不能不失真地传到 MEMS 加速度计。
先分析外壳和底座的固有频率、振型和模式参与因子,再看这些模态是否会影响安装在底座上的 ADXL382,所以设计的底座同时做了两种图:和文档最接近的模态振型图+真正的 von Mises 应力云图。
直接从 STEP 模型得到:参数
结果
外形 X
约 52 mm
外形 Y
约 50 mm
总高度
约 8.5 mm
实体体积
约 15332 mm³
假设 3003 铝质量
约 41.9 g

能看到几个很明显的机械设计特征:四周有较高的框架;中间是一块面积比较大的平板;四个主要安装孔分布在两侧;安装孔附近通过斜筋和外围框架连接;中间 PCB/MEMS 区域和外围固定点之间存在一定跨度。MEMS 必须尽量靠近真正的振动源
底座和中部结构采用铝;MEMS 和电源 PCB 放在底座上;而且尽量靠近被测振动源;上部 BLE/AI PCB 则竖直布置;顶盖使用 ABS 塑料,避免金属对 BLE 天线产生过强屏蔽。第一版设计

PCB 部分使用垂直安装:

塑料底座为测试品,最终会使用 CNC 底座
这也是最小桥的一个版本(后面有改动)新的设计
仿真条件
材料先按文档中的金属底座处理:
E = 69 GPa,ν = 0.33,ρ = 2730 kg/m³
也就是近似 3003 铝。
边界条件没有粗暴地把整个底面固定,而是把四个较大的安装孔周围区域看成螺栓固定区:
图里的星号是定义的 MEMS/PCB 中心测量点。底座前四阶模态
彩色模态图:
前四阶固有频率大约是:
继续往上:模态
固有频率
Mode 1
17.25 kHz
Mode 2
17.83 kHz
Mode 3
23.05 kHz
Mode 4
30.25 kHz
这一点其实相当不错:模态
固有频率
Mode 5
33.37 kHz
Mode 6
33.78 kHz
Mode 7
37.73 kHz
Mode 8
40.16 kHz
f₁ ≈ 17.25 kHz
可以看到底座本体第一阶模态已经明显高于:8 kHz第一阶是 Z 向强模态
又算了一下模式有效质量,第一阶 f₁ ≈ 17.25 kHz,在 Z 方向的有效质量参与率大约:54.4%;结果来看它不是某个“无关紧要的小凸台,其局部抖动”是一个会被 Z 向底座振动明显激励的模式。
而主要 Y 向强模态大约在:
30.25 kHz
X 向明显参与的模态则大约在:
33.37 kHz
就这个底座而言:Z 方向是目前最值得重点优化的机械方向,因为 X/Y 方向有外围框架约束,而 Z 方向最容易让中间大面积板区发生弯曲。进一步算0~8 kHz 的机械传递函数
这里假设:
ζ = 2%
并观察底座固定端的振动传到中间 MEMS 假定位置以后,三个轴的加速度误差,结果:
底座振动传递函数,在 8 kHz:
这个结果就很有意思了,如果目标也像 Voyager4 一样,要求整个:0~8 kHz,保持在大约 ±1.5 dB,那么按当前的粗模型:方向
约机械增益
X
+0.38 dB
Y
+0.76 dB
Z
+2.29 dB
Z 方向大约到:f ≈ 6.58 kHz,已经触及 +1.5 dB;不过也已经满足我的设计要求。X、Y 基本比较舒服,Z 方向开始有些紧。
静态惯性载荷分析
四个安装区域固定,在整个底座上施加 1 g 惯性载荷,得到:
就算粗暴放大到:60 g,Z 向最大应力也只有大,σ_VM,max ≈ 0.265 MPa。载荷方向
最大位移
最大 von Mises 应力
X,1 g
0.287 nm
2.39 kPa
Y,1 g
0.485 nm
3.35 kPa
Z,1 g
1.26 nm
4.41 kPa
真正的应力云图如下:
60 g Z 向 von Mises 应力云图,这里图上的变形被我人为放大了,便于看清楚;应力数值则没有按视觉比例乱放大。
频率响应图
机械部分解决了,继续看 MEMS 的性能指标:
X/Y/Z 的频率响应,可以明显看到:原始 MEMS 响应在高频端上翘;接近机械共振时增益增加;不同工作模式带宽不同;HP + Equalizer 可以把高频响应重新压平。ADXL382 最有特色的地方:两条 ADC 信号链
这是整颗芯片的核心,ADXL382 内部有两种完全不同的采样路径:高性能路径使用 16-bit DSM;低功耗路径使用 12-bit SAR;两条路径还可以同时工作,这个设计非常有意思。PCB 设计
因为现在官方的评估版小贵,而且端口做了复用,不够灵活:
严格根据数据手册的要求设计,而且上面的机械要求也是要把传感器装到一个小板子上面,确实是有必要这样设计的。
刷锡膏
放器件,开始进行回流焊;另外 ADXL380 是382 更加灵敏的版本,量程缩小一倍,其它一模一样,我也装了一颗:

然后还测了一下医疗上面的心震图:

因为有专门的测量模式,所以这套测量系统就用处很广了,可以通过换传感器核心来测量不同的数据。
说回 ADXL382
另外 ADXL382 支持七种主要模式:
带宽和模式关系由数据手册给出;对机械振动仪,直接锁定 HP,项目要求:模式
ADC
默认带宽
典型功耗
定位
Standby
—
—
6.8 μA
配置/休眠
HP
16-bit Σ-Δ
8 kHz
520 μA
振动频谱
RBW
16-bit Σ-Δ
4 kHz
350 μA
中带宽振动
LP
16-bit Σ-Δ
2 kHz
200 μA
低功耗连续振动
VLP
12-bit SAR
500 Hz
44 μA
运动检测
ULP
12-bit SAR
50 Hz
33 μA
超低功耗运动
HS
12-bit SAR
400 Hz
32 μA
心音
BW = 0~5 kHzHP 为 BW = 8 kHz,满足。
HP 模式默认 ODR 是 16 kHz
HP:f_s = 16 kSPS,默认带宽 BW = 8 kHz,也就是 BW = f_s/2
对于 0~5 kHz,非常合适,而Nyquist:f_N = 16000/2 = 8000 Hz,计算下来看在 5 kHz 仍然有 3 kHz过渡带空间。量程三挡:
±15 g、±30 g、±60 g,16-bit DSM 时:
换算公式非常简单: ±15 g = a[g] = Code / 2000,或者:a[m/s²] = (Code / 2000) × 9.80665Range
灵敏度
单 LSB
±15 g
2000 LSB/g
500 μg/LSB
±30 g
1000 LSB/g
1 mg/LSB
±60 g
500 LSB/g
2 mg/LSB
算法设计
因为要做两个链路,分别是在设备端忠实的采集数据,以及 DSP 核心分段的对数据做 FFT;另外一个就是上位机端对 RAW 数据做更加精细的分析了。
核心主控使用 MAX32655,足够小巧,足够性能强大:
但是它的显示性能不太好,而且巨大的数据流没有办法通过 BLE 和 板载的调试串口完整移走,所以我使用了未被单独指出的一路 UART 做桥接,把完整的 RAW 和 DSP 计算数据给到了 XIAO ESP32-C3,且 C3 可以做显示和更多的人机交互:
在这里,且给每个单独的系统都配备了电池,可以最大程度的保证采集任务不掉线:
后面新加入了不少外设,屏幕也做了更新,所以设计了新的壳子,在底座不变的情况下,优化了内部布局,每个器件的都有属于自己的位置:

装配细节,因为是样机就都用飞线了,正式版会重新设计一块 PCB:
皆为垂直安装,另外 C3 还接入了一块 TFT 屏幕做数据展示和上位机控制:

上位机做不同的控制时,页面会切换。
系统构成为:
ADXL382 负责振动数字采集 → MAX32655 负责 DSP 与故障特征提取
ADXL382 本身已经包含 MEMS、模拟抗混叠、16-bit 高性能 Σ-Δ 路径和数字滤波,HP 模式适合宽带振动;器件标称宽带可到 8 kHz,XY/Z 噪声密度分别约为 44/55 μg/√Hz,并支持数字校正后的宽带平坦化。 MAX32655 则是 100 MHz Cortex-M4F,带单精度 FPU、SIMD/DSP 指令、128 KB SRAM 和 DMA,很适合做这一层边缘 DSP。
设计要求实际上对应六个技术问题:
项目要求最高分析频率:题目要求
DSP问题
同步采集
固定 f_s,XYZ sample index 对齐
DC~5 kHz
Nyquist、抗混叠、传感器带宽
1024~4096 FFT
FFT 长度与 RAM/CPU
≤1 Hz 分辨率
Δf = f_s/N
主要振动频率
峰值检测、插值
故障分析
RMS、峭度、谐波、阶次、包络等
预警
基线、阈值、持续性判断
f_max = 5 kHz
Nyquist 要求:
f_s > 2f_max
因此至少:
f_s > 10 kSPS
工程上不会正好选 10 kSPS,因为还需要给抗混叠滤波器留下过渡带;另外ADXL382 在 HP 模式下可以工作在 16-bit 高性能路径,而且官方的 HP 串行输出配置对应 16 kHz ODR;它本身的宽带指标达到 8 kHz。ADXL382 推荐的工作参数
±15 g 时 ADXL382 的灵敏度是:参数
设置
模式
HP
ADC 路径
16-bit DSM
ODR
16 kSPS
量程
初期 ±15 g
XYZ
全开
EQ
开启
内部 HPF
初期关闭
内部额外 LPF
初期关闭
数据接口
SPI
MCU
MAX32655
DSP
Cortex-M4F
2000 LSB/g
即:
500 μg/LSB
因此 MCU 收到int16_t:x[n]
转换到 g:
a_g[n] = x[n] / 2000
转成 SI:
a[n] = a_g[n] × 9.80665
单位m/s²调试过程
382 是比较简单的,就是 SPI 接口,然后有 INT 引脚;最大的问题就是 ADI 的 MCU 设计电压域,默认是 1.8V,然后可以通过修改结构体里面的内容:mxc_spi_pins_t pins = {
需要修改为:
.clock = true,
.miso = true,
.mosi = true,
.ss0 = false,
.ss1 = false,
.ss2 = false,
.vddioh = false,
};mxc_spi_pins_t pins = {
MAX32655 的 GPIO 配置里有一个容易忽略的字段:
.clock = true, .ss0 = false, .ss1 = false, .ss2 = false,
.miso = true, .mosi = true, .sdio2 = false, .sdio3 = false,
.vddioh = true,
};typedef enum {
实际控制 GPIO 的输出高电平所对应的电源域,输入高低电平判定门限,内部上拉所连接的电压域;SDK 最终会操作端口的
MXC_GPIO_VSSEL_VDDIO,
MXC_GPIO_VSSEL_VDDIOH,
} mxc_gpio_vssel_t;VSSEL寄存器:case MXC_GPIO_VSSEL_VDDIO:
也就是说,同一个 P0.21 引脚,选择不同
port->vssel &= ~mask;
break;
case MXC_GPIO_VSSEL_VDDIOH:
port->vssel |= mask;
break;vssel后,虽然仍然是 SPI MOSI,但其电气特性不同。
只修改电压域并重新烧录后,就连续收到了合理且稳定的数据:raw_x = -5191
而且三轴合加速度约为:
raw_y = 1079
raw_z = 5819
x = -0.69213 g
y = 0.14387 g
z = 0.77587 g
temperature = 29.61 °Csqrt(0.692² + 0.144² + 0.776²) ≈ 1.05 g
这与静止状态下主要受到约 1 g 重力加速度相符,连续采样也只有正常噪声范围内的小幅波动软件设计
本次是使用了 ADI 推出的全新环境CodeFusion Studio™,可以快速的建立项目和配置外设:
而且是全平台支持,我这边使用 MAC 开发,可以看到这里打开了 SPI,GPIO,UART,在右边配置详细的细节

时钟树也可以配置,我比较喜欢的是寄存位的查看:
我使用了自带的一个 SPI demo 做修改,使用了ADI no-OS ADXL38x 官方驱动,后面把 no-OS 的 SPI 接口转换为 MAX32655 MSDK SPI API,并实现本板的软件片选和电压域配置。
主要文件:本工程不是代码生成器自动生成的工程,而是以 ADI MSDK 的 MAX32655 SPI 示例为基础进行集成。
SPI/
官方参考代码:
├── Makefile
├── project.mk
├── main.c
├── include/
│ ├── adxl38x.h
│ └── no_os_*.h
└── src/
├── adxl38x.c
├── adxl38x_max32655_spi.c
└── no_os_*.cADXL38x 驱动:https://github.com/analogdevicesinc/no-OS/tree/main/drivers/accel/adxl38x
ADXL38x 示例:https://github.com/analogdevicesinc/no-OS/tree/main/projects/eval-adxl38x
MAX32655 MSDK:https://github.com/analogdevicesinc/msdk
整体逻辑

SPI 和中断引脚
ADXL382 信号
MAX32655FTHR 引脚
MCU 功能
方向
MISO
P0.22
SPI1_MISO
ADXL382 → MCU
MOSI
P0.21
SPI1_MOSI
MCU → ADXL382
SCK
P0.23
SPI1_SCK
MCU → ADXL382
CS
P2.5
普通 GPIO 软件片选
MCU → ADXL382
INT0
P2.4
普通 GPIO 输入
ADXL382 → MCU
INT1
P2.3
普通 GPIO 输入
ADXL382 → MCU
VDD/VDDIO
3.3 V
传感器及数字接口电源
电源
GND
GND
公共地
电源
ADXL382 与 MAX32655FTHR 必须共地。本文中的
P2.3对应 INT1。软件片选
MAX32655 的 SPI1 硬件片选 0 是 P0.20,但本工程不使用 P0.20;P2.5 被配置为普通 GPIO,由软件控制片选:传输开始:P2.5 拉低
因此,P0.20 不需要连接 ADXL382,也不需要在 SPI 初始化中申请硬件 SS 引脚;SPI 引脚配置中所有硬件 SS 均关闭:
执行 SPI 全双工传输
传输结束:P2.5 拉高mxc_spi_pins_t pins = {
.clock = true,
.ss0 = false,
.ss1 = false,
.ss2 = false,
.miso = true,
.mosi = true,
.sdio2 = false,
.sdio3 = false,
.vddioh = true,
};SPI 参数
当前接口参数如下:
SPI1 初始化使用 MSDK API:参数
配置
SPI 控制器
MAX32655 SPI1
工作模式
Controller/Master
SPI Mode
Mode 0,CPOL=0、CPHA=0
数据宽度
8 bit
位序
MSB first
总线宽度
Standard,单线 MOSI/MISO
测试频率
100 kHz
片选
P2.5 软件片选,低有效
传输方式
阻塞式全双工传输
MXC_SPI_Init(MXC_SPI1, 1, 0, 1, 0, speed_hz, pins);
其中
MXC_SPI_SetDataSize(MXC_SPI1, 8);
MXC_SPI_SetWidth(MXC_SPI1, SPI_WIDTH_STANDARD);
MXC_SPI_SetMode(MXC_SPI1, MXC_SPI_MODE_0);
MXC_SPI_HWSSControl(MXC_SPI1, 0);MXC_SPI_HWSSControl(MXC_SPI1, 0)禁用硬件 SS 控制,P2.5 完全由 GPIO 软件控制。ADXL382 SPI 协议
ADI 官方 ADXL38x 驱动采用如下 SPI 命令格式。读取寄存器
发送缓冲区格式为:[写命令] [数据0] [数据1]...软件片选时序
每一次完整寄存器访问保持一次连续的片选:MXC_GPIO_OutClr(MXC_GPIO2, MXC_GPIO_PIN_5);
多字节读取期间不能在命令字节和数据字节之间释放 CS。
MXC_SPI_MasterTransaction(&req);
MXC_GPIO_OutSet(MXC_GPIO2, MXC_GPIO_PIN_5);
MSDK 负责 MAX32655 相关功能:Cortex-M4 启动和系统时钟;MAX32655FTHR 板级支持;GPIO 引脚复用和电压域;SPI1 控制器;UART 和printf;GCC 编译、链接、HEX 生成;OpenOCD 下载和复位。
编译时板级配置应使用:TARGET=MAX32655
BOARD=FTHR_Apps_P1ADI no-OS ADXL38x 驱动层
官方adxl38x.c/.h提供:ADXL380、ADXL382、ADXL384 设备识别;SPI/I2C 通信抽象;寄存器读写;软件复位;量程和工作模式配置;XYZ 加速度和温度读取;数据换算、自检、中断等功能。
ADXL382 应使用对应的设备类型:
ADXL382 的量程枚举为:.dev_type = ID_ADXL382
ADXL382_RANGE_15G
在 ±15 g 档位,官方驱动定义的灵敏度为:
ADXL382_RANGE_30G
ADXL382_RANGE_60G#define ADXL382_ACC_SENSITIVITY 2000 /* LSB/g */
因此 ±15 g 时,原始加速度转换为 g 可使用:accel_g = (double)raw / 2000.0;
其他量程还需要应用相应的量程倍数,优先使用官方驱动提供的转换函数,避免在应用层重复硬编码灵敏度。MAX32655 平台适配层
src/adxl38x_max32655_spi.c实现 no-OS 所需的接口:no_os_spi_init()
调用关系如下:
no_os_spi_write_and_read()
no_os_spi_remove()main.c
│
├─ ADXL38x 官方驱动 API
│ │
│ └─ no_os_spi_write_and_read()
│ │
│ ├─ P2.5 拉低
│ ├─ MXC_SPI_MasterTransaction()
│ └─ P2.5 拉高
│
└─ printf() → MAX32655 UART → USB 串口初始化流程
采用以下顺序:初始化 P2.5,并先将 CS 拉高;将 INT0、INT1 配置为 VDDIOH 输入;等待传感器电源稳定;初始化 SPI1,选择 Mode 0、8 bit、MSB first 和 VDDIOH;读取并确认 ADXL382 设备标识;执行软件复位并等待复位完成;配置 ADXL382 量程;使能 X、Y、Z 和温度通道;设置工作模式;周期读取数据并通过串口输出。
ADXL382 初始化参数示例:struct adxl38x_init_param init = {
量程配置示例:
.comm_init.spi_init = {
.device_id = 1,
.max_speed_hz = 100000,
.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST,
.mode = NO_OS_SPI_MODE_0,
.chip_select = 5,
},
.comm_type = ADXL38X_SPI_COMM,
.dev_type = ID_ADXL382,
};adxl38x_set_range(dev, ADXL382_RANGE_15G);
8 kHz 实时输出与 ESP32-C3 USB 桥接实测
第一次写的时候使用了 8 kHz 的量程当前数据链路
ADXL382
这里使用的是 MAX32655 的 UART2,不是连接 DAPLink 的 UART0:
└─ SPI1 2 MHz
└─ MAX32655(8 kHz 读取,32 组 XYZ/包)
└─ UART2 921600 8N1,P1.1 TX
└─ XIAO ESP32-C3 D3/GPIO5 RX
├─ USB Serial/JTAG 原样二进制转发到电脑
└─ ST7789 显示链路状态、速率和最新 XYZ信号
MAX32655FTHR
XIAO ESP32-C3
说明
MAX → C3 数据
P1.1 / UART2_TX
D3 / GPIO5
已实接并通过测试
C3 → MAX 命令
P1.0 / UART2_RX
D10 / GPIO10
当前可选,数据转发不依赖
地
GND
GND
必须共地
二进制协议
每包固定 206 字节,包含 32 组三轴样本:offset size 字段
数据量计算:
0 2 sync = 0xA55A(线上字节 5A A5)
2 1 version = 1
3 1 type = 1
4 4 first_sequence,little-endian
8 2 sample_count = 32
10 2 dropped_total
12 192 32 × (int16 x, int16 y, int16 z),little-endian
204 2 CRC16-CCITT,初值 0xFFFF8000 sample/s ÷ 32 sample/packet = 250 packet/s
因此 921600 baud 对当前固定包协议留有约 44% 的线路余量,能够承载ADXL382 的 8 kHz XYZ 原始数据,15200 baud 则远远不够。
250 × 206 = 51,500 payload byte/s
UART 8N1 线上开销:51,500 × 10 = 515,000 bit/s
921,600 baud 理论占用率约 55.88%测试结果
测试方法:电脑持续打开 C3 USB 串口,先排空旧数据;通过 SWD 对 MAX32655;跳过 1.2 秒启动阶段;随后连续抓取 12 秒。接收端按同步字、版本、类型、样本数及 CRC16 校验切包,并检查相邻包的first_sequence。测试日期 2026-09-13
在 12 秒实测窗口内,MAX32655、UART2、ESP32-C3 USB Serial/JTAG桥接能够完整传出约 8.05 ksample/s 的 ADXL382 三轴数据;CRC、序号连续性和传感器端丢样计数三项均未发现丢包。
抓取时间 12.006482 s
USB 收到原始字节 622,592 byte
CRC 正确的完整数据包 3,021 packet
错误同步字候选 0
首包 first_sequence 9,408
末包 first_sequence 106,048
相邻包次数 3,020
序号增量恰好为 32 3,020 / 3,020
链路缺失样本 0
序号倒退/源端复位 0
MAX dropped_total(首包→末包) 0 → 0
有效包速率 251.614 packet/s
折算样本速率 8,051.651 sample/s
有效二进制负载 51,832.5 byte/s
按实收字节折算 UART 占用率 56.27% @ 921600 8N1链路压力
通过 SWD 读取运行计数器:累计采样 1,640,810
约连续运行 205 秒仍无采样调度丢失。
调度 Tick 1,640,810
错过采样周期 0
SPI 错误 0
UART 丢弃样本 0
已发送数据包 51,274
UART 是现有链路里最接近上限的环节,但仍有约 44% 理论余量。链路
当前数据量/负载
状态
ADXL382 → SPI1
每样本 7 字节,2 MHz,理论总线占用约 22.4%
余量较大
MAX32655 CPU
100 MHz,每样本周期 125 µs
当前零超期
MAX → C3 UART
51,500 B/s,约 515 kbps
占 921600 baud 的 55.9%
C3 → USB
实测约 51.8 kB/s
压力很小
C3 → ST7789
每秒刷新约 110 kB,40 MHz SPI
约 2.2% 屏幕总线时间
BLE
目前只有控制和状态
负载可忽略
DSP性能
首先要明确一点,MAX32655 没有独立的专用 DSP 核;它的“DSP 性能”来自 100 MHz Arm Cortex‑M4F 的 DSP 指令扩展和单精度浮点 FPU。
官方硬件配置:
官方资料确认其为 100 MHz Cortex‑M4F,并有一个专门卸载 BLE 时序处理的 RISC‑V 协处理器;理论上每秒约有 1 亿个 CPU 周期;实际处理量取决于数据类型、缓存、访存和中断。项目
MAX32655
主 CPU
Arm Cortex‑M4F
主频
100 MHz
DSP 指令
单周期 MAC、饱和运算、SIMD 等
FPU
FPv4-SP,硬件单精度浮点
Flash
512 KB
SRAM
128 KB
指令缓存
16 KB
BLE 辅核
32 位 RISC‑V,负责卸载 BLE 时序任务
对于当前 8 kHz ADXL382:CPU 时钟 100 MHz
当前 SPI 每次读取 7 字节、频率 2 MHz,纯线路时间约为:
采样率 8 kHz
每个采样周期 125 µs
每个采样周期 CPU 周期 12,500 cycles7 × 8 ÷ 2 MHz = 28 µs
因此一个采样周期理论上剩余:125 - 28 = 97 µs,约 9,700 CPU cycles/sample
实际还需要扣除 SPI 驱动、CRC、打包、UART 和中断开销,不过目前实测超过 164 万次采样:错过采样周期 0
当前还有处理余量。
SPI 错误 0
UART 丢样 0升级到16k SPS 采样率
需要做的修改是:SysTick_Config(SystemCoreClock / 16000U)
另外SPI 从 2 MHz 提升到 8 MHz,UART2 和 C3 UART1 改成 2 Mbps;改用固定 224 字节协议,加入双缓冲。(以及启用 FIFO)
字节协议:Header 28 bytes
数据类型:
Payload 192 bytes
CRC32 4 bytes
Total 224 bytes0x01 RAW_XYZ
原始数据固定:
0x02 STATUS
0x03 CONFIG
0x04 FAST_FEATURES
0x05 SPECTRUM_FEATURES
0x06 ALARM
0x07 SPECTRUM_CHUNK32 × int16 XYZ = 192 bytes
ADXL382 配置为 HP 模式、XYZ、±15 g、开启 FIFO 的 Stream 模式,96 words 水位,即 32 组三轴;SPI 读取 193 字节 DMA burst。
在 20.014 秒 的模式测试中,成功采集 10,016 个有效 V2 帧(320,512 个有效样本),实收速率达 16,014.69 SPS,且 CRC、缺失样本、序号中断、调度遗漏及 UART 错误均为 0,最后一组 XYZ 轴数据正常为(-205, 488, 1912),期间 MAX32655 内部 SWD 计数显示 10 秒时基为 160,024、FIFO 取样 159,360、UART 完成 4,979 帧。内部DSP计算
建立 4096 点环形采样缓冲,实现快速时域特征(去直流、RMS、峰值、峰峰值、波峰因子、峭度。)
数据帧里面原始 XYZ 数据仍保留,DSP 特征作为附加包发送;每 4096 个样本计算一次统计与频谱特征,还没有把完整频谱曲线传给电脑,数据路径是:ADXL382 以 16 kSPS 采样 → SPI DMA 每次读取 32 组三轴数据 → 原始数据组成实现 4096 点 Hann 窗 + RFFT,对应:频率分辨率3.90625 Hz,奈奎斯特频率8 kHz,项目关注频段0–5 kHz
0x01帧经 UART2 以 3 Mbaud 发给 C3;同一批样本也送进 DSP 双缓冲。4096 点对应 256 ms 的数据,频率分辨率是
16000 / 4096 = 3.90625 Hz/bin
32655 对 X、Y、Z 各轴分别计算:
时域部分,先求均值、再去均值后(去直流)的 AC RMS、AC 绝对峰值、峰峰值、峰值因子(峰值/RMS)、峭度;这些数值目前以传感器原始 LSB 为单位,尚未统一转换成 g。
频域部分是先去均值并乘 Hann 窗,再用 CMSIS-DSP 做 4096 点实数 FFT;只搜索约 0–5 kHz,输出每轴的主峰频率、主峰幅值,以及五个频带的 RMS;主峰频率还使用相邻 bin 做抛物线插值;频域幅值按代码中的0.0005 g/LSB换算。
计算时用两组4096 × 3的int16缓冲交替填充;每读取一个 32 样本包,只推进一个 DSP 步骤;均值和统计每步处理 512 点,功率谱每步处理 256 个 bin,FFT 则是其中单独的一步。使用SWD评估DSP计算性能
调试的时候以build/SPI.elf的符号地址解释 RAM 计数器;使用板载 DAPLink CMSIS-DAP,经 OpenOCD SWD 在 CPU 运行时读取;未暂停、复位或重刷 MCU。
本轮结果(20.1441 秒):
窗口内 DSP 块数与采样量一致(322,688 / 4,096 ≈ 78.78),没有观察到 DSP 跟不上采集的迹象;特征帧数也恰好是 DSP 块数的两倍。指标
观察值
采集样本增量
322,688
平均采集速率
16,023.7 SPS
DSP 块增量
79
DSP 完成速率
3.922 块/s
理论块速率(16,000 / 4,096)
3.906 块/s
特征帧增量
158(每块 2 帧)
UART 已完成帧增量
10,246
g_missed_deadlines增量0
g_fifo_not_ready增量41
g_dsp_max_ticks终值61(开机以来最大;非本窗口最大)
g_fifo_not_ready是定时轮询时 FIFO 尚未凑够 96 个字的次数,不等同于丢样;SWD 采样本身有轻微扰动,采样间隔和速率均按主机单调时钟计算;约 0.5 秒的块速率会因整数块量化而呈阶梯。
使用DWT更加精细的评估DSP性能
给 DSP 各计算阶段加 DWT 周期计数,记录每阶段累计周期、调用次数和最大单次周期,再通过 SWD 读取并用 Python 出图;这样能把 FFT 与均值、时域统计、频带计算分开评估Window 20.146s, core 100.0 MHz, counter overhead 16 cycles
三轴每个 4096 点块的 DSP 总测得约 20.28 ms,其中 FFT 约 11.38 ms;折合测试窗口约 7.95% 的核心时钟时间。采样仍为约 16.02 kSPS、漏期增量 0。
Sampling 16022.1 SPS; 79 DSP blocks; 158 features; missed +0; FIFO wait +41
setup 237 calls mean 0.57 us max 0.77 us core time 0.00%
mean 1896 calls mean 53.52 us max 54.05 us core time 0.50%
moments_hann 1896 calls mean 240.94 us max 244.35 us core time 2.27%
fft_4096 237 calls mean 3793.50 us max 3793.77 us core time 4.46%
power_bands 1185 calls mean 121.38 us max 121.69 us core time 0.71%
finalize 237 calls mean 4.79 us max 4.86 us core time 0.01%
Total measured DSP core time: 7.95%
同一窗口原始数据 322,784 样本,实际采集率 16,022.1 SPS;DSP 完成 79 块,特征帧 158,漏期增量 0,FIFO 暂未凑齐增量 41;三轴 4096 点块的理想周期为 256 ms;平均 DSP 耗时为周期的约 7.9%。阶段
调用次数
单次平均
开机以来单次最大
三轴每块合计
窗口核心时间占比
初始化步骤
237
0.57 µs
0.77 µs
<0.01 ms
<0.01%
均值,每轴 8×512 点
1,896
53.52 µs
54.05 µs
1.28 ms
0.50%
中心矩、峰值、Hann 窗,每轴 8×512 点
1,896
240.94 µs
244.35 µs
5.78 ms
2.27%
4096 点实数 FFT,每轴一次
237
3,793.50 µs
3,793.77 µs
11.38 ms
4.46%
功率谱/频带,每轴 5 个分片
1,185
121.38 µs
121.69 µs
1.82 ms
0.71%
峰值插值及频带结果
237
4.79 µs
4.86 µs
0.01 ms
0.01%
合计
20.28 ms/块
7.95%
实时性重点不只是平均负载:单次 FFT 约 3.79 ms,超过 32 XYZ 包对应的 2 ms 时间,所以采集会暂时靠 ADXL382 FIFO 缓冲,之后追赶。
频谱数据解析
从 C3 USB 链路抓一帧最新的0x05频谱特征,按三轴主峰和五个频带分解:crc 59
block 4227 first_seq 17313792 bin_hz 3.90625
X peak_hz 268.3132019042969 peak_g 0.0009868545457720757 bands_g_rms (0.0013011862756684422, 0.0018773552728816867, 0.0019023217028006911, 0.0027426122687757015, 0.004297043662518263)
Y peak_hz 770.075439453125 peak_g 0.001155573409050703 bands_g_rms (0.001327782985754311, 0.0020827981643378735, 0.0023854034952819347, 0.002570707118138671, 0.004741341806948185)
Z peak_hz 268.40802001953125 peak_g 0.0017939069075509906 bands_g_rms (0.001608308870345354, 0.002986389212310314, 0.0031467906665056944, 0.003475544275715947, 0.005687463562935591)0 (4275, 17510400, 3.90625, 4266.13525390625, 3763.20166015625, 252.0399627685547, 0.0012536837020888925, 0.0013949715066701174, 0.0024219087790697813, 0.0010756059782579541, 0.0017819652566686273, 0.002098222030326724, 0.002652243245393038, 0.0045760259963572025, 0.0012079484295099974, 0.0019669109024107456, 0.0024646390229463577, 0.0029253715183585882, 0.004754867870360613, 0.0013006648514419794, 0.0034214667975902557, 0.0032509721349924803, 0.0036392351612448692, 0.006086269393563271)
这些数据是 MAX32655 从每个 4096 点数据块中提取的“频谱特征摘要”,有效频谱帧里面是:DSP 块:4275
首样本序号:17,510,400
FFT 点数:4096
采样率:16 kSPS
频率分辨率:3.90625 Hz
分析范围:0–5 kHz
五频带 RMS:轴
主峰频率
主峰幅值
X
4266.14 Hz
0.001254 g
Y
3763.20 Hz
0.001395 g
Z
252.04 Hz
0.002422 g
每个频谱帧是固定 V2 协议中的频带
X
Y
Z
0–200 Hz
0.001076 g
0.001208 g
0.001301 g
200–500 Hz
0.001782 g
0.001967 g
0.003421 g
500–1000 Hz
0.002098 g
0.002465 g
0.003251 g
1–2 kHz
0.002652 g
0.002925 g
0.003639 g
2–5 kHz
0.004576 g
0.004755 g
0.006086 g
0x05类型:block_sequence
有效负载 96 bytes,整个线上帧仍是固定 224 bytes;如果想在电脑上画传统的完整频谱曲线,需要把 0–5 kHz 的 1280 个 bin 分片发送。
first_sample_sequence
bin_width_hz
peak_frequency_hz[3]
peak_amplitude_g[3]
band_rms_g[3][5]为什么不能算出 1 Hz 的分辨率?
项目的一点核心数学矛盾是 FFT 点数和 1 Hz 分辨率,DFT/FFT 的频率间隔:
Δf = f_s/N
现在:
f_s = 16,000 Hz
于是:
所以:FFT 点数 N
Δf
数据时间长度
1024
15.625 Hz
64 ms
2048
7.8125 Hz
128 ms
4096
3.90625 Hz
256 ms
8192
1.953125 Hz
512 ms
16384
0.9765625 Hz
1.024 s
N = 4096
时只能得到:
Δf = 3.90625 Hz
达不到 1 Hz,所以在算法里面频域相关的内容以这个为准;emmmm,其实也不是算不出,而是当前 32655 固件只用 4096 点做 FFT;在 16 kSPS 下,频率 bin 间距是16000 ÷ 4096 = 3.90625 Hz,这一块数据只覆盖 256 ms。
要达到约 1 Hz 的 bin 间距,需要观察约 1 秒:16,000 点 DFT 的理论间距 1 Hz;16,384 点 FFT 间距约 0.977 Hz,数据时长 1.024 秒。
现有链路仍持续把 16 kSPS 三轴原始数据传到电脑,所以最直接的做法是:32655 保持当前实时特征计算,电脑端累积至少 16,384 点后做约 1 Hz 频谱,不必改采样驱动或传输协议。当前固件之所以没直接改成 16,384 点,主要是 32655 的 SRAM:现有三轴双缓冲和浮点 FFT 缓冲已占用较多内存,当前固件 SRAM 占用约 80%;把整套缓冲扩大四倍会超过板上 128 KiB SRAM。FFT 后补零可以让曲线更平滑、峰值读数更细,但不能凭空获得 1 Hz 的真实分辨能力。
简单来说就是这个采样率下,需要的内存比较多,现在 MCU 满了,但是可以到电脑端处理。但是还要区分“bin 间距约 1 Hz”和“可靠分开相距 1 Hz 的两个频率”:后者受 Hann 窗泄漏影响,通常需要更长的观测时间。
实测结果
因为附近没找到工业的场景,在电梯里面做了测试:
上下楼来回测试,可以看到停顿过程:
还有骑电动车通过颠簸路段的测试:

上位机

(看视频)后记
感谢硬禾和 ADI 举办的活动,可以体验到一流公司的一流产品,活动中也学到很多(下次还来~),另外也感谢俺帅气B 人的设计师,外壳和 CNC 件均是他设计的,包括宣传视频,这里摇个花手。
内容介绍
内容介绍
软硬件
软件
工具
电路图
附件下载
SPI_副本.zip
主控代码
TFT-32655.zip
ESP32-C3+屏幕
FmiVtnnY5cMQhpVnS-5azHMVk4dU
团队介绍
专业信号链设计师为您服务~
评论
0 / 100
查看更多
猜你喜欢
制作FPGA电子琴1. 存储一段音乐,并可以进行音乐播放,
2. 可以自己通过板上的按键进行弹奏,支持两个按键同时按下(和弦)并且声音不能失真,板上的按键只有13个,可以通过有上方的“上“、”下”两个按键对音程进行扩展
john
2908
2026 ADI CodeFusion 竞赛 - 基于MAX32690制作简易频谱仪该项目使用了MAX32690,实现了简易频谱仪的设计,它的主要功能为:使用ADC 通过 DMA 进行高速数据采样,做FFT实现频谱计算,在 TFT LCD 进行实时频谱图的展示。
姜小豆
17
2026 ADI CodeFusion 竞赛 - 小型旋转机械的边缘振动监测与状态识别系统该项目使用了MAX32650FTHR、BMI160,实现了识别旋转机械状态和环境监测的设计,它的主要功能为:加速度计检测电风扇的关闭、开启、异常状态,并通过ESP-12F上报到上位机。
scgummy
55