Bir dalganın frekansını ve periyodunu belirleme


11

Buzdolabından sıcaklık verileri topluyorum. Veriler bir dalgaya benziyor. Dalganın periyodunu ve sıklığını belirlemek istiyorum (böylece buzdolabındaki değişikliklerin herhangi bir etkisi olup olmadığını ölçebilirim).

R kullanıyorum ve veri üzerinde bir FFT kullanmam gerektiğini düşünüyorum, ama oradan nereye gideceğimi bilmiyorum. R ve sinyal analizinde çok yeniyim, bu yüzden herhangi bir yardım çok takdir edilecektir!

İşte ürettiğim dalga:

Benim dalga

İşte şimdiye kadar benim R kodu:

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

Burada SQLite veritabanı ile birlikte R kodunu gönderdim .

İşte normalleştirilmiş grafiğin bir grafiği (ortalama kaldırılmış olarak):

normalleştirilmiş grafik

Çok uzak çok iyi. İşte spektral yoğunluk grafiği:

spektral yoğunluk

Sonra grafiğin sol tarafını yakınlaştırırız ve en yüksek endeksi (70 olan) yeşil bir çizgiyle işaretleriz:

spektral çizimi büyüt

Son olarak dalganın frekansını hesaplıyoruz. Bu dalga çok yavaş, bu yüzden onu döngü başına dakikaya dönüştürüyoruz ve 17.14286 olan bu değeri yazdırıyoruz.

İşte sekmede verilerim ayrılmış biçim başkasının denemek istiyorsa.

Yardım için teşekkürler! Bu sorun (benim için) zordu ama harika zaman geçirdim!


Aaron, bence buradaki en iyi şey veri dosyanıza bir bağlantı (metin veya başka bir şey olarak) bir dropbox'a koymanızdır, böylece indirebilir ve size cevap verebilirim. Aksi takdirde ileri geri gidecek çok şey olacaktır. En soldaki sayıları çıkaramıyorum. :-) (Ayrıca örnek oranı verin - yani, ne sıklıkla bir sıcaklık okuması alıyorsunuz).
Spacey

Ah Üzgünüm. Veriler C derece cinsinden sıcaklık içerir, grafik için F derecesine dönüştürülür. Doğru veri olsa da ("temp" sütunu).
Aaron Patterson

Frekansı bu şekilde ölçmeyle ilgili sorun, döngüden devire önemli ölçüde değişkenlik elde ederseniz, ortalama frekansı belirlemenin çok daha zor olacağıdır - zirveler birlikte bulaşır - oysa geziler arasındaki zamanı saymak, ortalama şeyleri güzel bir şekilde değerlendirmenize izin verir. (ve ayrıca std dev, vb hesaplamak). Çok fazla gürültü olsaydı, FFT yaklaşımını kullanmak daha çok çağrılacaktı, ama burada durum böyle görünmüyor.
Daniel R Hicks

Gönderme, kod, veri, grafikler ve github bağlantısı için +1.
nibot

@DanielRHicks Bu özel durumda, bunun önemli olduğunu düşünmüyorum, ancak evet, FFT size hepsinin ortalamasını verecektir, oysa sıfır geçiş gibi bir şey yaparsak, her döngü süresini (frekans) ölçeriz, ve sonra ortalama, medyan, mod vb. almak isteyip istemediğimizi belirleyebiliriz. İyi bir nokta!
Spacey

Yanıtlar:


7

Orada devam ettiğiniz ilginç bir proje! :-)

Bir sinyal analizi POV'sinden, bu aslında basit bir sorudur - ve evet, bu frekans tahmin problemi için FFT'yi kullanacağınız konusunda haklısınız.

R'ye aşina değilim, ama esas olarak yapmak istediğiniz şey sıcaklık sinyalinizin FFT'sini almak. Sinyaliniz gerçek olduğundan, FFT'nizin çıkışı olarak karmaşık bir sonuç elde edersiniz. Artık karmaşık FFT sonucunuzun mutlak büyüklüğünü kareye alabilirsiniz (çünkü fazı önemsemiyoruz). Yani, . Bu sizin güç spektral yoğunluğunuzdur.real2+imag2

Sonra, çok basit bir şekilde, PSD'nizin oturduğu maksimum yeri bulun. Bu maksimumun apsisi frekansınıza karşılık gelecektir.

Uyarıcı Emptor, size genel bir görünüm veriyorum ve R'deki FFT'nin sonucunun normalleştirilmiş frekans olacağından şüpheleniyorum, bu durumda geri dönüştürmek için örnek oranınızı (yaptığınız) bilmek zorunda kalacaksınız Hz. Frekans çözünürlüğünüz, FFT boyutunuz ve muhtemelen önce sinyalinizi kastetmek istediğiniz gerçeği gibi dışarıda bıraktığım birçok önemli ayrıntı var, ancak önce bir arsa görmek iyi olacak.

DÜZENLE:

Sinyalinizi dikkate alalım. Bunu kastettikten sonra şöyle görünüyor:

resim açıklamasını buraya girin

DC sapması teknik olarak 0 Hz'lik bir frekans olduğu ve bunun diğer ilgi frekanslarını boğmasını istemediğiniz için kast etmek istersiniz. Bu kasıtlı olmayan işaret diyelim .x[n]

Şimdi, FFT'yi aldığınızda, bazı ayrıntılara dikkat etmelisiniz. Sinyalin uzunluğunun 10 katı bir FFT uzunluğu kullanıyorum, bu yüzden olduğunu söyleyebiliriz . Orijinal sinyalden daha büyük bir FFT boyutunun FFT sonucunuzu enterpolasyon etkisi vardır frekans alanında. Bu, bir bilgi teorisi POV'sinden sizin için herhangi bir bilgi eklemese de, özellikle iki frekans bölmesi arasında olduğu durumlarda, gerçek zirvenizin tam olarak nerede olduğunu daha iyi fark etmenize yardımcı olur. Almak için gerçek daha iyi frekans çözünürlüğü, daha fazla veri almak istiyorum. (yani, sensörü daha uzun süre çalıştırın).Nfft=103600=36000.

Metin dosyasından hareket ederken, sensörünüzün her 2 saniyede bir sıcaklık okumaları aldığını görüyorum. Bu, örnekleme oranınızın veya olduğu anlamına gelirfs=0.5Hz

Böylece, nin bir FFT'sini alalım ve bu sonucu . Bu sonuç karmaşık olacak ve aslında, eşlenik simetrik, ama burada önemli değil. (Bu sadece sizin amaçlarınız için anlamına gelir, yarısı yedeklidir). Şimdi , bu güç spektral yoğunluğudur (log ölçeğinde). Sonuç şöyle görünür:x[n]X(f)10log10(|X(f)|2)

resim açıklamasını buraya girin

Nasıl simetrik olduğunu görebilirsiniz. Son yarıyı görmezden gelir ve sadece ilk yarıyı inceler ve yakınlaştırırsanız, bunu görebilirsiniz:

resim açıklamasını buraya girin

Dizin 70'te bir zirve var! Peki endeks 70 gerçek frekans açısından nedir? Frekans çözünürlüğünüzü istediğiniz yer burasıdır. Bunu hesaplamak için sadece . Bu, her indeksin bu sayının katı olan bir frekansı temsil ettiği anlamına gelir. Endeks 0, . Dizin 1, . Dizin 70, .01.3889e-005=0Hz11.3889e-005=1.3889e-005Hz701.3889e-005=9.7222e-004HzFsNfft=1.3889e005Hz01.3889e005=0Hz11.3889e005=1.3889e005Hz701.3889e005=9.7222e004Hz

Neredeyse bitti. Şimdi bu rakama sahip olduğunuza göre, daha lezzetli bir şeye dönüştürebiliriz. Bu rakam sadece sinyalinizin saniyede 9.7222e-004 döngüsünü tamamladığını söylüyor. Öyleyse bir döngüyü hesaplamanın kaç dakika sürdüğünü sorabiliriz. Böylece, döngü başına dakika.1(9.7222e004)60=17.14


@AaronPatterson Gönderiyi düzenledim, lütfen bakın. Ayrıca, resimlerinizi doğrudan orijinal postanıza ekleyebilirsiniz. :-). Lütfen aldığınız PSD sonucunun bir görüntüsünü ekleyin.
Spacey

1
FFT sonuç bölmeleri arasında olduğu ortaya çıkarsa tam olarak doğru değildir.
hotpaw2

@ hotpaw2 Bu yüzden OP'yi genel bir bakış açısı verdiğimi ve neden komployu görmem gerektiğini uyardım. Yine de, ilave uyarılar eklemek için editörlük yaptım.
Spacey

1
@AaronPatterson Sorun değil, yardımcı olmaktan memnuniyet duyarız. Kitaplara gelince, Richard Lyons'ın "DSP'yi Anlamak" a bakın - bu başlamak için büyüleyici bir kitap.
Spacey

1
@Frank Bu sadece bir üstel. . 1.3x105
Spacey

4

Bir dalga şekli için bu pürüzsüz ve sabit, bazı ortalama eşik değerlerin pozitif gidiş geçişleri arasındaki örnek noktaları saymak size bir dönem tahmini verecektir. Daha ortalama bir tahmin almak veya herhangi bir eğilimi tespit etmek için birkaç eşik geçiş dönemine bakın.


3

Karmaşık bir şey yapmaya gerek yoktur: sadece dalga formunun zirveleri arasındaki süreyi ölçün. Bu dönem. Frekans, döneme göre sadece 1'dir.

2 saatte yaklaşık 8 döngü ile, frekans saatte 4 döngü veya yaklaşık 1 mHz'dir.


3
Bunu programlı olarak nasıl yapabilirim?
Aaron Patterson
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.