简体   繁体   English

数字化模拟信号

[英]Digitizing an analog signal

I have a array of CSV values representing a digital output. 我有一组表示数字输出的CSV值。 It has been gathered using an analog oscilloscope so it is not a perfect digital signal. 它是使用模拟示波器收集的,因此它不是一个完美的数字信号。 I'm trying to filter out the data to have a perfect digital signal for calculating the periods (which may vary). 我试图过滤掉数据以获得完美的数字信号来计算周期(可能会有所不同)。 I would also like to define the maximum error i get from this filtration. 我还想定义从这个过滤得到的最大误差。

Something like this: 像这样的东西:

在此输入图像描述

Idea 理念

Apply a treshold od the data. 应用数据阈值。 Here is a pseudocode: 这是一个伪代码:

for data_point_raw in data_array:
    if data_point_raw < 0.8: data_point_perfect = LOW
    if data_point_raw > 2  : data_point_perfect = HIGH

else:
    #area between thresholds
    if previous_data_point_perfect == Low : data_point_perfect = LOW
    if previous_data_point_perfect == HIGH: data_point_perfect = HIGH

There are two problems bothering me. 有两个问题困扰着我。

  1. This seems like a common problem in digital signal processing, however i haven't found a predefined standard function for it. 这似乎是数字信号处理中的常见问题,但是我还没有找到预定义的标准功能。 Is this an ok way to perform the filtering? 这是一种执行过滤的好方法吗?
  2. How would I get the maximum error? 我怎样才能得到最大误差?

Here's a bit of code that might help. 这里有一些可能有用的代码。

from __future__ import division

import numpy as np


def find_transition_times(t, y, threshold):
    """
    Given the input signal `y` with samples at times `t`,
    find the times where `y` increases through the value `threshold`.

    `t` and `y` must be 1-D numpy arrays.

    Linear interpolation is used to estimate the time `t` between
    samples at which the transitions occur.
    """
    # Find where y crosses the threshold (increasing).
    lower = y < threshold
    higher = y >= threshold
    transition_indices = np.where(lower[:-1] & higher[1:])[0]

    # Linearly interpolate the time values where the transition occurs.
    t0 = t[transition_indices]
    t1 = t[transition_indices + 1]
    y0 = y[transition_indices]
    y1 = y[transition_indices + 1]
    slope = (y1 - y0) / (t1 - t0)
    transition_times = t0 + (threshold - y0) / slope

    return transition_times


def periods(t, y, threshold):
    """
    Given the input signal `y` with samples at times `t`,
    find the time periods between the times at which the
    signal `y` increases through the value `threshold`.

    `t` and `y` must be 1-D numpy arrays.
    """
    transition_times = find_transition_times(t, y, threshold)
    deltas = np.diff(transition_times)
    return deltas


if __name__ == "__main__":
    import matplotlib.pyplot as plt

    # Time samples
    t = np.linspace(0, 50, 501)
    # Use a noisy time to generate a noisy y.
    tn = t + 0.05 * np.random.rand(t.size)
    y = 0.6 * ( 1 + np.sin(tn) + (1./3) * np.sin(3*tn) + (1./5) * np.sin(5*tn) +
               (1./7) * np.sin(7*tn) + (1./9) * np.sin(9*tn))

    threshold = 0.5
    deltas = periods(t, y, threshold)
    print("Measured periods at threshold %g:" % threshold)
    print(deltas)
    print("Min:  %.5g" % deltas.min())
    print("Max:  %.5g" % deltas.max())
    print("Mean: %.5g" % deltas.mean())
    print("Std dev: %.5g" % deltas.std())

    trans_times = find_transition_times(t, y, threshold)

    plt.plot(t, y)
    plt.plot(trans_times, threshold * np.ones_like(trans_times), 'ro-')
    plt.show()

The output: 输出:

Measured periods at threshold 0.5:
[ 6.29283207  6.29118893  6.27425846  6.29580066  6.28310224  6.30335003]
Min:  6.2743
Max:  6.3034
Mean: 6.2901
Std dev: 0.0092793

情节

You could use numpy.histogram and/or matplotlib.pyplot.hist to further analyze the array returned by periods(t, y, threshold) . 您可以使用numpy.histogram和/或matplotlib.pyplot.hist来进一步分析由periods(t, y, threshold)返回的数组。

This is not an answer for your question, just and suggestion that may help. 这不是您的问题的答案,只是建议可能有所帮助。 Im writing it here because i cant put image in comment. 我在这里写它是因为我不能把图像放在评论中。

I think you should normalize data somehow, before any processing. 我认为你应该在任何处理之前以某种方式规范化数据。

After normalization to range of 0...1 you should apply your filter. 归一化到0 ... 1范围后,您应该应用您的过滤器。

在此输入图像描述

If you're really only interested in the period, you could plot the Fourier Transform, you'll have a peak where the frequency of the signals occurs (and so you have the period). 如果你真的只对这段时间感兴趣,你可以绘制傅立叶变换,你会有一个峰值信号的频率出现(所以你有周期)。 The wider the peak in the Fourier domain, the larger the error in your period measurement 傅立叶域中的峰值越宽,周期测量中的误差越大

import numpy as np

data = np.asarray(my_data)

np.fft.fft(data)

Your filtering is fine, it's basically the same as a schmitt trigger, but the main problem you might have with it is speed. 你的过滤很好,它与施密特触发器基本相同,但你可能遇到的主要问题是速度。 The benefit of using Numpy is that it can be as fast as C, whereas you have to iterate once over each element. 使用Numpy的好处是它可以像C一样快,而你必须在每个元素上迭代一次。

You can achieve something similar using the median filter from SciPy. 您可以使用SciPy的中值滤波器实现类似的功能。 The following should achieve a similar result (and not be dependent on any magnitudes): 以下应该可以达到类似的结果(并且不依赖于任何大小):

filtered = scipy.signal.medfilt(raw)
filtered = numpy.where(filtered > numpy.mean(filtered), 1, 0)

You can tune the strength of the median filtering with medfilt(raw, n_samples) , n_samples defaults to 3. 您可以使用medfilt(raw, n_samples)调整中值过滤的强度, n_samples默认为3。

As for the error, that's going to be very subjective. 至于错误,那将是非常主观的。 One way would be to discretise the signal without filtering and then compare for differences. 一种方法是在不过滤的情况下对信号进行离散,然后比较差异。 For example: 例如:

discrete = numpy.where(raw > numpy.mean(raw), 1, 0)
errors = np.count_nonzero(filtered != discrete)
error_rate = errors / len(discrete)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM