EIT电阻抗断层成像下位机逻辑及二次开发
下位机逻辑
模块一:电极拓扑与查找表
定义了16电极EIT的相邻激励和相邻测量模式。
static const uint8_t mux_current_table[][2]={{1,2}, {2,3}, ... {16,1} };
static const uint8_t mux_voltage_table[][2]={{1,2}, {2,3}, ... {16,1} };
这是一个二维数组:
电流激励为外循环,有16次,第一次正信号给编号1,负信号给编号2,第二次正信号给编号2,负信号给编号3,以此类推直到{16,1} 完成一次外循环。
内循环逻辑类似,当给到一次电流激励时,要采集16次电极电压,例如给到{1,2}电流激励,那么电压采集按照以上逻辑循环16次,完成一次电压采集。
完整的一次电压采集,包含16*16=256次,所以下位机每次打包传输给上位机的数据有256个。
整体而言即硬件内部预置了符合相邻模式协议的电极对映射表,通过查表法快速索引当前的激励端与测量端,实现了 16 电极的循环扫描。
模块二:微秒级延时控制
标准的 HAL_Delay 只能提供毫秒(ms)级延时,对于 EIT 的开关切换来说太慢(会降低帧率),而简单的 for 循环延时又不准。这里利用了 Cortex-M 内核自带的 DWT 寄存器中的周期计数器。它能以 CPU 主频(120MHz)进行计数,提供极高精度的延时。用于多路复用器切换后的建立时间控制,确保模拟信号稳定后再采样。这样既不影响成像,同时也能提高帧率。
模块三:DDS 信号生成
DDS 原理:这是一个软件直接数字频率合成(DDS)的波形表生成函数。因为 STM32 的 DAC 是单电源供电(0~3.3V),无法输出负电压。代码通过 sin(x) + 1 将正弦波整体抬升,使其完全位于正电压区间。将一个完整的正弦周期分割为 256 个点,计算每个点的数字量存入 SineData 数组,供 DAC DMA 使用。在不占用 CPU 资源的情况下持续输出 19kHz 的正弦激励信号。
计算每个点之间的相位步进,NPoints=256,生成带直流偏置的正弦波,
sin(radian) 范围 -1 到 1 +1.0 后范围从 0 到 2, VMaxRange / 2.0 调整幅值,将电压值转换为 12-bit DAC 数值 (0~4095),3.3 是参考电压 Vref。
模块四:数据解调与处理
去直流,ADC 采集的是抬升后的正弦波(中心在 1.65V 左右,对应数字量 2048)
减去 2048 还原为以 0 为中心的交流信号数字量,再平方累加,求均方根,进行物理量转换,返回电压有效值。这是标准的时域 RMS 算法。相比 FFT,计算量更小,代码中硬编码了 2048.0f 作为直流偏置点。这意味着硬件电路的信号中心必须精确对准 ADC 量程的一半。
采样时序控制:利用 TransferComplete 标志位(在中断回调 HAL_ADC_ConvCpltCallback 中置 1)实现了 CPU 与 ADC 硬件的同步。只有采满了 128 个点,才开始计算。原本是256个点,但对于16电极EIT设备,128个点已经能够满足精准度,并且能显著降低计算量,提高我们连续成像所需要的帧率。
模块五:全扫描流程
外层循环:遍历 16 组激励模式,切换激励电极对,固定50us的等待时间,等待恒流源和多路复用器稳定,避免开关噪声。
内层循环:遍历 16 组测量模式,切换电压测量电极对,定义测量建立延时 (50us)等待仪表放大器前端稳定,再执行采样与解调,最后进行数据打包,将浮点电压值转换为微伏(uV)整数,便于传输且保留精度。
嵌套循环: 典型的 EIT 数据采集逻辑,16×16=256 次测量。
时序关键: 这里的 tm_delay_us(50) 是保证数据质量的关键。如果没有这个延时,采集到的数据会包含大量的开关尖峰噪声,造成成像错误。
模块六:主程序入口
先初始化高精度延时,再进行ADC校准,消除内部偏差,进而启动激励源DAC,生成波形表,启动DAC触发定时器,开启DAC DMA循环输出,形成连续正弦波,最后进行主循环:
检查是否有开始采集的标志,由USB接受中断置位,最后清楚标志,执行一次完整的256次扫描。通过 USB 虚拟串口将数据发送给上位机tx_buff 大小 = 256 * 4字节 = 1024 字节。
最后该设备除了电源指示灯之外还有一个心跳灯,指示系统存活。
该设备具有信号链同步: 采用阻塞式同步采样。在 do_one_sample 中,CPU 启动 ADC DMA 后挂起等待,直到 128 个数据点全部进入内存,保证了数据处理的实时性与完整性。
数字解调: 实现了软件 RMS 检波。读取 ADC 原始值后,软件去除 1.65V 直流偏置,计算交流分量的有效值。相比硬件检波电路,这种方式减少了模拟器件,且通过平均作用提高了信噪比。
通信协议:在接收到上位机指令后触发一次全扫描。数据被格式化为 32位无符号整型(微伏单位),一帧包含 256 个测量点,通过 USB 批量传输端点一次性上传。
下位机二次开发:
修改的目的都在于提升帧率,即降低单次完整采集256个数据所需要的时间。从“保守调试模式”转向“高性能实时模式”。大幅提高扫描速度,增强信号强度,简化计算逻辑以提升效率。主要从以下四个方面进行改进:
1.扫描时序:从毫秒级到微秒级
以上是未改动的扫描时序逻辑,即慢速高稳模式,采用全矩阵采集,代码采用嵌套的双层循环结构,
外层循环 (i from 0 to 15):控制激励遍历 16 组电流注入模式。每次循环调用 select_current_electrode_pairs,将恒流源切换到指定的电极对。
内层循环 (j from 0 to 15):控制测量在当前激励模式下,遍历 16 组电压测量模式。每次循环调用 select_voltage_electrode_pairs,将仪表放大器的输入端切换到指定的电极对。
数据总量:单帧图像包含 16×16=256 个测量点。
①帧间延时 HAL_Delay(20):
在开始一帧新的 256 点扫描前,暂停 20ms。这是为了让上一帧的USB数据传输完毕,让电源电压在大负载工作后恢复稳定。
②激励建立延时 HAL_Delay(4):位置在切换电流激励电极之后。
作用:等待 4ms。给恒流源和电极接触界面足够的建立时间。确保了恒流源电路完全进入稳态,消除了负载突变引起的瞬态震荡。如果延时不够,会导致电流未稳时就开始测量,造成数据偏差。
③测量建立延时 HAL_Delay(2):位置在切换电压测量电极之后。
作用:等待 2ms。这是为了让模拟前端(仪表放大器 AD8421 + 抗混叠滤波器)的输入电容完成充放电。如果没有这个延时,上一通道的残余电压会影响当前通道,导致图像出现严重的伪影。
④采样后延时 HAL_Delay(2):位置在 do_one_sample() 之后。
作用:限制数据吞吐率,防止数据产生过快导致下位机发送缓冲区溢出或上位机处理不过来。
以上是修改之后的扫描时序逻辑。即高速实时成像模式。
将基于系统滴答定时器的HAL_Delay()删去,因为其最小单位是1ms,会导致为了等待CPU稳定,被迫浪费大量CPU时间。
改为使用tm_delay_us(),基于 DWT 计数器,最小单位是1us。并通过反复实验验证将等待时间控制在50us,既满足硬件建立时间的要求,又消除了不必要的等待时间。
①将采集完一帧图像数据的等待时间从20ms改为了1ms,因为系统处理能力足够强,不需要等待这么长休息时间就可以接着采集下一帧的数据了。
②激励切换建立时间从4ms改为了50us,因为对于该设备的所有运放,其建立时间远远小于4ms,50us既能保证信号稳定,又不会浪费时间。
③测量切换建立时间从2ms到50us,因为经验证50us足以让多路复用器和仪表放大器前端的寄生电容充放电完毕,不会使图像出现伪影,且缩短了单个数据获取时间。
④将采样后延时直接注释掉,采完后立即进入下一次循环,因为数据已经存入tx_buff中,不需要等待。并且将每次激励建立前的固定等待2ms时间也注释掉,因为这并不影响采集数据,反而会增加延时。
延时对比:
T单帧=t帧头+N激励*[t激励前等待+t激励建立+N测量*(t测量建立+t采样+t采样后等待)]
t采样指的是单次 ADC 采集与数据处理的耗时。
所以Told=1140ms+256t采样
Tnew=14.6ms+256t采样
优化后,系统的固定死区时间从1140ms降至14.6ms。此时,总耗时主要取决于 ADC的物理性能,系统架构不再是瓶颈。
这是目前下位机的数据,帧率最高在8.9FPS,ADC计算占主要部分。
- 采样深度:从 512 点降至 128 点
代码对比:
旧版: #define FFT_LENGTH 512
新版: #define FFT_LENGTH 128
基于系统时钟配置,ADC采样率设定为1Msps(1us/点),激励信号频率由 TIM7 (10MHz) 和点数 (256) 决定——39.06 kHz。信号周期Tsig约为25.6us.
采样时间窗口:
旧版 (512点):耗时 512×1μs=512μs。
新版 (128点):耗时 128×1μs=128μs。
而周期数=采样窗口/信号周期
所以旧版覆盖20个完整信号周期,新版恰好覆盖了 5 个完整的正弦波周期。且计算 RMS 时如果采样窗口涵盖的是整数个周期,其计算误差是最小的。对于一个稳定的正弦波,测量5个周期算出来的有效值和测量 20 个周期算出来的有效值,在精度上几乎没有区别。并且能在数据量减少 75% 的情况下,测量精度依然维持在高水平。单次采集耗时缩减至128μs,单帧累计节省采样时间约 98.3 ms。
- 激励信号幅值:从 0.2V 增强至 2V
代码对比:
旧版: GenSineWaveData(0.2);
新版: GenSineWaveData(2);
大幅提升信噪比,之前烧录的 0.2V 信号太微弱,经过阻抗衰减后,到达接收端的信号可能被淹没在底噪中,或者 ADC 采集到的有效位数太少。使得成像不准确,且电导率的变化与实际严重不符,提升到 2V 可以充分利用 DAC 和 ADC 的动态范围(0-3.3V),使测量结果更精准,成像更准确,且与原始版本进行对比,成像精准度基本不变,并没有受高速模式下的影响。
- RMS 算法:从“库函数”回归“手动计算”
旧函数是先转电压,再调用ARM DSP库函数,在循环里进行了繁重的浮点乘除,消耗大量的CPU周期。
而修改后的是手动编写了平方和逻辑,优化计算流程,减少循环内的浮点运算,先直接处理原始ADC数据,只在最后做一次电压转换,运算量大幅减少。
上位机逻辑以及二次开发将在下一篇详细介绍~
