- 引言
- 电路设计
- 软件设计
- 采集HYS1254数据
- 软件滤波算法
- 换算压力为ADC采样值
- 实验过程
- 数据可视化
- 优化电路
- 使用软件滤波
- 降低ADC的采样速率
- 使用独立的供电电源
- 再次调整滤波算法
- 验证总结
- 参考文献
引言
NPI提了需求,需要验证使用友商SDADC芯片和MM32L0130微控制器集成的一个系统应用方案。
本文参考 CN-0216 Precision Weigh Scale Design 方案对使用MM32L0130和HYS1254的应用方案进行验证,使用灵动微电子MM32L0130
微控制器、健芯半导体的HYS1254
高精度24位分辨率的Sigma Delta ADC,以及圣邦微电子SGM8967-1
运放前端,实现了高精度电子秤的方案,记录了尝试使用各种方法消除采样值抖动问题,总结了目前验证过程中遇到的问题。
只是比较遗憾,最终验证方案性能未达预期,有点小小的翻车。。。
电路设计
设计电子秤方案系统,使用了搭载MM32L0136C7P
微控制器的EVB-L0136
开发板,使用HYS1254
SDADC构成的采样电路采集来自压力传感器输出的电信号,实现测量压力的功能,以演示高精度ADC的分辨率。如图x所示。试想,能不能测量风吹过的感觉呢?
figure-system-arch-diagram
图x 电子秤原型系统框图
设计称重信号采集电路,如图x电路,使用了HYS1254
SDADC和SGM8967-1
运放前端两个主要的分立元件搭建而成。
figure-hys1254-schmatic
图x HYS1254及采样电路
根据HYS1254
手册中的建议,在采样电路中使用OPA350UA/2K5
向HYS1254
提供4.096V
的参考电压ADC_VERF
,如图x所示:
figure-OPA350UA-schmatic
图x 使用OPA350UA/2K5的参考电压源电路
最终搭建电路系统实物,如图x所示。
figure-system-hardware
图x 电子秤验证方案实物
软件设计
采集HYS1254数据
根据HYS1254
数据手册中对传输ADC采样值的数字通信信号时序描述,如图x所示。
figure-hys1254-signal-timing-seq
图x HYS1254读数信号时序图
这里特别注意,MCU每次使用引脚中断捕获到DRDY的下降沿(一次ADC转换完成)后,需要等一段时间,才能由MCU驱动SCLK时钟,从DOUT引脚串行捕获ADC采样结果的值。
使用GPIO模拟时序,实现读取一次采样值代码如下:
/* read a sample value from hys1254. */
int32_t app_hys1254_read_adc_value_raw(void)
{
int32_t adc_val = 0;
/* wait to enter hys1254 data cycle. */
for (uint32_t delay = (CLOCK_SYS_FREQ / APP_ADC_CLK_FREQ)*2; delay > 0; delay--)
{
__NOP();
}
/* read data. */
for (uint32_t i = 24; i; i--)
{
adc_val <<= 1;
adc_val |= (GPIOB->IDR & BOARD_ADC_SDA_PIN) != 0;
BOARD_ADC_SCK_PORT->BSRR = BOARD_ADC_SCK_PIN;
__NOP();
BOARD_ADC_SCK_PORT->BRR = BOARD_ADC_SCK_PIN;
__NOP();
}
if (0u != (adc_val & 0x800000))
{
adc_val |= 0xFF000000;
}
return adc_val;
}
这里根据HYS1254数据输出的时序特征,使用外部中断下降沿触发的方式读取HYS1254输出的数据读取,实现代码如下:
/* prepare to read the hys1254. */
void app_hys1254_init(void)
{
/* init MCO to provide clock. */
CLOCK_MCO_1MHz();
/* init exti to get data. */
SYSCFG_SetExtIntMux(BOARD_SYSCFG_EXTIPORT, BOARD_SYSCFG_EXTI_LINE);
EXTI_EnableLineInterrupt(BOARD_EXTI_PORT, BOARD_EXTI_LINE, true);
EXTI_SetTriggerIn(BOARD_EXTI_PORT, BOARD_EXTI_LINE, EXTI_TriggerIn_FallingEdge);
NVIC_EnableIRQ(EXTI15_4_IRQn);
}
void EXTI15_4_IRQHandler(void)
{
uint32_t flags = EXTI_GetLineStatus(EXTI);
if ( 0u != ( flags & BOARD_EXTI_LINE ) ) /* interrupts. */
{
hys1254_adc_raw_fifo_buff[hys1254_adc_raw_fifo_index] = app_hys1254_read_adc_value_raw();
hys1254_adc_raw_fifo_index = (hys1254_adc_raw_fifo_index+1) % HYS1254_ADC_RAW_FIFO_LEN;
}
EXTI_ClearLineStatus(EXTI, flags);
}
其中,使用hys1254_adc_raw_fifo_buff[]
作为窗口缓冲区,缓存最近若干个(由HYS1254_ADC_RAW_FIFO_LEN
指定)ADC的原始采样结果。
软件滤波算法
在直接使用采样原始值作为结果输出时,发现压力传感器在未称重物的情况下,持续一段时间内,采集采样电路输出的ADC数值偏差过大,这里使用了滑动窗口+中段数据均值滤波法来尝试消除采样值的抖动问题,实现原理为每采样128次值后对这128次采样值进行升序排序,然后舍去前段和后段的数据,取剩余的中间段的数据求平均值作为一次采样结果。有代码如下所示:
int32_t app_hys1254_get_adc_value_filted(int32_t * out_buff)
{
/* sequencilize. */
app_bubble_sort(out_buff, HYS1254_ADC_RAW_FIFO_LEN);
/* scoll the data into the filter window. */
int64_t sum_64 = 0;
for (uint32_t i = HYS1254_ADC_RAW_FIFO_LEN/4u; i < HYS1254_ADC_RAW_FIFO_LEN-(HYS1254_ADC_RAW_FIFO_LEN/4); i++)
{
sum_64 += out_buff[i];
}
sum_64 /= (HYS1254_ADC_RAW_FIFO_LEN/2u);
return (int32_t)sum_64;
}
换算压力为ADC采样值
实验中使用了HX711压力传感器套装的压力传感器模块。如图x所示。
figure-hx711-pressure-sensor-module
图x HX711压力传感器套装
关于压力传感器模块,需要关注技术指标为:量程、接线方式、供电电压、输出灵敏度。实验中,使用的是5kg量程传感器,灵敏度1.0mV/V,供电电压5V,对应满量程输出电压(输出最大电压值)= 灵敏度 * 供电电压 = 5mV,即在传感器托盘上放置5kg的重物对应输出5mV。传感器的参数清单,如图x所示。
figure-hx711-pressure-sensor-spec
图x 压力传感器参数指标清单
在软件中,将HYS1254的采集值与最终的称重值成正比,在实际转换为称重值时,需要HYS1254采样值除以一个系数,而该系数将由试凑法,通过用标准砝码进行校验(俗称“去皮”),也可通过理论值进行计算。在应用工程中,已经设计了转换代码。
volatile int32_t app_weight_base = 0;
volatile int32_t app_weight_current = 0;
volatile float adc_factor = 740;
int main(void)
{
...
while (1)
{
...
app_slcd_display((float)(app_weight_current- app_weight_base)/adc_factor);
}
}
其中,adc_factor
变量即为可调整的比例系数,app_weight_base
为“去皮”的基准采样值。
实验过程
数据可视化
为直观的分析和观察实时采集到的HYS1254输出的数据,这里使用了FreeMaster软件观察MCU中记录滤波前的全局变量app_hys1254_adc_raw_fifo_current[0]
和滤波后全局变量 app_hys1254_value_filted
,如图x所示。
figure-sdadc-data-visualization-with-freemaster
图x 对采样数据进行可视化
通过实验发现,压力传感器相对静止的状态下,在同一状态下连续一段时间内,观察采集得到的各个24位采样值之间的后13位一直在不断波动,每次得到的采样结果波动过大,无法精确实现克单位级别细粒度的测量。
优化电路
在分析ADC采样值不稳定的原因时,意外碰到ADC模块之间的物理连接线,发现数据可视化的界面受到了很明显的影响,波形抖动幅度甚至达到了5g砝码对传感器产生的影响。由此可判定电路之间的连接线对模拟信号影响颇大。在实验中采取的应对措施是,缩短ADC采集电路与压力传感器之间的连线,将之前由杜邦线连接改为将压力传感器引出的线直接焊接在ADC采集电路板中,如图x所示。
按照上述条件,进行对比实验,数据波动有明显改善。但是,数据波动仍然明显。
使用软件滤波
实验中,使用MCU在向HYS1254
提供8MHz
的时钟源,获得20.833kHz
的采样率,未使用滤波,和使用滑动窗口+中段数据均值滤波后,有采样波形,如图x所示。
观察数据发现,使用软件滤波算法前后所得到的数据,通过比较采样期间得到的最大最小值之间的差值可以发现数据波动虽有改善但仍然有较大的波动,对最终的获得精确称重效果无明显改善,即24位采样值中,在电子秤保持静止状态下,数值波动最大最小值在经过滤波后的波动差在 5689 ,即至少24位的采样值其中的后13位(8192)在波动,未实现克单位级别的测量。
降低ADC的采样速率
阅读SDADC的数据手册发现,降低ADC采样频率至低速,有助于提高ADC转换结果的准确度。故在本实验中调整SDADC芯片的工作频率,进而降低ADC转换的频率。
在向HYS1254提供1MHz的时钟源,获得2.604kHz的采样率后的采样结果:
使用1MHz
的时钟源获得2.604kHz
的采样率,相对于之前的实验结果可以看到,降低采样率是可以在一定程度上减小波动,但采集出来的数据波动仍然过大,未满足稳定测量1克单位级别细粒度的要求。
使用独立的供电电源
进一步分析系统噪声可能来自于电源,因此分别使用DCDC充电器和电池作为整个系统的电源,验证电源对应用系统中ADC采样精度的影响。
- 使用使用手机电源适配器(MDY-08-ES,5V3A)供电。在向HYS1254提供1MHz的时钟源,获得2.604kHz的采样率后的采样结果:
- 使用干电池供电(3节南孚5号电池,4.5V供电),在向HYS1254提供1MHz的时钟源,获得2.604kHz的采样率后的采样结果:
按照上述条件,进行了对比实验,可以发现数据波动改善不明显。
再次调整滤波算法
在向HYS1254提供1MHz的时钟源,获得2.604kHz的采样率。由每组采集128次增加到每组采集256次再进行滤波,有采样结果,如图x所示。
由上述数据可知,增大每组的采样次数到256次,再进行中段数据均值滤波后,数值波动最大最小值在经过滤波后的波动差在5689
,即至少24位的采样值其中的后12位(4096)仍在波动,未能实现克单位级别的测量,未实现预期结果。
验证总结
本次验证实验,发现使用以HYS1254为主要器件的分立元件构成的SDADC采样方案结果波动过大,暂未实现1克细粒度的压力测量,即在压力传感器相对静止的状态下连续一段时间采样得到的各个24位采样值之间相互的后13位一直在不断波动的,通过使用缩短模拟信号连接导线、使用软件滤波、降低采样率,以及使用独立电源供电的方法尝试优化,均未明显改善的测量结果。
本文对此次验证过程的梳理记录总结,为接下来进一步的分析实验和定位问题提供参考。
后续可能有一些新思路继续改善静态采样数据波动问题:
- 进一步使用理想信号源,搞不好本方案中用到的大路货压力传感器也不是很灵敏。
- 优化采样电路设计。SDADC和分立的运放前端配合,中间的模拟信号通路容易受到外界干扰。市面上常规的设计方案,绝大多数是将SDADC和AFE合并在一起。甚至可以将MCU和SDADC采样电路合封在一起,最大化缩短信号链的物理传输路径。另外,很多集成SDADC的SoC中同时也集成了硬件SINC滤波器模块。
- 在软件算法方面,考虑到MM32L0130的片上资源和算力有限,尚未进行更多的数据滤波算法实现,后期可设计通过二阶或多阶滤波,也可通过进一步降低采样率到
kHz
或Hz
级别,并将每组的采样个数进一步地增大,如增大到512或者是1024个采样值作为一组值求平均,来尝试获取稳定的数据。
参考文献
作者:安德鲁苏
文章来源:安德鲁的设计笔记本
推荐阅读
- 利用DMA的触发循环实现对eTMR的PWM周期计数
- 手工打造基于MM32F5微控制器的MicroPython开发板
- 汽车电子系统总线LIN通信协议精要
- 在ARM微控制器上部署MATLAB/Simulink仿真模型
- 车规微控制器的ECC机制及EMU外设
更多MM32F5系列资料请关注灵动MM32 MCU专栏。如想进行MM32相关芯片技术交流,请添加极术小姐姐微信(id:aijishu20)加入微信群。