사인파를 사각 파로 변환하기 위해 사인파의 교차점을 찾으려고합니다. 유일한 문제는 사인파가 시끄러워서 많은 지터와 잘못된 제로 크로싱을 얻는다는 것입니다.
누구나 간단한 유사 코드 또는 관련 자료를 추천 할 수 있습니까? 지금까지 나는 이와 같은 것을 가지고있다 :
if (sample[i]>0 && sample[i+1]<0) || (sample[i]<0 && sample[i+1]>0)
누구나 더 강력한 방법을 추천 할 수 있습니까?
사인파를 사각 파로 변환하기 위해 사인파의 교차점을 찾으려고합니다. 유일한 문제는 사인파가 시끄러워서 많은 지터와 잘못된 제로 크로싱을 얻는다는 것입니다.
누구나 간단한 유사 코드 또는 관련 자료를 추천 할 수 있습니까? 지금까지 나는 이와 같은 것을 가지고있다 :
if (sample[i]>0 && sample[i+1]<0) || (sample[i]<0 && sample[i+1]>0)
누구나 더 강력한 방법을 추천 할 수 있습니까?
답변:
당신이 확실히 보여준 것은 제로 크로싱 검출기입니다. 상황을 개선 할 수있는 몇 가지 사항이 있습니다.
신호 대역 외부에 노이즈가있는 경우 (입력이 순수한 톤이므로 거의 모든 경우에 해당) 관심 신호 주위에 대역 통과 필터를 적용하여 신호 대 잡음비를 개선 할 수 있습니다. . 필터의 통과 대역 폭이 선택 당신이 정현파 주파수 방법을 알고 정확하게에 기초해야 선험적 . 정현파에 존재하는 노이즈의 양을 줄임으로써 잘못된 제로 크로싱 횟수와 올바른 크로싱 시간에 대한 지터가 감소합니다.
제로 크로싱 검출기 자체와 관련 하여 공정에 약간의 히스테리시스 가 추가 될 수 있습니다 . 이것은 정확한 교차점을 중심으로 여분의 스퓨리어스 측정 교차점이 생성되는 것을 방지합니다. 검출기에 히스테리시스를 추가하면 다음과 같이 보일 수 있습니다.
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
신호가 다시 포지티브로 다시 진동했음을 선언하기 위해 신호가 임계 값 위로 다시 상승해야 합니다.
원하는 값으로 임계 값을 선택할 수 있지만 정현파와 같은 균형 잡힌 신호의 경우 임계 값을 0으로 대칭하는 것이 좋습니다. 이 접근 방식은보다 깔끔한 출력을 제공하는 데 도움이 될 수 있지만 실제로는 제로 크로싱 대신 0이 아닌 임계 값 크로싱을 측정한다는 사실로 인해 약간의 시간 지연이 발생합니다.
Pchen이 당신이하려는 일을 거의 정확하게 수행하기 때문에 pichenettes가 그의 대답에서 제안했듯이 위상 고정 루프가 가장 좋은 방법 일 것입니다. 요컨대, 입력 정현파와 병렬로 작동하는 구형파 발생기를 실행합니다. PLL은 정현파에 대해 주기적 위상 측정을 한 다음, 구형파 발생기의 순간 주파수를 조정하기 위해 측정 스트림을 필터링합니다. 어떤 시점에서 루프는 (희망적으로) 잠기 며,이 지점에서 구형파는 입력의 정현파로 주파수와 위상으로 고정되어야합니다 (물론 약간의 오차가 있습니다. 엔지니어링에는 완벽하지 않습니다).
T
. 대신에을 && (sample[i - 1] > -T) && (sample[i] < -T))
사용하십시오 && (sample[i - 1] >= -T) && (sample[i] < -T))
. 이것은 진술 if
과 else if
진술 에 모두 적용되어야합니다 .
나는 때때로 신호의 부호 변화를 찾는 매우 간단한 방법에 대한 좋은 경험이 있습니다.
각 군집의 평균 / 중앙값, 부호 변경입니다
4에 의해 예측 된 지점에서 스텝 함수와 상관 관계
필자의 경우 5와 6은 방법의 정밀도를 높이 지 않습니다. 노이즈로 신호를 디더링하고 도움이되는지 확인할 수 있습니다.
나는이 질문이 다소 오래되었다는 것을 알고 있지만 최근에는 제로 크로싱을 구현해야했습니다. Dan이 제안한 방식을 구현했으며 결과에 만족합니다. 누군가 관심이 있다면 여기에 파이썬 코드가 있습니다. 정말 우아한 프로그래머가 아니에요, pls 나와 함께 곰.
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 참고 : 내 코드는 부호를 감지하지 못하고 목표 임계 값에 대한 약간의 사전 지식을 사용하여 시간 임계 값을 결정합니다. 이 임계 값은 그룹 중간 값에 가장 가까운 것을 선택하는 다중 교차 (그림의 다른 색상 점)를 그룹화하는 데 사용됩니다 (그림의 파란색 십자가).