基于STC32检测20kHz 电磁导航信号

基于STC32检测20KHZ电磁导航信号

◎ 修改要点:

(1) 在C51程序中, 通过平均获得数据的平均值, 然后在后面计算幅度的时候减去动态平均值。

D ˉ = 1 N ∑ i = 0 N − 1 d [ i ] \bar D = {1 \over N}\sum\limits_{i = 0}^{N - 1} {d\left[ i \right]} Dˉ=N1i=0N1d[i] S d = 2 N ∑ i = 0 N − 1 [ d [ i ] − D ˉ ] ⋅ sin ⁡ ( i ⋅ Δ θ ) S_d = {2 \over N}\sum\limits_{i = 0}^{N - 1} {\left[ {d\left[ i \right] - \bar D} \right] \cdot \sin \left( {i \cdot \Delta \theta } \right)} Sd=N2i=0N1[d[i]Dˉ]sin(iΔθ) C d = 2 N ∑ i = 0 N − 1 [ d [ i ] − D ˉ ] ⋅ cos ⁡ ( i ⋅ Δ θ ) C_d = {2 \over N}\sum\limits_{i = 0}^{N - 1} {\left[ {d\left[ i \right] - \bar D} \right]} \cdot \cos \left( {i \cdot \Delta \theta } \right) Cd=N2i=0N1[d[i]Dˉ]cos(iΔθ) A d = S d 2 + C d 2 A_d = \sqrt {S_d^2 + C_d^2 } Ad=Sd2+Cd2

实验验证结果: 使用DG1062输入 Vpp=5mV, f=20kHz, Dmean=2.5V 正弦波信号;

  1. 数据计算时,减去 0x800, 数值大约为 1: 减去 0x400: 数值大约在 4-6之间; 数据不减去中值, 计算数据大约为 12 左右。 减去 Average, 计算数值大约为 1;

(2) 采集的数据个数,应该是正弦波的整数倍数:

f 0 = 10055 ,    f 1 = 20000 f_0 = 10055,\,\,f_1 = 20000 f0=10055,f1=20000 Δ θ = 2 π ( 2 f 0 − f 1 ) f 0 \Delta \theta = { {2\pi \left( {2f_0 - f_1 } \right)} \over {f_0 }} Δθ=f02π(2f0f1) N 1 = 2 π Δ θ = f 0 2 f 0 − f 1 = 91.409 N_1 = { {2\pi } \over {\Delta \theta }} = { {f_0 } \over {2f_0 - f_1 }} = 91.409 N1=Δθ2π=2f0f1f0=91.409 20 × N 1 = 1828 20 \times N_1 = 1828 20×N1=1828

20倍的周期数据个数为 1828。

实验结果:

  1. 取数据个数为 1828: 308 个数据, 均值为1.0205, STD: 0.07428
  2. 取数据个数为 2000: 309个数据, 均值为 1.00544, STD:0.0699
  3. 取数据个数为 3000: 121 个数据, 均值为 0.997, STD: 0.0568
  4. 取数据个数为 1000: 141个数据, 均值 为 1.025, STD:0.09222

结论: 可以看到实际上采集数据个数并不是正弦波的整数倍数为最好, 还是采集数据越多越好。

(3) 计算时间:

float BufferAmp(void) {
    
    
    float fSin, fCos, fAngle, fDeltaTheta, fValue, fAverage;
    int i;
    float f0 = 10055;
    float f1 = 20000;
    
    fDeltaTheta = 2*3.1415926*(2*f0-f1)/f0;
    
    fSin = fCos = 0;
    
    fAverage = 0;
    for(i = 0; i < ADC_BUFFER; i++)
        fAverage += g_nADC[i];
        
    fAverage /= ADC_BUFFER;
    
    for(i = 0; i < ADC_BUFFER; i ++) {
    
    
        fAngle = i * fDeltaTheta;
        fValue = g_nADC[i] - fAverage;
        fSin += fValue * sin(fAngle);
        fCos += fValue * cos(fAngle);
    }
                
    fSin /= ADC_BUFFER;
    fCos /= ADC_BUFFER;
                
    fValue = sqrt(fSin*fSin + fCos*fCos);
    return fValue;                
}
  • 在浮点数库下: 68.2ms
  • 没有浮点库情况下: 492ms

01 磁导航信号


一、前言

C51\STC\Test\2023\Test32F12\Detect20kHzAD\Detect20kHzAD.uvproj

  在电子锥桶设计中,  需要使用电磁导航信号对电子锥桶进行复位,  前期测试了基于LM567检测电磁信号的方案,  发现它的检测灵敏度会受到电路中的电阻和电容精度的影响,  昨天测试了基于 STC32 ADC检测方案,  无论是精度还是灵敏度都大大提高了。 下面对此进行进一步测试。



GM1695380648_1280_720.MPG|_-6

二、基本原理

  STC32F 单片机中的 ADC 在 12位下, 数据手册要求不能够高于800kHz。 下面利用程序,  对转换函数时间进行测量。  前后通过对 LED 管脚单片的改变,   可以得到ADC所消耗的时间。 这是示波器显示 LED 脉冲波形。  可以看到,  高电平时间为 3.22 微秒, 这是实际 STC32F 单片机采集时间。

GM1695368801_1280_720.MPG|_-8
  这是 STC32F 数据手册中给出的ADC转换速度公式,  根据软件中的设置, 可以计算出ADC转换时钟数量 为52,  在 24MHz下, 对应 2.2微秒的转换时间。  实测转换时间为 3.2微秒。

GM1695369497_1280_720.MPG|_-4

  这是通过循环连续采集 2000 个信号数据绘制出的波形。 信号峰峰值为 100mV。 频率为 20kHz。 由于采样周期在 3 微秒左右,  所以每个周期所采集到的数据点只有15个左右, 数据波形也存在较大的失真。 为了解决采集速度的问题, 下面采用欠采样方法来提高信号采样精度。

GM1695376046_1280_720.MPG|_-2

from headm import *                 # =
from tsmodule.tsvisa        import *
from tsmodule.tsstm32       import *

f0 = 10055
f1 = 20000
t0 = 1/f0
t1 = 1/f1
deltat = t1*2-t0
samplen = t1/deltat
deltatheta = 2*pi/samplen
printf(samplen)

dat = stm32data(1, 2000)
datlen = len(dat)
sindata = sin(linspace(0, datlen * deltatheta, datlen, endpoint=False)) * 1000 + 0x800

plt.plot(dat, lw=3)
plt.xlabel("N")
plt.ylabel("data")
plt.grid(True)
plt.tight_layout()
plt.show()

三、欠采样

  使用欠采样来采集周期高频信号波形, 设置采样周期比信号周期的整数倍数略高, 或者略低, ·便可以获得与原信号相同波形的数据。 下面测量一下定时器4 中断的频率,   就是前面 定时器4 中断内进行AD转换的脉冲信号的频率, 是 10.055kHz,  这个数值比 20kHz 信号频率一半略微高一些, 可以利用这个方式完成信号的欠采样。  下面来看一下采集到的数据波形。

GM1695370097_1280_720.MPG|_-5

▲ 图1.3.1 采集到 2000个数据的信号波形

▲ 图1.3.1 采集到 2000个数据的信号波形

  这是采集到的 2000个数据点。 为了表明数据波形的稳定性, 在数据中间还有橙色正弦曲线, 可以看到它们之间的相位非常稳定。  采样频率为 f0, 信号频率为 f1。  那么可以求得各自的周期, t0, t1。  采样周期比两倍信号周期少了 delta t。  对应信号一个周期内采样数据的个数为 Ns。  代入数据可以计算出大约为 91.4。   由此, 可以得到数据正弦信号, 每个采样数据对应的相位差为 delta θ。  按照这个相位差绘制出橙色曲线, 理论正弦信号与实际采样信号之间对应非常完美。

GM1695374009_1280_720.MPG|_-9

四、信号幅度

  这是峰峰值为 5mV, 20kHz 的导航信号, 经过采集之后的波形。 下面给出计算其中正弦波形的公式。  这是根据采样频率和信号频率计算出数据采样周期, 对于采样数据,  分别计算出数据与 sine、cosine 信号的内积,  然后计算出信号的幅值。

GM1695374761_1280_720.MPG|_-5

float BufferAmp(void) {
    
    
    float fSin, fCos, fAngle, fDeltaTheta, fValue;
    int i, nValue;
    float f0 = 10055;
    float f1 = 20000;
    
    fDeltaTheta = 2*3.1415926*(2*f0-f1)/f0;
    
    fSin = fCos = 0;
    for(i = 0; i < ADC_BUFFER; i ++) {
    
    
        fAngle = i * fDeltaTheta;
        nValue = g_nADC[i] - 0x800;
        fSin += nValue * sin(fAngle);
        fCos += nValue * cos(fAngle);
    }
                
    fSin /= ADC_BUFFER;
    fCos /= ADC_BUFFER;
                
    fValue = sqrt(fSin*fSin + fCos*fCos);
    return fValue;                
}

  这是计算出信号的幅值,  可以看到信号幅值计算值为 1, 上下偏差在0.1 之间。 这能够表明信号的存在。

GM1695375364_1280_720.MPG|_-2
  这是输入信号峰峰值为 100mV时,采集到的信号波形。  这里给出了 500次测量结果, 计算数值在 20左右波动。

GM1695375555_1280_720.MPG|_-2

五、实测导航信号

  仿照前面利用 LM567 检测电磁信号中的电路,  采用一个三极管对来自 LC 并联谐振电磁感应信号进行放大,  然后连接到 STC32 ADC通道。  这个电路就在面包板上搭建。 三极管集电极放大信号直接引入单片机,  三极管集电极均值电压在2.3V 左右。  经过测试, 可以看到 在旁边 1米附近, 如果有 电磁导航线圈, 便可以引起单片机检测信号触发。  如果 检测到 20kHz 信号幅值超过 2, 便点亮 LED 指示灯。 ·这个实验证明了利用单片机检测电磁信号的高灵敏性和可靠性。

GM1695380320_1280_720.MPG|_-8

  结 ※


  文介绍了基于STC32检测电磁导航信号的方法。  实验证明了该电路的可靠性。

GM1695380389_1280_720.MPG|_-2


■ 相关文献链接:

● 相关图表链接:

猜你喜欢

转载自blog.csdn.net/zhuoqingjoking97298/article/details/133170631