파도의 주파수와주기 결정


11

냉장고에서 온도 데이터를 수집하고 있습니다. 데이터는 파도처럼 보입니다. 나는 파도의주기와 주파수를 결정하고 싶습니다 (냉장고에 대한 수정이 효과가 있는지 측정 할 수 있도록).

R을 사용하고 있으며 데이터에 FFT를 사용해야한다고 생각하지만 어디에서 어디로 가야할지 모르겠습니다. 저는 R 및 신호 분석에 익숙하지 않으므로 도움을 주시면 감사하겠습니다.

다음은 내가 생성하는 물결입니다.

내 파도

지금까지 내 R 코드는 다음과 같습니다.

require(graphics)
library(DBI)
library(RSQLite)

drv <- dbDriver("SQLite")
conn <- dbConnect(drv, dbname = "s.sqlite3")

query <- function(con, query) {
  rs <- dbSendQuery(con, query)
  data <- fetch(rs, n = -1)
  dbClearResult(rs)
  data
}

box <- query(conn, "
SELECT id,
       humidity / 10.0 as humidity,
       temp / 10.0 as temp,
       ambient_temp / 10.0 as ambient_temp,
       ambient_humidity / 10.0 as ambient_humidity,
       created_at
FROM measurements ORDER BY id DESC LIMIT 3600
")

box$x <- as.POSIXct(box$created_at, tz = "UTC")

box$x_n <- box$temp - mean(box$temp)
png(filename = "normalized.png", height = 750, width = 1000, bg = "white")
plot(box$x, box$x_n, type="l")

# Pad the de-meaned signal so the length is 10 * 3600
N_fft  <- 3600 * 10
padded <- c(box$x_n, seq(0, 0, length= (N_fft - length(box$x_n))))
X_f    <- fft(padded)
PSD    <- 10 * log10(abs(X_f) ** 2)

png(filename = "PSD.png", height = 750, width = 1000, bg = "white")
plot(PSD, type="line")

zoom <- PSD[1:300]

png(filename = "zoom.png", height = 750, width = 1000, bg = "white")
plot(zoom, type="l")

# Find the index with the highest point on the left half
index <- which(PSD == max(PSD[1:length(PSD) / 2]))

# Mark it in green on the zoomed in graph
abline(v = index, col="green")

f_s     <- 0.5 # sample rate in Hz
wave_hz <- index * (f_s / N_fft)
print(1 / (wave_hz * 60))

R 코드를 SQLite 데이터베이스와 함께 여기에 게시했습니다 .

다음은 정규화 된 그래프의 플롯입니다 (평균이 제거 된 상태).

정규화 된 그래프

여태까지는 그런대로 잘됐다. 스펙트럼 밀도 플롯은 다음과 같습니다.

스펙트럼 밀도

그런 다음 플롯의 왼쪽을 확대하고 가장 높은 색인 (70)을 녹색 선으로 표시합니다.

스펙트럼 플롯 확대

마지막으로 파도의 주파수를 계산합니다. 이 물결은 매우 느리기 때문에주기 당 분으로 변환하고 17.14286의 값을 인쇄합니다.

다음은 탭에서 내 데이터 형식을 구분 다른 사람이 시도하고자하는 경우.

도와 주셔서 감사합니다! 이 문제는 어려웠지만 (나를 위해) 좋은 시간을 보냈습니다!


애런, 여기에 가장 좋은 점은 드롭 박스에 데이터 파일 (텍스트 또는 무언가로)에 대한 링크를 넣어서 다운로드하여 답변을 얻는 것입니다. 그렇지 않으면 많은 것들이왔다 갔다 할 것입니다. 가장 왼쪽 끝에있는 숫자를 만들 수 없습니다. :-) (또한 샘플 속도를 제공합니다. 즉, 온도를 얼마나 자주 측정하는지)
Spacey

아 죄송합니다 데이터에 온도가 C로 표시되어 그래프의 F로 변환되었습니다. 그러나 올바른 데이터입니다 ( "temp"열임).
Aaron Patterson 2016 년

그런 식으로 주파수를 측정하는 문제는 사이클마다 상당한 변동이 발생하면 평균 주파수를 결정하기가 훨씬 어려워지고 피크가 함께 번지는 것입니다. (또한 std dev 등을 계산하십시오). 소음이 많으면 FFT 접근 방식을 사용하는 것이 더 필요하지만 여기서는 그렇지 않습니다.
Daniel R은

게시, 코드, 데이터, 플롯 및 github에 대한 링크는 +1입니다.
nibot

@DanielRHicks이 특별한 경우에, 나는 그것이 중요하지 않다고 생각하지만, 예, FFT는 그들 모두의 평균을 줄 것입니다. 그리고 우리는 평균, 중간 값, 모드 등을 취할 것인지 결정할 수 있습니다. 좋은 지적입니다!
Spacey

답변:


7

흥미로운 프로젝트가 있습니다! :-)

신호 분석 POV에서 이것은 실제로 간단한 질문입니다. 그렇습니다.이 주파수 추정 문제에 FFT를 사용하는 것이 옳습니다.

나는 R에 익숙하지 않지만, 당신이 본질적으로하고 싶은 것은 온도 신호의 FFT를 취하는 것입니다. 신호가 실제이므로 FFT의 출력으로 복잡한 결과를 얻을 수 있습니다. 이제 복잡한 FFT 결과의 절대 크기 제곱을 취할 수 있습니다 (위상에 신경 쓰지 않기 때문에). 즉, 입니다. 이것이 파워 스펙트럼 밀도입니다.real2+imag2

그런 다음 매우 간단하게 PSD가있는 최대 위치를 찾으십시오. 최대 값의 가로 좌표는 주파수와 일치합니다.

Caveat Emptor, 나는 당신에게 일반적인 전망을 제공하고 있으며, R에서 FFT의 결과가 정규화 주파수가 될 것이라고 생각합니다.이 경우 다시 변환하려면 샘플 속도 (당신이하는)를 알아야합니다 Hz로. 주파수 분해능, FFT 크기 및 신호를 먼저 의미를 없애고 싶지만 먼저 플롯을 보는 것이 좋습니다.

편집하다:

신호를 고려하겠습니다. 의미를 제거한 후에는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

DC 바이어스는 기술적으로 0Hz의 주파수이기 때문에 의미를 잃어 버리고 다른 관심 주파수를 익사시키지 않기를 바랍니다. 이 측정되지 않은 신호 이라고하자 .x[n]

이제 FFT를받을 때 몇 가지 세부 사항을주의해야합니다. 신호 길이의 10 배인 FFT 길이를 사용하므로 이라고 말할 수 있습니다 . 원래 신호의 크기보다 큰 FFT 크기는 FFT 결과를 보간하는 효과가 있습니다. 주파수 영역에서. 정보 이론 POV에서 정보를 추가하지는 않지만, 특히 두 주파수 빈 사이에있는 경우 실제 피크가 어디에 있는지 정확하게 식별하는 데 도움이됩니다. 얻으려면 사실 더 나은 주파수 해상도를, 당신은 더 많은 데이터를 얻을 싶어요. (즉, 센서를 더 오랫동안 작동 시키십시오).Nfft=103600=36000.

텍스트 파일에서 센서가 2 초마다 온도를 측정하는 것으로 나타났습니다. 즉 , 샘플링 속도 또는fs=0.5Hz

따라서 FFT 가져 와서 그 결과를 합니다. 이 결과는 복잡 할 것이며 실제로는 공액 대칭이지만 여기서는 중요하지 않습니다. (그것은 단지 당신의 목적을 위해, 그중 절반은 중복됨을 의미합니다) 이제 을 취하면 이것이 전력 스펙트럼 밀도 (로그 스케일)입니다. 결과는 다음과 같습니다.x[n]X(f)10log10(|X(f)|2)

여기에 이미지 설명을 입력하십시오

대칭이 어떻게되는지 확인할 수 있습니다. 마지막 절반을 무시하고 처음 절반을보고 확대하면 다음을 볼 수 있습니다.

여기에 이미지 설명을 입력하십시오

따라서 지수 70에서 최고점을 기록했습니다! 그러나 실제 주파수 용어로 인덱스 70은 무엇입니까? 주파수 분해능을 원하는 곳입니다. 이를 계산하기 위해 간단히 합니다. 이것은 모든 인덱스가이 숫자의 배수 인 빈도를 나타냄을 의미합니다. 인덱스 0은 입니다. 인덱스 1은 입니다. 인덱스 70은 입니다.FsNfft=1.3889e005Hz01.3889e005=0Hz11.3889e005=1.3889e005Hz701.3889e005=9.7222e004Hz

우리는 거의 끝났습니다. 이제이 숫자를 얻었으므로 더 맛있는 것으로 변환 할 수 있습니다. 이 수치는 신호가 초당 9.7222e-004 사이클을 완료한다는 것을 나타냅니다. 한 사이클을 계산하는 데 몇 분이 걸립니까? 따라서 주기 당 분입니다.1(9.7222e004)60=17.14


@AaronPatterson 게시물을 편집했습니다. 참조하십시오. 또한 사진을 원본 게시물에 직접 추가 할 수도 있습니다. :-). 얻은 PSD 결과 이미지를 추가하십시오.
Spacey

1
주파수가 FFT 결과 빈 사이에있는 경우 정확하지 않습니다.
hotpaw2 2016 년

@ hotpaw2 그렇기 때문에 OP에 일반적인 전망을 제공하고 플롯을보아야하는 이유를 경고했습니다. 모두 동일하게 추가 경고를 추가하도록 편집했습니다.
Spacey

1
@AaronPatterson 문제 없습니다. 기꺼이 도와 드리겠습니다. 책까지는 Richard Lyons "DSP 이해"를 살펴보십시오.이 책은 가장 빠른 책입니다.
Spacey

1
@ 프랭크 그것은 단지 지수입니다. 예를 들어 입니다. 1.3x105
Spacey

4

이 매끄럽고 고정 된 파형의 경우, 일부 평균 임계 값의 양의 교차점 사이에서 샘플 포인트를 계산하면주기 추정값이 제공됩니다. 보다 평균적인 추정치를 얻거나 추세를 감지하려면 몇 개의 임계 값 교차 기간을 살펴보십시오.


3

복잡한 작업을 수행 할 필요가 없습니다. 파형 피크 사이의 지속 시간 만 측정하면됩니다. 이것은 기간입니다. 주기는 1로 나눈 값입니다.

2 시간에 걸쳐 약 8 주기로, 주파수는 시간당 4주기 또는 약 1mHz입니다.


3
프로그래밍 방식으로 어떻게 할 수 있습니까?
Aaron Patterson 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.