Funpack4-2 - 基于高速ADC采样的物体振动频率测量方案设计
该项目使用了dsPIC33CK64MC105 Curiosity Nano和振动传感器,实现了物体振动频率测量方案的设计,它的主要功能为:物体振动频率测量。
标签
ADC
Funpack4-2
dsPIC33
振动频率
TetraPak
更新2025-07-01
10

项目背景

funpack第四季第二期的活动中,本项目选用是的开发板是dsPIC33CK64MC105 Curiosity Nano

功能介绍

任务描述

  • 使用片内的ADC和高速比较器配合振动传感器,将探头贴在物体外部,敲击后测出振动的固有频率。

硬件介绍

dsPIC33CK64MC105 Curiosity Nano评估套件EV88G73A是一款高性价比的硬件平台,专为高性能数字电源和电机控制设计。该平台搭载一颗100MHz高性能数字信号控制器,并配备64KB ECC Flash和8KB RAM,同时集成12位/3.5Msps ADC、12位DAC以及四组高速PWM,其分辨率高达2ns,并拥有独立的核心外设。它不仅支持高精度PWM、快速ADC采样和硬件加速功能,还内置板载调试器和可调电压功能,便于实时调试,非常适用于工业自动化和电机驱动等高实时性应用。该ADC配备多个专用单通道内核以实现同时采样,并设有一个共享内核用于顺序采样,支持以AVdd作为正参考电压、AVss作为负参考电压,其单通道转换速率最高可达3.5Msps且分辨率为12位,转换延迟低;此外,它最多支持24个模拟输入通道,每个通道均有独立的16位转换结果寄存器输出无符号数据,各内核还支持多种转换触发方式,并内置多达四个数字比较器,这些比较器具备专用中断和灵活分配功能。所有ADC通道和比较器均可通过图形界面进行配置,而ADC的时钟和分频器设置则可在驱动模块的PLIB依赖项中进行调整。

设计思路

本项目的设计思路主要围绕如何通过ADC采样值提取信号峰值来计算振动频率展开。采用软件滤波(例如滑动窗口平均)去除随机噪声,并设定一定的阈值(例如NOISE_THRESHOLD)来区分振动信号与背景噪声。通过比较连续采样值判断信号的上升和下降,检测到有效峰值后计算相邻峰值之间的时间间隔,由此确定振动周期,最终反推出振动频率。

主要困难

  • 噪声干扰:在未振动状态下,ADC采集值存在0到30的随机波动,容易导致误判峰值。
  • 采样精度与速率:由于振动信号的周期较短,必须保证ADC采样的时间分辨率足够高,以便准确捕捉到峰值信息。
  • 实时性要求:振动频率的计算需要在较短的时间内完成,并及时显示在dataStreamer上,对软件流程和中断响应的要求较高。

解决思路

为了解决上述困难,项目采取以下措施:

  • 采用滑动窗口平均滤波技术,降低ADC采样数据的随机波动对峰值检测的影响;
  • 设定合适的噪声阈值和最小峰间隔,避免因微小波动产生错误触发;
  • 通过硬件定时器实现精确的采样间隔(10ms采样一次),利用软件定时器记录时间戳,从而计算峰值之间的时间间隔;
  • 利用片内高速比较器的中断机制实现实时数据处理和频率计算。

功能实现

在content libraries下载Data Streamer

ADC硬件比较器设置

DataStreamer字段设置


振动的ADC波形与对应的振动频率

软件流程图

核心配置及代码片段

本项目功能将在示例代码的基础上实现。在MPLAB IDE中,依据官方提供的ADC示例完成配置。

(1)ADC比较器回调函数

该函数通过滑动窗口对ADC采样值进行滤波处理,并利用高速比较器检测信号峰值,从而触发振动周期的计算。注释中标明了各步骤的作用。

c
复制static void ADC_Compare(enum ADC_CMP comparator)
{
static enum ADC_CHANNEL selectedChannel = Channel_AN0;
static uint32_t lastTriggerTime = 0;
static uint32_t lastPeakTime = 0;
static int sampleBuffer[WINDOW_SIZE] = {0};
static uint8_t bufIndex = 0;
static int prevFiltered = 0;
static uint8_t rising = 0;

if(adc->IsConversionComplete(selectedChannel))
{
DataStreamer.adcResult = adc->ConversionResultGet(selectedChannel);

// 将采样值存入滑动窗口缓冲区,并更新索引
sampleBuffer[bufIndex] = DataStreamer.adcResult;
bufIndex = (bufIndex + 1) % WINDOW_SIZE;

// 滑动窗口滤波,计算平均值
int filtered = 0;
for(uint8_t i = 0; i < WINDOW_SIZE; i++) {
filtered += sampleBuffer[i];
}
filtered /= WINDOW_SIZE;

switch(comparator)
{
case ADC_CMP_0: // 用于检测上升沿和峰值
DataStreamer.cmp0Result = DataStreamer.adcResult;
// 检测从低于阈值到高于阈值的上升趋势
if(filtered > NOISE_THRESHOLD && prevFiltered <= NOISE_THRESHOLD) {
rising = 1;
}
// 在上升后检测到下降并且仍高于阈值时,判定为峰值
if(rising && (filtered < prevFiltered) && (filtered > NOISE_THRESHOLD)) {
// 保证两次峰值之间的最小间隔
if((currentTime - lastPeakTime) > (MIN_PEAK_INTERVAL * 10)) {
if(!measurementActive) {
lastTriggerTime = currentTime;
measurementActive = true;
}
lastPeakTime = currentTime;
}
rising = 0;
}
prevFiltered = filtered;
break;

case ADC_CMP_1: // 用于计算频率并处理超时情况
DataStreamer.cmp1Result = DataStreamer.adcResult;
if(measurementActive)
{
// 计算从有效触发到当前的时间间隔(单位转换为秒)
measuredPeriod = (currentTime - lastTriggerTime) / 1000.0;
// 根据周期计算频率
DataStreamer.frequency = (measuredPeriod > 0) ? 1.0 / measuredPeriod : 0;
measurementActive = false; // 重置测量状态
}
else
{
// 超过一定时间未检测到新峰值时,频率置为0
if((currentTime - lastPeakTime) > 200) {
DataStreamer.frequency = 0;
}
}
break;

default:
break;
}
}

// 标记数据帧准备发送
sendDataStreamerFrame = true;
}

(2)定时器回调函数

通过定时器中断,定时触发ADC采样,并更新系统时间。主要包括1ms和3s两个定时器回调函数。

c
复制// 1ms定时器回调函数:更新系统时间并触发ADC采样
static void Timer_Callback_1ms(void)
{
adc->SoftwareTriggerEnable();
currentTime += 1;
}

// 100ms定时器回调函数(示例中未使用,可作为扩展):
static void Timer_Callback_100ms(void)
{
adc->SoftwareTriggerEnable();
}

// 3s定时器回调函数:用于LED指示(调试或状态指示)
static void Timer_Callback_3s(void)
{
LED0_Toggle();
}

(3)主函数完成系统初始化、定时器和ADC比较器回调的注册,以及在主循环中调用dataStreamer写帧函数,确保采集数据的实时传输。

c
复制int main(void)
{
// 定时器实例(根据具体项目进行替换)
const struct TIMER_INTERFACE *timer = &Timer1;
const struct TIMER_INTERFACE *timer2 = &Timer2;

// 系统初始化
SYSTEM_Initialize();

// 初始化dataStreamer数据
DataStreamer.adcResult = 0;
DataStreamer.cmp0Result = 0;
DataStreamer.cmp1Result = 0;
DataStreamer.frequency = 0.0f;

// 注册ADC比较器回调函数
adc->adcMulticoreInterface->ComparatorCallbackRegister(ADC_Compare);

// 注册定时器回调函数
timer->TimeoutCallbackRegister(Timer_Callback_1ms);
timer2->TimeoutCallbackRegister(Timer_Callback_3s);

// 主循环:检测并发送数据帧
while(1)
{
if(sendDataStreamerFrame)
{
WriteFrame();
sendDataStreamerFrame = false;
}
}
}

功能展示

最终的演示效果可通过将传感器探头贴在物体表面,敲击后实时观察MPLAB中Data Visualizer上的物体振动频率。

具体演示效果请观看演示视频

总结

本项目依托dsPIC33CK64MC105 Curiosity Nano评估套件,完成物体振动频率测量任务。在此过程中阅读dsPIC33CK64MC105数据手册和官方示例代码,分别实现ADC测量振动频率和dataStreamer显示功能,最终顺利完成任务。

附件下载
dsPIC33_Project.zip
项目工程源码
adc.dvws
MPLAB的Data Visualizer配置文件
团队介绍
团队成员
TetraPak
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号