Xác định tần số và chu kỳ của sóng


11

Tôi đang thu thập dữ liệu nhiệt độ từ tủ lạnh. Dữ liệu trông giống như một con sóng. Tôi muốn xác định chu kỳ và tần số của sóng (để tôi có thể đo nếu sửa đổi cho tủ lạnh có ảnh hưởng gì không).

Tôi đang sử dụng R và tôi nghĩ rằng tôi cần sử dụng FFT trên dữ liệu, nhưng tôi không chắc sẽ đi đâu từ đó. Tôi rất mới với R và phân tích tín hiệu, vì vậy bất kỳ trợ giúp sẽ được đánh giá rất cao!

Đây là làn sóng tôi đang sản xuất:

Sóng của tôi

Đây là mã R của tôi cho đến nay:

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

Tôi đã đăng mã R cùng với cơ sở dữ liệu SQLite tại đây .

Dưới đây là một biểu đồ của đồ thị chuẩn hóa (với giá trị trung bình bị loại bỏ):

đồ thị chuẩn hóa

Càng xa càng tốt. Dưới đây là biểu đồ mật độ phổ:

mật độ phổ

Sau đó, chúng tôi phóng to ở bên trái của âm mưu và đánh dấu chỉ số cao nhất (là 70) bằng một đường màu xanh lá cây:

phóng to biểu đồ quang phổ

Cuối cùng, chúng tôi tính toán tần số của sóng. Sóng này rất chậm, vì vậy chúng tôi chuyển đổi nó thành phút trong mỗi chu kỳ và in ra giá trị đó là 17.14286.

Đây là dữ liệu của tôi ở định dạng được phân định bằng tab nếu có ai muốn thử.

Cảm ơn đã giúp đỡ! Vấn đề này thật khó khăn (đối với tôi) nhưng tôi đã có một khoảng thời gian tuyệt vời!


Aaron, tôi nghĩ điều tốt nhất ở đây là cho bạn đặt một liên kết đến tệp dữ liệu của bạn (dưới dạng văn bản hoặc một cái gì đó) trên một hộp nhỏ, để tôi có thể tải xuống và cho bạn câu trả lời. Nếu không, sẽ có rất nhiều đi lại. Tôi không thể tạo ra các con số ở phía xa bên trái. :-) (Cũng cung cấp cho bạn tỷ lệ mẫu - nghĩa là tần suất bạn đang đọc nhiệt độ).
Spacey

Ồ xin lỗi. Dữ liệu chứa nhiệt độ tính bằng độ C, tôi chuyển đổi sang độ F cho biểu đồ. Đây là dữ liệu chính xác (đó là cột "tạm thời").
Aaron Patterson

Vấn đề với việc đo tần số theo cách đó là nếu bạn có được sự thay đổi đáng kể từ chu kỳ này sang chu kỳ khác thì việc xác định tần số trung bình sẽ khó khăn hơn nhiều - trong khi việc đếm thời gian giữa các chuyến du lịch sẽ cho phép bạn trung bình mọi thứ tốt đẹp (và cũng tính std dev, v.v.). Sử dụng phương pháp FFT sẽ được gọi nhiều hơn nếu có nhiều tiếng ồn, nhưng dường như đó không phải là trường hợp ở đây.
Daniel R Hicks

+1 để đăng bài, mã, dữ liệu, lô và liên kết đến github.
nibot

@DanielRHicks Trong trường hợp cụ thể này, tôi không nghĩ nó có vấn đề, nhưng vâng, FFT sẽ cung cấp cho bạn mức trung bình của tất cả chúng, trong khi nếu chúng tôi làm một cái gì đó giống như giao nhau, chúng tôi sẽ đo từng khoảng thời gian chu kỳ (tần số), và sau đó chúng ta có thể xác định xem chúng ta có muốn lấy trung bình, trung vị, chế độ, v.v. Điểm tốt!
Spacey

Câu trả lời:


7

Dự án thú vị mà bạn đang thực hiện ở đó! :-)

Từ phân tích tín hiệu POV, đây thực sự là một câu hỏi đơn giản - và vâng, bạn đúng rằng bạn sẽ sử dụng FFT cho vấn đề ước tính tần số này.

Tôi không quen thuộc với R, nhưng những gì bạn thực sự muốn làm là lấy FFT của tín hiệu nhiệt độ của bạn. Vì tín hiệu của bạn là có thật, bạn sẽ nhận được một kết quả phức tạp là đầu ra của FFT của bạn. Bây giờ bạn có thể lấy bình phương độ lớn tuyệt đối của kết quả FFT phức tạp của bạn, (vì chúng tôi không quan tâm đến pha). Đó là, . Đây là mật độ phổ sức mạnh của bạn.real2+imag2

Sau đó, rất đơn giản, tìm tối đa nơi PSD của bạn nằm. Các abscissa của max đó sẽ tương ứng với tần số của bạn.

Hãy cẩn thận, tôi đang đưa ra một triển vọng chung và tôi nghi ngờ kết quả của FFT trong R sẽ là tần số chuẩn hóa, trong trường hợp đó bạn sẽ phải biết tỷ lệ mẫu của mình, (mà bạn làm), để chuyển đổi lại thành Hz. Có nhiều chi tiết quan trọng khác mà tôi đang bỏ qua, chẳng hạn như độ phân giải tần số, kích thước FFT của bạn và thực tế là bạn có thể muốn khử tín hiệu của bạn trước, nhưng sẽ rất tốt khi xem âm mưu trước.

BIÊN TẬP:

Hãy để chúng tôi đưa tín hiệu của bạn vào tài khoản. Sau khi tôi không có ý đó, nó trông như thế này:

nhập mô tả hình ảnh ở đây

Bạn muốn hủy bỏ ý nghĩa vì độ lệch DC là tần số 0 Hz về mặt kỹ thuật và bạn không muốn nó bị nhấn chìm các tần số quan tâm khác. Hãy để chúng tôi gọi tín hiệu không có nghĩa này .x[n]

Bây giờ, khi bạn thực hiện FFT, bạn phải chú ý một số chi tiết. Tôi sử dụng độ dài FFT gấp 10 lần độ dài của tín hiệu, vì vậy chúng ta có thể nói rằng Bất kỳ kích thước FFT nào được đặt lớn hơn kích thước của tín hiệu gốc đều có tác dụng nội suy kết quả FFT của bạn trong miền tần số. Mặc dù điều này không thêm bất kỳ thông tin nào cho bạn từ lý thuyết thông tin POV, nhưng nó giúp bạn nhận thức rõ hơn về vị trí chính xác của bạn, đặc biệt là trong trường hợp nó nằm giữa hai thùng tần số. Để có được độ phân giải tần số thực sự tốt hơn, bạn muốn nhận được nhiều dữ liệu hơn. (nghĩa là để cảm biến chạy trong một khoảng thời gian dài hơn).Nfft=103600=36000.

Di chuyển dọc, từ tệp văn bản, tôi thấy rằng cảm biến của bạn đang đọc nhiệt độ cứ sau 2 giây. Điều này có nghĩa là tốc độ lấy mẫu của bạn , hoặcfs=0.5Hz

Do đó, chúng ta hãy lấy FFT là và gọi kết quả đó là . Kết quả này sẽ phức tạp và trên thực tế, nó là đối xứng liên hợp, nhưng điều đó không quan trọng ở đây. (Nó chỉ có nghĩa cho mục đích của bạn, một nửa trong số đó là dư thừa). Bây giờ nếu chúng ta lấy , thì đây là mật độ phổ công suất (theo thang đo log). Kết quả trông giống như vậy:x[n]X(f)10log10(|X(f)|2)

nhập mô tả hình ảnh ở đây

Bạn có thể thấy nó đối xứng như thế nào. Nếu bạn bỏ qua nửa cuối và chỉ cần nhìn vào nửa đầu và phóng to bạn, có thể thấy điều này:

nhập mô tả hình ảnh ở đây

Vì vậy, bạn có một đỉnh ở chỉ số 70! Nhưng chỉ số 70 về tần số thực là gì? Đây là nơi bạn muốn độ phân giải tần số của bạn. Để tính toán điều đó, chúng tôi chỉ cần lấy . Điều này đơn giản có nghĩa là mọi chỉ số đại diện cho một tần số là bội số của số này. Chỉ số 0 là . Chỉ số 1 là . Chỉ số 70 là .0*1,3889e-005=0Hz1*1,3889e-005=1,3889e-005Hz70*1,3889e-005=9,7222e-004HzFsNfft=1.3889e005Hz01.3889e005=0Hz11.3889e005=1.3889e005Hz701.3889e005=9.7222e004Hz

Chúng ta đang gần hoàn tất. Bây giờ bạn có con số này, chúng ta có thể chuyển đổi nó thành một cái gì đó ngon miệng hơn. Con số này chỉ nói rằng tín hiệu của bạn hoàn thành các chu kỳ 9.722e-004 mỗi giây. Vì vậy, chúng ta có thể hỏi, mất bao nhiêu phút để tính một chu kỳ? Do đó, phút mỗi chu kỳ.1(9.7222e004)60=17.14


@AaronPatterson Tôi đã chỉnh sửa bài viết, vui lòng xem. Ngoài ra, bạn có thể thêm hình ảnh của bạn trực tiếp vào bài viết gốc của bạn. :-). Vui lòng thêm một hình ảnh của kết quả PSD mà bạn nhận được.
Spacey

1
Không chính xác nếu tần số hóa ra nằm giữa các thùng kết quả FFT.
hotpaw2

@ hotpaw2 Đó là lý do tại sao tôi đã cảnh báo OP rằng tôi đang đưa ra quan điểm chung và tại sao tôi cần xem cốt truyện. Tất cả đều giống nhau, tôi đã chỉnh sửa để thêm các cảnh báo thêm.
Spacey

1
@AaronPatterson Không có vấn đề, vui lòng giúp đỡ. Theo như sách, hãy xem Richard Lyons "Hiểu DSP" - đó là một cuốn sách nhanh để bắt đầu.
Spacey

1
1.3x105

4

Đối với dạng sóng mịn và ổn định này, việc đếm các điểm mẫu giữa các điểm giao nhau dương của một số giá trị ngưỡng trung bình sẽ cho bạn ước tính thời gian. Nhìn vào một số giai đoạn vượt ngưỡng để có ước tính trung bình hơn hoặc phát hiện bất kỳ xu hướng nào.


3

Không cần phải làm gì phức tạp: chỉ cần đo thời lượng giữa các đỉnh của dạng sóng. Đây là thời kỳ. Tần số chỉ là 1 chia cho thời gian.

Với khoảng 8 chu kỳ trong hơn 2 giờ, tần số là 4 chu kỳ mỗi giờ, hoặc khoảng 1 mHz.


3
Làm thế nào tôi có thể làm điều này lập trình?
Aaron Patterson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.