Gürültülü Sinüs Dalgasının Sıfır Geçişi


9

Sinüs dalgasını kare dalgaya dönüştürmek için sinüs dalgasının sıfır geçişini bulmaya çalışıyorum. Tek sorun sinüs dalgasının gürültülü olması, bu yüzden çok fazla titreşim ve yanlış sıfır geçişleri alıyorum.

Herkes herhangi bir basit kod kodu veya ilgili materyal önerebilir mi? Şimdiye kadar böyle bir şey var:

if (sample[i]>0 && sample[i+1]<0) || (sample[i]<0 && sample[i+1]>0)

Herkes daha sağlam bir yöntem önerebilir mi?


Bunu kare dalga haline getirmeye çalışmanın amacı nedir? Sinyalin nerede başladığını ve bittiğini bulmaya mı çalışıyorsunuz? Eğer öyleyse bir yöntem önerebilirim.
Spacey

if ((örnek [i] * örnek [i + 1]) <0) sıfır_geçiş ++;
Marius Hrisca

Yanıtlar:


8

Daha düzgün sıfır geçişleri elde etmek için giriş sinyalini alçak geçiren filtrelemeyi deneyebilirsiniz (hatta sinüs dalgasının frekans konumu hakkında iyi bir fikriniz varsa bant geçiren filtreleme). Risk, uygulamanız için örnek-doğru faz bilgisi gerekliyse, filtreden gelen ek gecikme bir sorun olabilir.

Başka bir yaklaşım: Sinüs dalgasını kare bir dalgaya dönüştürmeye çalışmak yerine, faz / frekansta kendini sinüs dalgasıyla hizalamak için bağımsız bir kare dalga osilatörünü almaya ne dersiniz? Bu, faz kilitli bir döngü ile yapılabilir .


6

Kesinlikle gösterdiğiniz şey sıfır geçişli bir dedektördür. Durumunuzu iyileştirebilecek birkaç şey akla geliyor:

  • Sinyalin bandının dışında bir gürültü varsa (girişiniz saf bir ton olduğu için neredeyse kesinlikle durum budur), ilgilenilen sinyalin etrafına bir bant geçiren filtre uygulayarak sinyal / gürültü oranını artırabilirsiniz. . Filtrenin geçiş bandı genişliği, sinüsoid frekansını önceden nasıl bildiğinize bağlı olarak seçilmelidir . Sinüzoid üzerinde bulunan gürültü miktarını azaltarak, yanlış sıfır geçişlerinin sayısı ve doğru geçiş süreleri hakkındaki titreşimleri azaltılacaktır.

    • Bir yan not olarak, önceden iyi bir bilginiz yoksa , adından da anlaşılacağı gibi, periyodik bir giriş sinyalini artıracak uyarlanabilir bir filtre olan uyarlanabilir hat arttırıcı olarak bilinen daha karmaşık bir teknik kullanabilirsiniz . Ancak, bu biraz gelişmiş bir konudur ve genellikle sinyalin bu tür bir yaklaşıma ihtiyaç duymadığı frekansı hakkında yeterince iyi bir fikriniz vardır.
  • Sıfır geçiş dedektörünün kendisiyle ilgili olarak, işleme biraz histerezis ekleyebilirsiniz . Bu, doğru geçiş anında ekstra sahte ölçülü geçişlerin oluşmasını önleyecektir. Dedektöre histerezis eklemek şöyle bir şey olabilir:

    if ((state == POSITIVE) && (sample[i - 1] > -T) && (sample[i] < -T))
    {
        // handle negative zero-crossing
        state = NEGATIVE;
    }
    else if ((state == NEGATIVE) && (sample[i - 1] < T) && (sample[i] > T))
    {
        // handle positive zero-crossing
        state = POSITIVE;
    }
    

    Etkili bir şekilde, sıfır geçiş dedektörünüze bir miktar durum eklersiniz. Giriş sinyalinin pozitif bir değere sahip olduğuna inanıyorsanız, -Tgerçek bir sıfır geçişi bildirmek için sinyalin seçilen bir eşik değerinin altına düşmesini gerekir. Benzer şekilde, sinyalin Ttekrar pozitif olarak salındığını bildirmek için sinyalin eşiğin üzerine çıkmasını zorunlu kılar .

    Eşikleri istediğiniz gibi seçebilirsiniz, ancak sinüzoid gibi dengeli bir sinyal için sıfır civarında simetrik olmaları mantıklıdır. Bu yaklaşım size daha temiz görünümlü bir çıktı vermenize yardımcı olabilir, ancak sıfır geçişleri yerine sıfır olmayan eşik geçişlerini ölçtüğünüz için biraz zaman gecikmesi ekleyecektir.

Pichenettes'in cevabında önerdiği gibi, bir PLL yapmaya çalıştığınız şeyi tam olarak yaptığından, faz kilitli bir döngü muhtemelen en iyi yol olacaktır. Kısacası, sinüsoid girişiyle paralel çalışan bir kare dalga üreteci çalıştırıyorsunuz. PLL sinüsoid üzerinde periyodik faz ölçümleri yapar, daha sonra kare dalga üretecinin anlık frekansını yönlendirmek için bu ölçüm akışını filtreler. Bir noktada, döngü (umarım) kilitlenecektir, bu noktada kare dalga girişin sinüzoidi ile frekans ve fazda kilitlenmelidir (elbette bir miktar hatayla; mühendislikte hiçbir şey mükemmel değildir).


Bu bir Schmitt tetikleyicisi mi?
Davorin

Gerçekten, bunun bir Schmitt tetikleyicisinin yazılım versiyonu olduğunu söyleyebilirsiniz . Bir Schmitt tetikleyicinin belirleyici özelliği, histerezis ile karşılaştırıcı olmasıdır
Jason R

Geçişi saptamamak için her iki koşulda da eşik değerlerini ekleyin T. Anlam yerine && (sample[i - 1] > -T) && (sample[i] < -T)), kullanın && (sample[i - 1] >= -T) && (sample[i] < -T)). Bu, hem uygulanacak gerekiyor ifve else iftabloların.
marc

2

Zaman zaman sinyal değişikliklerini bulmak için çok basit bir yöntem ile iyi bir deneyime sahip:

  1. a = diff (işaret (sinyal))! = 0 # Bu işaret değişikliklerini algılar
  2. adaylar = çarpı [a] # bunların hepsi yanlış geçişler dahil aday puanlarıdır
  3. adaylarda puan kümeleri bul
  4. ortalama / medyan her küme, bu sizin işaret değişikliğiniz

  5. 4 ile öngörülen noktadaki basamak fonksiyonu ile korelasyon yapabilecek

  6. eğriyi korelasyon sonuçlarına sığdır ve zirve bul

Benim durumumda 5 ve 6 yöntemin hassasiyetini artırmıyor. Sinyalinizi gürültü ile renklendirebilir ve yardımcı olup olmadığını görebilirsiniz.


2

Bu sorunun oldukça eski olduğunu biliyorum, ama son zamanlarda sıfır geçişi uygulamak zorunda kaldım. Dan'ın önerdiği yöntemi uyguladım ve sonuçtan oldukça memnunum. İlgilenen varsa, Python kodumu heres. Gerçekten zarif bir programcı değilim, lütfen benimle ayı.

import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle

fig = plt.figure()
ax = fig.add_subplot(111)

sample_time = 0.01
sample_freq = 1/sample_time

# a-priori knowledge of frequency, in this case 1Hz, make target_voltage variable to use as trigger?
target_freq = 1
target_voltage = 0

time = np.arange(0.0, 5.0, 0.01)
data = np.cos(2*np.pi*time)
noise = np.random.normal(0,0.2, len(data))
data = data + noise


line, = ax.plot(time, data, lw=2)

candidates = [] #indizes of candidates (values better?)
for i in range(0, len(data)-1):
    if data[i] < target_voltage and data[i+1] > target_voltage:
        #positive crossing
        candidates.append(time[i])
    elif data[i] > target_voltage and data[i+1] < target_voltage:
        #negative crossing
        candidates.append(time[i])

ax.plot(candidates, np.ones(len(candidates)) * target_voltage, 'rx')
print('candidates: ' + str(candidates))

#group candidates by threshhold
groups = [[]]
time_thresh = target_freq / 8;
group_idx = 0;

for i in range(0, len(candidates)-1):
    if(candidates[i+1] - candidates[i] < time_thresh):
        groups[group_idx].append(candidates[i])
        if i == (len(candidates) - 2):
            # special case for last candidate
            # in this case last candidate belongs to the present group
            groups[group_idx].append(candidates[i+1])
    else:
        groups[group_idx].append(candidates[i])
        groups.append([])
        group_idx = group_idx + 1
        if i == (len(candidates) - 2):
            # special case for last candidate
            # in this case last candidate belongs to the next group
            groups[group_idx].append(candidates[i+1])



cycol = cycle('bgcmk')
for i in range(0, len(groups)):
    for j in range(0, len(groups[i])):
        print('group' + str(i) + ' candidate nr ' + str(j) + ' value: ' + str(groups[i][j]))
    ax.plot(groups[i], np.ones(len(groups[i])) * target_voltage, color=next(cycol), marker='o',  markersize=4)


#determine zero_crosses from groups
zero_crosses = []

for i in range(0, len(groups)):
    group_median = groups[i][0] + ((groups[i][-1] - groups [i][0])/2)
    print('group median: ' + str(group_median))
    #find index that best matches time-vector
    idx = np.argmin(np.abs(time - group_median))
    print('index of timestamp: ' + str(idx))
    zero_crosses.append(time[idx])


#plot zero crosses
ax.plot(zero_crosses, np.ones(len(zero_crosses)) * target_voltage, 'bx', markersize=10) 
plt.show()

Pls Not: Kodum işaretleri tespit etmez ve zaman eşiğini belirlemek için hedef frekans hakkında biraz a priori bilgisi kullanır. Bu eşik, ortanca gruplara en yakın olanın seçildiği (resimde mavi haçlar) çoklu geçişi (resimdeki farklı renk noktaları) gruplamak için kullanılır.

Sıfır çarpı işaretli gürültülü sinüs dalgası

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.