波の周波数と周期の決定


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

SQLiteデータベースと一緒にRコードをここに投稿しまし

これは、正規化されたグラフのプロットです(平均が削除されています)。

正規化されたグラフ

ここまでは順調ですね。これはスペクトル密度のプロットです:

スペクトル密度

次に、プロットの左側を拡大し、最高のインデックス(70)を緑の線でマークします。

スペクトルプロットを拡大する

最後に、波の周波数を計算します。この波は非常に遅いため、1サイクルあたりの分数に変換し、その値である14.14286を出力します。

ここにあるタブの私のデータ形式を区切り誰にも試してみたい場合。

助けてくれてありがとう!この問題は(私にとって)困難でしたが、素晴らしい時間を過ごしました!


アーロン、ここで一番いいのは、ドロップボックスにデータファイルへのリンク(テキストなど)を配置して、ダウンロードして答えを出せるようにすることです。そうでなければ、多くの行き来があります。左端の数字がわかりません。:-)(サンプルレートも指定してください。つまり、温度の読み取りを行う頻度です)。
Spacey

あ、ごめんなさい。データにはC単位の温度が含まれています。グラフではFに変換しました。ただし、これは正しいデータです(「temp」列です)。
アーロンパターソン

そのように頻度を測定することの問題は、サイクルごとにかなりの変動が生じると、平均頻度を決定することがはるかに困難になることです-ピークは一緒に不鮮明になります-単にエクスカーション間の時間をカウントするだけで、物事をうまく平均化できます(そしてstd devも計算します)。ノイズが多い場合は、FFTアプローチを使用する必要がありますが、ここではそうではありません。
ダニエルRヒックス

投稿、コード、データ、プロット、githubへのリンクの+1。
nibot

@DanielRHicksこの特定のケースでは、私はそれが重要だとは思いませんが、はい、FFTはそれらすべての平均を提供しますが、ゼロクロッシングのようなことをした場合、各サイクルの持続時間(周波数)を測定します、そして、平均、中央値、最頻値などを取得するかどうかを決定できます。
Spacey

回答:


7

あなたがそこで行っている興味深いプロジェクト!:-)

信号分析のPOVから、これは実際には簡単な質問です。そして、はい、この周波数推定問題にFFTを利用するのは正しいことです。

real2+imag2

次に、非常に簡単に、PSDが置かれている場所の最大値を見つけます。その最大の横座標は周波数に対応します。

Caveat Emptor、私はあなたに一般的な見通しを与えています、そして私はRのFFTの結果が正規化された周波数であると思います、その場合、あなたはそれを変換するためにサンプルレートを知っている必要があります(そうします) Hzに。周波数分解能、FFTサイズ、最初に信号の意味を明らかにしたいなど、私が除外している他の多くの重要な詳細がありますが、最初にプロットを確認することをお勧めします。

編集:

あなたのシグナルを考慮に入れましょう。私がそれを明らかにした後、それは次のようになります:

ここに画像の説明を入力してください

x[n]

Nfft=103600=36000.

fs=0.5Hz

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

ここに画像の説明を入力してください

対称性がわかります。後半を無視して、前半を見てズームインすると、次のようになります。

ここに画像の説明を入力してください

したがって、インデックス70にピークがあります。しかし、実際の周波数でのインデックス70とは何でしょうか。ここで、周波数分解能が必要になります。それを計算するには、単純に取りますFsNfft=1.3889e005Hz01.3889e005=0Hz11.3889e005=1.3889e005Hz701.3889e005=9.7222e004Hz

1(9.7222e004)60=17.14


@AaronPatterson投稿を編集しました、ご覧ください。また、元の投稿に写真を直接追加することもできます。:-)。得られたPSD結果の画像を追加してください。
Spacey

1
周波数がFFT結果ビンの間にあることが判明した場合、正確ではありません。
hotpaw2

@ hotpaw2それが私が私に一般的な見通しを与えていることをOPに警告した理由であり、そして私はプロットを見る必要がある理由です。すべて同じように、私は追加の警告を追加するために編集しました。
Spacey

1
@AaronPatterson問題ありません。喜んでお手伝いします。書籍に関しては、Richard Lyonsの「Understanding DSP」をご覧ください。これは、始めるのが速い本です。
Spacey

1
1.3x105

4

この滑らかで定常的な波形の場合、いくつかの平均しきい値の正の交差点間のサンプルポイントをカウントすると、期間の見積もりが得られます。いくつかのしきい値超過期間を調べて、より平均的な見積もりを取得するか、傾向を検出します。


3

複雑なことをする必要はありません。波形のピーク間の期間を測定するだけです。これが期間です。頻度は、周期で割った1だけです。

2時間で約8サイクル、周波数は1時間あたり4サイクル、つまり約1 mHzです。


3
これをプログラムでどのように実行できますか?
アーロンパターソン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.