打印

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

[复制链接]
楼主: highgear
手机看帖
扫描二维码
随时随地手机跟帖
41
xuyiyi| | 2010-8-30 07:49 | 只看该作者 回帖奖励 |倒序浏览
请继续! 顶!

使用特权

评论回复
42
highgear|  楼主 | 2010-8-30 08:06 | 只看该作者

*

本帖最后由 highgear 于 2010-8-30 08:28 编辑

(5) 问题 A 的解答
在上面的代码 CalculateHarmonic(Complex* X, int harmonic) 中可以看出dft 的各次谐波计算是独立的, 不依赖其它次谐波。而且,问题 A 不需要计算2次(100hz),3次(150hz)等等谐波,这是 dft 的优点之一。首先,定义两个复数的结构:
 

typedef short int16;
typedef int int32;
typedef struct SComplex
{
int16 R;
int16 I;
} Complex;
typedef struct SComplex32
{
int32 R;
int32 I;
} Complex32;


接着, 定义两个常数以及电压电流的结构:
 

#define N 16       //每周期采样点数
#define LOG2_N 4   // log2(N)

struct UI {
Complex  U;         //电压的结果
Complex  I;   //电流的结果
  int16  Voltage[N]; //先前的 N 个电压
int16  Current[N];   //先前的 N 个电流
Complex32 UAcc;  //电压的累加器
Complex32 IAcc;   //电流的累加器
int   Index;  //迭代索引计数器, 8-BIT MCU 可以为 char, 如果 N < 256.
Complex  W[N];  //N 点的 cos, sin 系数
} ui;

初始化,cos, sin 系数数组应该事先计算好:


void UI_Init()
{
for (int i=0; i<N; i++) {
  ui.W[i].R = (int16) (::cos( 2*3.1415927*i/N) * (1<<14) + 0.5); //应离线计算!!!
  ui.W[i].I = (int16) (::sin(-2*3.1415927*i/N) * (1<<14) + 0.5);
  ui.Voltage[i] = 0;
  ui.Current[i] = 0;
}
ui.UAcc.R = 0; ui.UAcc.I = 0;
ui.IAcc.R = 0; ui.IAcc.I = 0;
ui.Index = 0;
}

下面的代码不断递推, 可以求出电压和电流的复数:
 

void UI_Calculate(int16 voltage, int16 current)
{
int16 d;
d = voltage - ui.Voltage[ui.Index];
ui.Voltage[ui.Index] = voltage;
ui.UAcc.R += (d * ui.W[ui.Index].R) >> (13 + LOG2_N - 16);
ui.UAcc.I += (d * ui.W[ui.Index].I) >> (13 + LOG2_N - 16);
ui.U.R = (int16) (ui.UAcc.R >> 16);
ui.U.I = (int16) (ui.UAcc.I >> 16);
d = current - ui.Current[ui.Index];
ui.Current[ui.Index] = current;
ui.IAcc.R += (d * ui.W[ui.Index].R) >> (13 + LOG2_N - 16);
ui.IAcc.I += (d * ui.W[ui.Index].I) >> (13 + LOG2_N - 16);
ui.I.R = (int16) (ui.IAcc.R >> 16);
ui.I.I = (int16) (ui.IAcc.I >> 16);

ui.Index = (ui.Index + 1) & (N-1);
}

  

上面的计算dft计算使用的是 16-bit, 32-bit 的定点运算,这里需要把电压和电流单位化。比如系统最大电压幅值为 Vmax = 400V,最大电流幅值 Imax = 20A, 在数字系统中统一归一化:  Q15 = 2^15 = 32768. 即 Vmax,Imax在数字系统对应Q15 = 32768. 因此,演示主程序中的:
     8000 ---〉8000/Q15 * Vmax  =  97.66V
     4000 ---〉4000/Q15 * Imax  =   2.441A

至于功率,很简单, 用电压乘以电流的轭(用 j 来代替复数i, 以免混淆):
     P + jQ = U*I’ = (ui.U.R + j ui.U.I) * (ui.I.R – j ui.I.I)
P是有功功率, Q是无功功率;
功率因数为:cos(theta) = P / sqrt(P*P +Q*Q)     

 

visual c++下的演示主程序 :
#include "stdafx.h"
#include "Math.h"
#include "stdio.h"
#include "UI.h"
#define Magnitude(c) ((int) sqrtf(c.R*c.R + c.I*c.I))
#define PI 3.14159265f
int _tmain(int argc, _TCHAR* argv[])
{
int16 voltage, current;
Complex PQ;
UI_Init();
for (int i=0; i<1000; i++) {
  voltage = (int16) (::sin(2*PI*i/N)*8000);    //模拟采样电压
  current = (int16) (::sin(2*PI*i/N + PI/3)* 4000);  //模拟采样电流
  UI_Calculate(voltage, current);
}
PQ.R = (ui.U.R * ui.I.R + ui.U.I * ui.I.I) >> 15;
PQ.I = (ui.U.I * ui.I.R - ui.U.R * ui.I.I) >> 15;
printf("Voltage: %d\n",  Magnitude(ui.U));
printf("Cuurent: %d\n",  Magnitude(ui.I));
printf("Power Factor: %d\n", PQ.R * 1000 / Magnitude(PQ));
::getchar();
return 0;
}

结果
Voltage: 8000
Cuurent: 3999
Power Factor: 500


使用特权

评论回复
43
machunshui| | 2010-8-30 08:26 | 只看该作者
顶一下。
要搞清楚,还是要先静下心来看书。

使用特权

评论回复
44
itelectron| | 2010-8-30 08:39 | 只看该作者

使用特权

评论回复
45
望断云山| | 2010-8-30 10:47 | 只看该作者
专程前来学习,并非偶然路过。

使用特权

评论回复
46
123jj| | 2010-8-30 10:55 | 只看该作者
学习,学习,继续跟highgear老师学习。

使用特权

评论回复
47
宇宙飞船| | 2010-8-30 12:15 | 只看该作者
对于没有数字信号处理基础的电工,既使放出应用代码,变换数学公式,也没有能力去弄懂博立叶变换的原理。
除非楼主有能力用初等数学夹杂在一起讲解。但是这需要楼主确彻地精通博立叶变换。

使用特权

评论回复
48
雪山飞狐D| | 2010-8-30 12:21 | 只看该作者
要想正真理解,关键是对系统响应的物理过程的理解

使用特权

评论回复
49
btiger2000| | 2010-8-30 12:29 | 只看该作者
路过,学习!

使用特权

评论回复
50
望断云山| | 2010-8-30 13:12 | 只看该作者
飞船何不一句话点爆傅里叶变换?:lol

使用特权

评论回复
51
宇宙飞船| | 2010-8-30 14:35 | 只看该作者
要具备一些数学基础知识。好比如连欧姆定律,方程组还不会解的情况下,谈何学习模拟基础电路。
本飞船一句话点破是对于已有基础的电工,并非针对任何没有基础的电子菜鸟。
但是21IC这里已经有一些基础的电工,给飞船的感觉是很“串”----广东话。
做任何事都要负出代价的,“串”过之后所负出的代价,那就是在今后自学过程中负出的痛苦时间。

使用特权

评论回复
52
xuyiyi| | 2010-8-30 14:41 | 只看该作者
这么漂亮的楼,怎么看见一只苍蝇在飞?

谁放进来的?拖出去砍了~~~ :@

使用特权

评论回复
53
超级马夹| | 2010-8-30 14:56 | 只看该作者
垃圾堆中当然有苍蝇了,在“我们的--AVR”上好象没有发现苍蝇。
因为那里很干净纯正。

使用特权

评论回复
54
yewuyi| | 2010-8-30 15:36 | 只看该作者
呵呵,还有人开课啊。。。


BBS有希望了。。。

使用特权

评论回复
55
TCL| | 2010-8-30 18:23 | 只看该作者
使用FFT的话,不仅是考考知识,主要是在考耐心.
搞好了,不仅能区分50和55HZ的信号.能从1万个人的声音中找到一个人的声音.简单的就是现在的电话和电视的声音比以前的声音清楚,就是用了FFT技术

使用特权

评论回复
56
TCL| | 2010-8-30 18:26 | 只看该作者
我到现在还是用汇编语言,搞懂FFT就简单了许多!

使用特权

评论回复
57
xuyiyi| | 2010-8-30 18:37 | 只看该作者
LS又是神仙,能从1万个人的声音中找到一个人的声音.  ;P

使用特权

评论回复
58
yuyi21ic| | 2010-8-30 18:59 | 只看该作者
哈哈,正好我这学期选修课选了一门数字信号处理,看来用的上喽!!!得好好看看!

使用特权

评论回复
59
lymum| | 2010-8-30 19:28 | 只看该作者
我是来听课的

使用特权

评论回复
60
odqqdo| | 2010-8-30 19:48 | 只看该作者
楼主有没有C代码

使用特权

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

本版积分规则