Menentukan Frekuensi dan Periode gelombang

11

Saya mengumpulkan data suhu dari kulkas. Data terlihat seperti gelombang. Saya ingin menentukan periode dan frekuensi gelombang (sehingga saya dapat mengukur apakah modifikasi pada kulkas berpengaruh).

Saya menggunakan R, dan saya pikir saya perlu menggunakan FFT pada data, tapi saya tidak yakin ke mana harus pergi dari sana. Saya sangat baru dalam analisis R dan sinyal, jadi bantuan apa pun akan sangat dihargai!

Inilah gelombang yang saya hasilkan:

Gelombang saya

Ini kode R saya sejauh ini:

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

Saya telah memposting kode R bersama dengan database SQLite di sini .

Berikut ini adalah plot grafik yang dinormalisasi (dengan mean dihapus):

grafik dinormalisasi

Sejauh ini bagus. Berikut adalah plot kerapatan spektral:

kepadatan spektral

Kemudian kita perbesar di sisi kiri plot dan tandai indeks tertinggi (yaitu 70) dengan garis hijau:

memperbesar plot spektral

Akhirnya kami menghitung frekuensi gelombang. Gelombang ini sangat lambat, jadi kami mengonversinya menjadi menit per siklus, dan mencetak nilai tersebut yaitu 17.14286.

Berikut adalah data saya dalam format tab terbatas jika ada orang lain yang ingin mencoba.

Terima kasih untuk bantuannya! Masalah ini sulit (untuk saya) tetapi saya bersenang-senang!

Aaron Patterson
sumber
Aaron, saya pikir yang terbaik di sini adalah Anda menaruh tautan ke file data Anda (sebagai teks atau sesuatu) di dropbox, sehingga saya bisa mengunduhnya dan memberikan jawabannya. Kalau tidak, akan ada banyak bolak-balik. Saya tidak bisa melihat angka di ujung paling kiri. :-) (Juga memberi Anda tingkat sampel - yaitu, seberapa sering Anda mengambil pembacaan suhu).
Spacey
Ah maaf. Data berisi suhu dalam derajat C, saya dikonversi ke derajat F untuk grafik. Ini adalah data yang benar (ini adalah kolom "temp").
Aaron Patterson
Masalah dengan mengukur frekuensi dengan cara itu adalah bahwa jika Anda mendapatkan variabilitas yang cukup besar dari siklus ke siklus maka akan jauh lebih sulit untuk menentukan frekuensi rata-rata - puncak akan dioleskan bersama - sedangkan menghitung waktu antara kunjungan akan membuat Anda rata-rata hal-hal baik (dan juga menghitung std dev, dll). Menggunakan pendekatan FFT akan lebih dipanggil jika ada banyak suara, tapi sepertinya tidak demikian di sini.
Daniel R Hicks
+1 untuk pengeposan, kode, data, plot, dan tautan ke github.
nibot
@DanielRHicks Dalam kasus khusus ini, saya tidak berpikir itu penting, tapi ya, FFT akan memberi Anda rata-rata dari semuanya, sedangkan jika kami melakukan sesuatu seperti zero-crossing, kami akan mengukur setiap siklus durasi (frekuensi), dan kemudian kita dapat menentukan apakah kita ingin mengambil mean, median, mode, dll. Poin bagus!
Spacey

Jawaban:

7

Proyek menarik yang telah Anda lakukan di sana! :-)

Dari analisis sinyal POV, ini sebenarnya adalah pertanyaan sederhana - dan ya, Anda benar bahwa Anda akan menggunakan FFT untuk masalah estimasi frekuensi ini.

real2+imag2

Kemudian, dengan sangat sederhana, cari maks tempat duduk PSD Anda. Absis dari maks itu akan sesuai dengan frekuensi Anda.

Caveat Emptor, saya memberi Anda pandangan umum, dan saya menduga hasil FFT dalam R akan dinormalisasi frekuensi, dalam hal ini Anda harus mengetahui laju sampel Anda, (yang Anda lakukan), untuk mengubahnya kembali ke dalam Hz. Ada banyak detail penting lainnya yang saya tinggalkan, seperti resolusi frekuensi Anda, ukuran FFT, dan fakta bahwa Anda mungkin ingin mendefinisikan sinyal Anda terlebih dahulu, tetapi akan lebih baik untuk melihat plot terlebih dahulu.

EDIT:

Biarkan kami memperhitungkan sinyal Anda. Setelah saya maksudkan, itu terlihat seperti ini:

masukkan deskripsi gambar di sini

x[n]

Nfft=103600=36000.

fs=0.5Hz

x[n]X(f)10log10(|X(f)|2)

masukkan deskripsi gambar di sini

Anda dapat melihat bagaimana simetrisnya. Jika Anda mengabaikan bagian terakhir, dan lihat saja bagian pertama dan memperbesar Anda, dapat melihat ini:

masukkan deskripsi gambar di sini

FsNfft=1.3889e005Hz01.3889e005=0Hz11.3889e005=1.3889e005Hz701.3889e005=9.7222e004Hz

1(9.7222e004)60=17.14

Spacey
sumber
@ AaronPatterson Saya telah mengedit posting, silakan lihat. Anda juga dapat menambahkan gambar Anda langsung ke posting asli Anda. :-). Silakan tambahkan gambar dari hasil PSD yang Anda dapatkan.
Spacey
1
Tidak sepenuhnya benar jika frekuensi ternyata berada di antara nampan hasil FFT.
hotpaw2
@ hotpaw2 Itulah sebabnya saya memperingatkan OP bahwa saya memberikan pandangan umum, dan mengapa saya perlu melihat plotnya. Semua sama, saya telah mengedit untuk menambahkan peringatan tambahan.
Spacey
1
@ AaronPatterson Tidak masalah, senang membantu. Sejauh buku, lihat Richard Lyons "Memahami DSP" - itu adalah buku fastastic untuk memulai.
Spacey
1
1.3x105
4

Untuk bentuk gelombang yang halus dan stasioner ini, menghitung titik sampel antara penyeberangan positif dengan beberapa nilai ambang rata-rata akan memberi Anda perkiraan periode. Lihatlah beberapa periode persimpangan ambang untuk mendapatkan perkiraan yang lebih rata-rata atau mendeteksi tren apa pun.

hotpaw2
sumber
3

Tidak perlu melakukan hal yang rumit: cukup mengukur durasi antara puncak gelombang. Inilah periode. Frekuensi hanya 1 dibagi dengan periode.

Dengan sekitar 8 siklus lebih dari 2 jam, frekuensinya adalah 4 siklus per jam, atau sekitar 1 mHz.

nibot
sumber
3
Bagaimana saya bisa melakukan ini secara terprogram?
Aaron Patterson