我正在从冰箱中收集温度数据。数据看起来像波浪。我想确定波浪的周期和频率(以便我可以测量对冰箱的修改是否有效果)。

我正在使用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。 >
谢谢您的帮助!这个问题对我来说很难,但我过得很愉快!

评论

亚伦,我认为最好的办法是将您指向数据文件的链接(文本或其他内容)放置在保管箱上,以便我下载该文件并给您答案。否则,将会有很多来回的事情。我无法找出最左端的数字。 :-)(也可以给您采样率-也就是说,您多久获取一次温度读数)。

啊对不起数据包含以摄氏度为单位的温度,我将该图转换为华氏度。不过,它是正确的数据(它是“ temp”列)。

以这种方式测量频率的问题在于,如果每个周期之间存在较大的可变性,则确定平均频率将变得更加困难-峰值会相互混淆-而仅计算两次偏移之间的时间将使您可以很好地对事物进行平均(以及计算std dev等)。如果存在很多噪声,则更需要使用FFT方法,但在这里似乎并非如此。

+1用于发布,代码,数据,图解以及指向github的链接。

@DanielRHicks在这种特殊情况下,我认为这并不重要,但是,是的,FFT将为您提供所有这些函数的平均值,而如果我们做过零的操作,我们将测量每个周期的持续时间(频率)然后我们可以确定是否要取均值,中位数,众数等。很好!!

#1 楼

您正在进行的有趣项目! :-)

从信号分析POV来看,这实际上是一个简单的问题-是的,您是对的,您可以将FFT用于此频率估计问题。

我对R并不熟悉,但是您实际上想要做的是对温度信号进行FFT。由于您的信号是真实的,因此您将获得复杂的结果作为FFT的输出。现在,您可以采用复杂FFT结果的绝对幅度平方(因为我们不在乎相位)。即$ real ^ 2 + imag ^ 2 $。这是您的功率谱密度。

然后,非常简单地找到PSD所在的最大值。该最大值的横坐标将对应于您的频率。

Caveat Emptor,我给您一个大致的看法,我怀疑R中FFT的结果将是归一化频率,在这种情况下,您将必须知道您的采样率,( ),以便将其转换回Hz。我遗漏了许多其他重要的细节,例如您的频率分辨率,FFT大小,以及您可能想先去除信号平均值的事实,但是最好先查看图表。

编辑:

让我们考虑您的信号。在我消除均值之后,它看起来像这样:



您要消除均值,因为技术上DC偏置的频率为0 Hz,您可以不想让它淹没其他感兴趣的频率。让我们称此为非均值信号$ x [n] $。

现在,当您进行FFT运算时,必须注意一些细节。我使用的FFT长度是信号长度的10倍,因此我们可以说$ N_ {fft} = 10 * 3600 = 36000. $任何设置为大于原始信号大小的FFT大小都会对您的信号进行内插FFT产生频域。尽管这不会从信息论POV中为您添加任何信息,但它确实可以帮助您更好地识别出真正的峰值位于何处,尤其是在两个频点之间的情况下。为了获得真正更好的频率分辨率,您想获取更多数据。 (即,让传感器运行更长的时间)。

从文本文件来看,我发现您的传感器每2秒获取一次温度读数。这意味着您的采样率,即$ f_s = 0.5 Hz该结果将是复杂的,并且实际上是共轭对称的,但这在这里并不重要。 (这只是出于您的目的,其中一半是多余的)。现在,如果我们取$ 10log_ {10}(| X(f)| ^ {2})$,这就是功率谱密度(以对数标度表示)。结果如下所示:



您可以看到它是如何对称的。如果您忽略后半部分,而只是看一下前半部分并进行放大,则会看到以下内容:但是实际频率指数是多少?这是您想要的频率分辨率的地方。为了进行计算,我们只需取\\ frac {F_s} {N_ {fft}} = 1.3889e-005 Hz $。这仅表示每个索引代表的频率是该数字的倍数。索引0为$ 0 * 1.3889e-005 = 0 Hz $。索引1是$ 1 * 1.3889e-005 = 1.3889e-005 Hz $。索引70为$ 70 * 1.3889e-005 = 9.7222e-004 Hz $。

我们快完成了。现在您已经有了这个数字,我们可以将其转换为更可口的东西。这个数字只是说您的信号每秒完成9.7222e-004个周期。因此,我们可以问一下,计算一个周期需要多少分钟?因此,每个周期$ \ frac {1} {(9.7222e-004)* 60} = 17.14 $分钟。

评论


$ \ begingroup $
@AaronPatterson我已经编辑了帖子,请参阅。另外,您可以将图片直接添加到原始帖子中。 :-)。请添加您获得的PSD结果的图像。
$ \ endgroup $
–太空
2012年6月2日19:18



$ \ begingroup $
如果频率结果在FFT结果块之间,则不完全正确。
$ \ endgroup $
– hotpaw2
2012年6月2日21:15

$ \ begingroup $
@ hotpaw2这就是为什么我警告OP我要给出总体观点,以及为什么我需要看情节的原因。都一样,我进行了编辑以添加其他警告。
$ \ endgroup $
–太空
2012年6月2日21:35



$ \ begingroup $
@AaronPatterson没问题,很高兴为您提供帮助。至于书籍,请看Richard Lyons的“ Understanding DSP”-这是一本入门的快速书。
$ \ endgroup $
–太空
2012年6月4日20:57

$ \ begingroup $
@Frank这只是一个指数。例如,$ 1.3 \ text {x} 10 ^ {-5} $。
$ \ endgroup $
–太空
2014年1月20日12:54



#2 楼

对于这种平稳的波形,在某个平均阈值的正向相交之间计数采样点将为您提供周期估计。查看几个阈值穿越期,以获得更平均的估计或检测任何趋势。

#3 楼

无需做任何复杂的事情:只需测量波形峰值之间的持续时间即可。这是时期。频率仅是1除以周期。

在2个小时中大约有8个周期,频率是每小时4个周期,或大约1 mHz。

评论


$ \ begingroup $
如何以编程方式执行此操作?
$ \ endgroup $
–亚伦·帕特森(Aaron Patterson)
2012年6月2日21:10