打印

授之以渔: 几个例子弄清复立叶变换的应用

[复制链接]
楼主: highgear
手机看帖
扫描二维码
随时随地手机跟帖
21
我不怕系统认为我恶意灌水,为了给LZ动力,我狂顶!

使用特权

评论回复
22
yuyi21ic| | 2010-8-29 15:39 | 只看该作者
我不怕系统认为我恶意灌水,为了给LZ动力,我狂顶!

使用特权

评论回复
23
David_ming| | 2010-8-29 16:24 | 只看该作者
很少见有好的傅里叶变换的**,

使用特权

评论回复
24
123jj| | 2010-8-29 17:18 | 只看该作者
本帖最后由 123jj 于 2010-8-29 17:19 编辑

22# yuyi21ic


LS的签名有趣,

每天清晨醒后,伴着初升的太阳,朝着maychang,NE5532,awey,ic921,程疗匠人的积分奋力追赶。一日一追,一追一日。

程疗匠人积分奋力追赶???一日一追,一追一日。

那你21IC的网都不用上了,呵呵! ;P

使用特权

评论回复
25
123jj| | 2010-8-29 17:22 | 只看该作者
截图留念,呵呵!


使用特权

评论回复
26
ert34| | 2010-8-29 18:11 | 只看该作者
不懂啊,大学没过数字信号处理,郁闷

使用特权

评论回复
27
odqqdo| | 2010-8-29 19:04 | 只看该作者
顶的人这么多,怎么还没开讲

使用特权

评论回复
28
pzhzwz| | 2010-8-29 19:28 | 只看该作者
再不讲,灌水了……

使用特权

评论回复
29
雪山飞狐D| | 2010-8-29 19:42 | 只看该作者
楼主快讲吧,不然21IC 显得很低档
我项目正需要,可以再讲讲真有效值怎么弄嘛:lol

使用特权

评论回复
30
laden| | 2010-8-29 20:15 | 只看该作者
灌水

使用特权

评论回复
31
itelectron| | 2010-8-29 20:52 | 只看该作者
讲这个 需要 功力的   呵呵 !  就怕是  哪个 皇帝旁边的。。。。。:lol

使用特权

评论回复
32
最爱01间| | 2010-8-29 21:20 | 只看该作者
听大师讲课!

使用特权

评论回复
33
zuoxuqi| | 2010-8-29 21:26 | 只看该作者
要讲赶紧,这个一定要听,先谢谢了!

使用特权

评论回复
34
望断云山| | 2010-8-29 21:54 | 只看该作者
再次路过,还没开讲

使用特权

评论回复
35
acute1110| | 2010-8-29 22:04 | 只看该作者
都用过好久了,用FFT可以精确的求得基波的各种参数,即使有谐波也能判断清楚,支持楼主普及该方法

使用特权

评论回复
36
超级马夹| | 2010-8-29 22:10 | 只看该作者
垃圾堆里走出来的高手。-----还是垃圾。

使用特权

评论回复
37
highgear|  楼主 | 2010-8-29 22:47 | 只看该作者
本帖最后由 highgear 于 2010-8-30 08:33 编辑

(1) 复数的基础知识
在讲解 fourier transform 前, 大家必须知道一点基本的复数知识。

在复平面上的一个点 P (x, y) 用复数表示为:  
      P = x + i y
用极坐标表示为:
       P = r * e^(i a)
这里,  r = sqrt(x*x + y*) 是点 (x, y) 到原点的距离, a = arctan2(x, y) 是角度, e 是自然常数。这里引出了一个非常重要的表达式:
      
                                            e^(i a) = cos(a) + i sin(a)

这个表达式,是利用复数完成角度变换和三角函数变换的利器。例如,把点 P 旋转 b 角度,那么新点(x1, y1) 的角度为 a+b, 距离仍为 r.
      P1 = x1 + i y1
         = r * e^(i (a+b))
         = r*e^(i a) * e^(i b)
         = (x + i y) * (cos(b)  +  i sin(b))
         = (x * cos(b) - y * sin(b)) + i ( y * cos(b) + x * sin(b))


        
(2)  傅里叶变换的基础知识
傅里叶变换是一个积分变换, 公式就不提供了, 有兴趣的同学可以直接访问下面的连接, 以获得更详尽的解释:
http://zh.wikipedia.org/zh-cn/%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2

(3) 离散傅里叶变换(DFT)
http://zh.wikipedia.org/zh-cn/%E7%A6%BB%E6%95%A3%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2

离散傅里叶变换的公式:
       X(k)  = ∑ x(n) * e^(i -2*PI* n/N * k) / N
这里 X(k) 是第 k 次谐波的复数;N 为周期采样点数;x(n)为输入,n从0 到N-1;     

用伪代码更直观地说明:
   void CalculateHarmonic(Complex* X, int harmonic)
   {
          for (int i=0; i<N; i++) {
                X->Real  = x(i) * cos( 2*PI* i/N * harmonic) / N;
                X->Image = x(i) * sin(-2*PI* i/N * harmonic) / N;
         }
    }

可以看到,离散傅里叶变换基本运算其实很简单, 没有那么复杂。只要有了 N 个输入,比如说通过AD 采样了 N 个数据后,可以轻易的计算出各个谐波,虽然计算量大了些。下面要做的就是减少计算量,这可以用两种方法, 一种当然就是熟知的 FFT, 还有一种就是递推。

(3)  递推离散傅里叶 (Recursive DFT)
傅里叶变换是一个积分变换,积分当然可以使用迭代递推来减少运算,尤其是周期性的函数。只要把最后一个数据仍出去,保持其他 N-1 个数据不变,加入一个新的数据就可以了。为了理解这一点,先考虑一下移动平均滤波算法:
        Y(k-1) = (x(k-1) + x(k-2) + … + x(k-N)) /N
上面的这个公式可以写成迭代也就是递推的形式:
        Y(k) = Y(k-1) + (x(k) – x(k-N)) /N
同理,由于sin, cosin函数的周期性,dft 可以由多项式乘法和的形式变换成迭代递推的形式:

        Y(k) = Y(k-1) + x(k) * e^(i -2*PI* k /N * harmonic) / N   
                     - x(k - N) * e^(i -2*PI* (k–N) /N * harmonic) / N
            = Y(k-1) + (x(k) - x(k- N)) * e^(i -2*PI* k /N * harmonic) / N

C 代码:
        x(i) = GetFromADC();
       X->Real  +=  (x(i) – x(i-N)) * cos( 2*PI* i/N * harmonic) /N;
       X->Image +=  (x(i) – x(i-N)) * sin(-2*PI* i/N * harmonic) /N;


由于 cos, sin 是周期函数,所以 cos(2*PI* (i * harmonic) / N) 与cos(2*PI* (i * harmonic % N) / N) 是一样的,(i * harmonic % N) 的取值范围:0 to N-1.

使用特权

评论回复
38
yuyi21ic| | 2010-8-29 23:08 | 只看该作者
当时故意留下这个Bug,看看能有几人能发现???? 24# 123jj

使用特权

评论回复
39
highgear|  楼主 | 2010-8-29 23:15 | 只看该作者
总结一下:
傅里叶变换可以很深奥, 也可以很浅显。对于离散的傅里叶变换的公式, 只要认真的看看很容易看明白, 更何况还有代码说明。通过理解 dft 如何计算出某一个谐波, 就可以进一步计算出所有谐波, 再想象一下, 某一个算法, 可以快速的计算出所有的谐波, 这样, 就可以很容易的理解 fft.

使用特权

评论回复
40
linjing| | 2010-8-29 23:21 | 只看该作者
加油!继续!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则