การข้ามศูนย์ของ Noine Sine Wave


9

ฉันกำลังพยายามหาการข้ามศูนย์ของคลื่นไซน์เพื่อแปลงคลื่นไซน์ให้เป็นคลื่นสี่เหลี่ยม ปัญหาเดียวก็คือคลื่นไซน์นั้นมีเสียงดังดังนั้นฉันจึงได้รับการกระวนกระวายใจและการข้ามศูนย์ผิดมาก

ใครสามารถแนะนำ psuedocode ง่าย ๆ หรือวัสดุที่เกี่ยวข้อง? จนถึงตอนนี้ฉันมีสิ่งนี้:

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

ทุกคนสามารถแนะนำวิธีการที่แข็งแกร่งกว่านี้ได้หรือไม่?


อะไรคือจุดประสงค์ของคุณที่พยายามทำให้มันเป็นคลื่นสี่เหลี่ยม? คุณพยายามที่จะหาว่าสัญญาณเริ่มต้นและสิ้นสุดหรือไม่? ถ้าคุณเป็นฉันสามารถแนะนำวิธีการ
Spacey

ถ้า ((ตัวอย่าง [i] * ตัวอย่าง [i + 1]) <0) zero_crossing ++;
Marius Hrisca

คำตอบ:


8

คุณสามารถลองกรองสัญญาณผ่านความถี่ต่ำเพื่อรับการข้ามศูนย์ที่ราบรื่นขึ้น (หรือแม้แต่การกรองสัญญาณความถี่วิทยุหากคุณมีความคิดที่ดีเกี่ยวกับตำแหน่งความถี่ของคลื่นไซน์) ความเสี่ยงคือถ้าข้อมูลเฟสที่แม่นยำตัวอย่างเป็นสิ่งจำเป็นสำหรับแอปพลิเคชันของคุณความล่าช้าเพิ่มเติมจากตัวกรองอาจเป็นปัญหา

อีกวิธีหนึ่ง: แทนที่จะพยายามแปลงคลื่นไซน์ให้เป็นคลื่นสี่เหลี่ยมแล้วจะให้ออสซิลเลเตอร์คลื่นสี่เหลี่ยมอิสระเรียงตัวเองในเฟส / ความถี่กับคลื่นไซน์ได้อย่างไร ซึ่งสามารถทำได้ด้วยเฟสล็อกลูป


6

สิ่งที่คุณแสดงให้เห็นอย่างแน่นอนคือเครื่องตรวจจับข้ามศูนย์ นึกถึงสองสามอย่างที่อาจทำให้สถานการณ์ของคุณดีขึ้น:

  • หากคุณมีสัญญาณรบกวนที่อยู่นอกย่านความถี่ของสัญญาณของคุณ (ซึ่งเกือบจะแน่นอนในกรณีเนื่องจากอินพุตของคุณเป็นโทนสีที่บริสุทธิ์) จากนั้นคุณสามารถปรับปรุงอัตราส่วนสัญญาณต่อเสียงรบกวนโดยใช้ตัวกรอง bandpass รอบสัญญาณที่น่าสนใจ . ความกว้างของตัวกรอง passband ควรจะเลือกขึ้นอยู่กับว่าคุณรู้ได้อย่างแม่นยำความถี่ sinusoid เบื้องต้น โดยการลดปริมาณของเสียงที่มีอยู่บนไซนัสนั้นจำนวนของการข้ามศูนย์ที่ผิดพลาดและกระวนกระวายใจของพวกเขาเกี่ยวกับเวลาข้ามที่ถูกต้องจะลดลง

    • ถ้าคุณไม่มีข้อมูลที่ดีล่วงหน้าคุณสามารถใช้เทคนิคที่มีความซับซ้อนมากขึ้นที่รู้จักกันในชื่อการปรับปรุงสายการปรับตัวซึ่งชื่อของมันหมายถึงเป็นตัวกรองการปรับตัวที่จะเพิ่มสัญญาณอินพุตเป็นระยะ อย่างไรก็ตามนี่เป็นหัวข้อขั้นสูงและโดยทั่วไปคุณมีความคิดที่ดีเกี่ยวกับความถี่ของสัญญาณว่าไม่จำเป็นต้องใช้วิธีการแบบนี้
  • เกี่ยวกับการตรวจจับศูนย์ข้ามตัวเองคุณอาจเพิ่มบางhysteresisกับกระบวนการ สิ่งนี้จะป้องกันการสร้างการข้ามที่ปลอมแปลงพิเศษที่วัดได้รอบการข้ามทันทีที่ถูกต้อง การเพิ่มฮิสเทรีซิสในอุปกรณ์ตรวจจับอาจมีลักษณะดังนี้:

    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;
    }
    

    อย่างมีประสิทธิภาพคุณเพิ่มบางรัฐในเครื่องตรวจจับข้ามศูนย์ของคุณ หากคุณเชื่อว่าสัญญาณอินพุตมีค่าเป็นบวกคุณต้องให้สัญญาณลดลงต่ำกว่าค่าเกณฑ์ที่เลือก-Tเพื่อประกาศการข้ามศูนย์จริง ในทำนองเดียวกันคุณต้องการให้สัญญาณเพิ่มสูงขึ้นเหนือขีด จำกัดTเพื่อประกาศว่าสัญญาณได้แกว่งกลับไปเป็นบวกอีกครั้ง

    คุณสามารถเลือกเกณฑ์ที่จะเป็นสิ่งที่คุณต้องการ แต่สำหรับสัญญาณที่สมดุลเช่นไซน์ไซด์มันก็สมเหตุสมผลที่จะให้พวกมันสมมาตรประมาณศูนย์ วิธีนี้สามารถช่วยให้ผลลัพธ์ที่ดูสะอาดตาขึ้น แต่จะเพิ่มการหน่วงเวลาบางส่วนเนื่องจากความจริงที่ว่าคุณกำลังวัดการข้ามจุดเริ่มต้นที่ไม่เป็นศูนย์แทนการข้ามจุดศูนย์

ดังที่ pichenettes แนะนำในคำตอบของเขาการวนลูปแบบล็อกเฟสน่าจะเป็นวิธีที่ดีที่สุดที่จะไปเพราะ PLL ทำสิ่งที่คุณกำลังพยายามทำอยู่ ในระยะสั้นคุณเรียกใช้เครื่องกำเนิดคลื่นสี่เหลี่ยมที่ทำงานในแบบคู่ขนานกับอินพุตไซนัส PLL ทำการวัดระยะเป็นระยะในไซน์ไซด์จากนั้นกรองการไหลของการวัดเพื่อคัดท้ายความถี่ในทันทีของเครื่องกำเนิดคลื่นสี่เหลี่ยม ในบางจุดลูปจะ (หวังว่า) จะล็อคซึ่งจุดที่คลื่นสแควร์ควรถูกล็อคในความถี่และเฟสด้วยไซน์ของอินพุต (แน่นอนว่ามีข้อผิดพลาดบางอย่างไม่มีอะไรในด้านวิศวกรรมที่สมบูรณ์แบบ)


นั่นคือชมิดท์ทริกเกอร์หรือไม่?
Davorin

คุณสามารถพูดได้ว่ามันเป็นเวอร์ชั่นซอฟท์แวร์ของตัวกระตุ้นชมิตต์ ลักษณะการกำหนดของไกชิตท์คือมันเป็นตัวเปรียบเทียบกับการตีโพยตีพาย
Jason R

เพื่อหลีกเลี่ยงไม่ได้ตรวจสอบการเปลี่ยนแปลงรวมอยู่ในเงื่อนไขใด ๆ Tทั้งยังเกณฑ์ ความหมายแทนการใช้&& (sample[i - 1] > -T) && (sample[i] < -T)) && (sample[i - 1] >= -T) && (sample[i] < -T))สิ่งนี้จำเป็นต้องใช้กับทั้งคำสั่งifและ else if
รายการ MARC

2

ฉันมีประสบการณ์ที่ดีด้วยวิธีที่ง่ายมากในการค้นหาการเปลี่ยนแปลงของสัญญาณในบางครั้ง:

  1. a = diff (เครื่องหมาย (สัญญาณ))! = 0 # จะตรวจจับการเปลี่ยนแปลงของสัญญาณ
  2. บอร์ดผู้สมัคร = คูณ [a] # นี่คือคะแนนผู้สมัครทั้งหมดรวมถึงการข้ามที่ผิด
  3. หากลุ่มของคะแนนในผู้สมัคร
  4. เฉลี่ย / มัธยฐานแต่ละกลุ่มนี่คือการเปลี่ยนแปลงเครื่องหมายของคุณ

  5. ทำความสัมพันธ์กับฟังก์ชั่นขั้นตอนที่จุดทำนายโดย 4

  6. ปรับเส้นโค้งให้พอดีกับผลลัพธ์สหสัมพันธ์และค้นหาจุดสูงสุด

ในกรณีของฉันที่ 5 และ 6 จะไม่เพิ่มความแม่นยำของวิธีการ คุณสามารถส่งสัญญาณด้วยเสียงรบกวนและดูว่ามันช่วยได้หรือไม่


2

ฉันรู้ว่าคำถามนี้ค่อนข้างเก่า แต่ฉันต้องใช้การข้ามศูนย์เมื่อเร็ว ๆ นี้ ฉันใช้วิธีที่แดนแนะนำและรู้สึกพอใจกับผลลัพธ์มาก นี่คือรหัสหลามของฉันหากใครสนใจ ฉันไม่ใช่โปรแกรมเมอร์ที่สง่างามจริงๆ

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()

โปรดทราบ: รหัสของฉันไม่ตรวจจับสัญญาณและใช้ความรู้เบื้องต้นเกี่ยวกับความถี่เป้าหมายเล็กน้อยเพื่อกำหนดเกณฑ์เวลา เกณฑ์นี้ใช้เพื่อจัดกลุ่มการข้ามหลายจุด (จุดสีต่างกันในภาพ) ซึ่งมีการเลือกค่ามัธยฐานของกลุ่มที่ใกล้เคียงที่สุดมากที่สุด (กากบาทสีฟ้าในภาพ)

คลื่นไซน์ที่มีเสียงดังและไม่มีเครื่องหมายกากบาททำเครื่องหมาย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.