论坛风格切换切换到宽版
  • 18210阅读
  • 212回复

方波的采样定理和DDS的问题 [复制链接]

上一主题 下一主题
离线bd1es
发帖
2096
只看该作者 100楼 发表于: 2008-08-05
[quote=一异]在我印象中,fft实际上从理论上讲就是有误差的,原因就在于fft处理的数据量是有限的。[/quote]

不要忘了加窗哦,这样可以减小误差的。但目前没有比fft更好更简单的分析工具了, :d 。
离线一异
发帖
868
只看该作者 101楼 发表于: 2008-08-05
'
唉,真是太不相信fft了。没关系,明天我按您的要求做16位的,环境在单位,现在做不了。
还有十进制dds,想法不错,不管有没有用也是挺创意的。不过这可能在硬件上付出代价的,搞不好会影响工作速度,:)。
'

在商品dds出来之前,我曾经用ttl加法器搭过28bit dds,dac用的是ns的8bitdac,用作0~1mhz的低频信号发生器。为了能够得到0.02hz的步进,我还专门去订做了5.368,709,12mhz的温度补偿晶体振荡器,受条件限制,做出来效果并不理想。其中,让我最不爽的就是那个晶振。
后来我还设计过10bit,1000进制的累加器,打算用fpga实现,用来做十进制dds。在这里面我用流水线方式处理二-十进制的进位问题,并不影响速度。
由于种种原因,这东西我没有做下去……
离线一异
发帖
868
只看该作者 102楼 发表于: 2008-08-05
'
不要忘了加窗哦,这样可以减小误差的。但目前没有比fft更好更简单的分析工具了, :d 。
'

这个问题你说起来我知道,但你不说我却想不起来了,感觉当初自己编fft程序已经是很久远的过去了。
离线bd1es
发帖
2096
只看该作者 103楼 发表于: 2008-08-05
是的,我也是搞软件的,对信号处理也是一知半解,我是搞oltp/olap应用类。所以才要仿真了,要不真是想不清楚,:)。

还好信号处理并不难学,比那些模拟电路容易,我是一见模拟电路就晕菜的人, :d 。
离线一异
发帖
868
只看该作者 104楼 发表于: 2008-08-05
'
是的,我也是搞软件的,对信号处理也是一知半解,我是搞oltp/olap应用类。所以才要仿真了,要不真是想不清楚,:)。
还好信号处理并不难学,比那些模拟电路容易,我是一见模拟电路就晕菜的人, :d 。
'

学起来容易,精通就不一样了,而且平时用的也不多。
模拟电路我比你强一些,做过不少
离线一异
发帖
868
只看该作者 105楼 发表于: 2008-08-06
我又想了一下,认为我昨天的看法应当没有错。
我们首先考虑纯数学的富利叶变换,也就是用解析方法来处理频谱问题。这种方法有一个基本要素:严格按照信号本身的周期来处理。当然,我们可以很容易的知道按照信号周期的若干整数倍来处理,可以得到完全性同的结果。
而fft这类算法,是以数值方法处理富利叶变换的问题,如果我们不考虑处理器的实际精度有限的问题,那么如果处理的数据正好是信号的整数周期,那么除了采样定理的限制之外,可以认为这种方法也能得到精确的答案。
由于通常的数字系统采样频率是固定的,加上这类算法通常处理的数据量是2的n次幂,所以很难在保证处理的数据周期和信号周期之间的整倍数关系。
为了减小由此产生的误差,所以引进了窗口函数。窗口函数的用途是减少时间轴上两端的数据的重要性,通过这种方法可以将由于周期不匹配导致的阶段误差减小到可以接受的程度。但不管什么样的窗口函数,都无法将误差减小到零。

我们再看看84楼的16bit dds的数据:这里相位步长是8321,从相位零开始,经过65536步之后,相位为8321*65536。实际上这里65536对应的相位2π,所以在这里fft的输入数据正好是8321个周期。
如果我前面的结论没有错,那么对这组数据进行fft的时候,即使不用窗口函数,我们也应当能得到同样好的频谱输出

而对于32bit dds,我们可以计算出fft输入数据为:8321.0017个周期,不满足整数周期的条件,所以fft的结果会有误差。

希望我没错
离线mainstreet
发帖
44
只看该作者 106楼 发表于: 2008-08-06
'
是的。说实话起初我玩dds的时候以为这东西挺简单的,不就是个加法器嘛。可是后来做了avr的dds后大失所望,不知道信号为什么那么乱。后来搂主提问方波dds,我也简单阐述了dds的原理,但还是说不清方波dds与正弦波dds过零比较再形成方波,这之间到底差别多少,于是就想起了仿真。一仿不得了,发现所谓方波dds根本不能用,现在更严格说应该是1bit dds [表情] 。
但我还是没搞清avr dds为什么信号质量不佳。直到这两天进一步仿真才知道是波表质量太差造成的,那个波表是256字节乘8位的,连40db的信噪比都没有,自然觉得乱了。这个avr dds的案例应该还能在网上查到,是一个叫j什么什么的老外做的。程序是汇编的,dds累加器字长24比特,波表深度256字节。他写了正弦、斜波、三角波和方波的波表。那个方波的波表是我们批判最严重的一个。有兴趣的上网找找。
现在觉得dds仍然是简单的,它只有3个参量:累加器字长、波表寻址字长和波表输出字长,3个整数而已!可是把这3个整数组合起来,结果可是太出乎意料了。竟然有那么多的不知道,很有意思。大概这就是仿真的魅力吧, [表情] [表情] 。特别是大家一起的时候更好玩,颇有点儿指点江山的意思。(这话是盗版的 :d )
--------------------------------------------------------------------------
继续仿真昨天一异说的问题。又出乎意料:
1、16位dds,不管相位增量取什么值,输出都是一样的纯净;
2、32位dds,只有相位增量与16位dds等效时,输出才与16位一样纯,否则噪声增加。
说明什么问题?mainstreet的观点正确,波表越完整dds输出质量越高!
因为32位dds的相位增量与16位等效时,32位dds等效于16位的,于是他拥有完整的波表。而稍微把预制数拉偏后,这个“完整波表就不存在了”,于是出现截断问题,噪声增加。参见第3图,是不是有加矩形窗的嫌疑? [表情]
图1:16位dds,预制数8321
图2:32位dds,预制数8321*65536
图3:32位dds,预制数8321*65536+111
'
我对这几个图的解释。

16位波表有64k个数,它的输出的最多64k重复一次,实际的周期可能更短。64k的fft,频率轴有32k个离散的频率。波表的输出很有可能正好落在某个离散的频率上,这样没有频谱的泄露。这是图1。

图2和图1一样,32位的波表当作为16位波表来用。

图3的波表输出,周期可能更长,并不落在个离散的频率之一,有频谱的泄露。我觉得这个频铺更有代表性。

图2和图3的区别就象0.1和0.1*exp(1)/2.7的区别。
离线bd1es
发帖
2096
只看该作者 107楼 发表于: 2008-08-06
谱泄漏有两个典型特征:
1、是一种sinc(x)调制,使信号出现旁瓣,但与信号的频率(位置)无关。不管频率如何变,她都原样依附在他的两旁;
2、随着序列的长度而变,序列越长,旁瓣的幅度和宽度都同时变小。

可是上面的图已经很清楚了。那旁瓣不随fft的长度变化,那是信号自身的边带。况且,这个边带会随预置数的不同而变化,岂不也说明这个问题。

中午再转一次程序,进一步说明这个问题, :d 。
离线alchemier
发帖
69
只看该作者 108楼 发表于: 2008-08-06
还是用波形图看比较直观些吧,反正越接近正弦波的波形频谱越纯。这里是用24位和30位累加器的结果比较,可以看出波形质量与累加器的位数无关,用16位的结果也一样,可以说累加器的位数只和频率精度有关,和频谱关系不大。
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线alchemier
发帖
69
只看该作者 109楼 发表于: 2008-08-06
如果把时钟频率提高,达到输出波形的256倍(与波表样点相适应),则输出波形又接近完美了(见下图),可见要充分利用波表的数据,达到纯净完美的输出,主要的手段是提高时钟频率。
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线mainstreet
发帖
44
只看该作者 110楼 发表于: 2008-08-06
请看这两张图,64点的dft。

图1对应cos(2*pi*n/14)+0.75*cos(4*pi*n/15),d和f是接近的。

图2对应cos(2*pi*n/16)+0.75*cos(4*pi*n/16),b和c差很远。

我猜想你的情况和这个类似。应该更多点的dft才是,增加频率的分辨率。从64k变到1k,我觉得不说明问题。
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线bd1es
发帖
2096
只看该作者 111楼 发表于: 2008-08-06
您的观点我支持,一异也说过,累加器决定频率的分辨度,这些都没问题。

问题是累加器的长度与波表长度的关系,以及波表宽度(输出位宽)与波表长度的关系。可以说累加器越精密,它所需的波表就要越长,为了进一步提高输出质量,还应该增加波表的位宽。这些需要在可能实现的基础上寻找折中,而寻找折中则优选仿真。

只有累加器很短时才有可能实现全波表,而拥有全波表时决定输出质量的是波表的宽度,这时也不必需在意dds是否有相位抖动了。

以上就是我的结论。另有一项我不大同意。通过波形分析信号虽然很有效,但有时也会给人误解。

比如上图,我们很容易理解为相同时钟下,dds输出频率越低则波形越精密,因而输出质量越好。而实际上是虽然输出高频率时波形很粗糙,但它在奈奎斯特频带内的输出质量与低频是一样的,那些粗糙所造成的杂散(几个伴随频率)都在奈奎斯特带宽之外。

由此我们就非常强调dds的输出滤波器质量,那有关键作用。甚至因为我们难以把握低通滤波器的过渡带,所以人们建议dds的工作范围是0到1/3时钟,也就是0.66奈奎斯特带宽,目的是为滤波器的制造留出一些余量。还有人建议到0.5奈奎斯特带宽,也是同样道理。但这绝不代表dds波形粗糙时信号质量不好,而是出于工程实践的考虑。

以上分析通过fft是很容易理解的,而波形分析往往不占主要地位,这也是我在本贴很少贴波形的原因。

至于fft的谱泄漏,大家再仔细想想。我再次强调,上面那些图片已经说明问题了。
离线bd1es
发帖
2096
只看该作者 112楼 发表于: 2008-08-06
'
请看这两张图,64点的dft。
图1对应cos(2*pi*n/14)+0.75*cos(4*pi*n/15),d和f是接近的。
图2对应cos(2*pi*n/16)+0.75*cos(4*pi*n/16),b和c差很远。
我猜想你的情况和这个类似。应该更多点的dft才是,增加频率的分辨率。从64k变到1k,我觉得不说明问题
'

我还是坚持认为已经说明问题了。fft长度从1k增加到256k,变了256倍,而那边带的宽度和高度都没有变化,难道这会是谱泄漏吗?这泄漏也太顽固了,不可能的,
离线alchemier
发帖
69
只看该作者 113楼 发表于: 2008-08-06
'
您的观点我支持,一异也说过,累加器决定频率的分辨度,这些都没问题。
问题是累加器的长度与波表长度的关系,以及波表宽度(输出位宽)与波表长度的关系。可以说累加器越精密,它所需的波表就要越长,为了进一步提高输出质量,还应该增加波表的位宽。这些需要在可能实现的基础上寻找折中,而寻找折中则优选仿真。
这也是我先前在小比尔/5帖子里的观点,但是现在我认为累加器和波表关系不大,倒是波表的长度和位宽应该相近。
只有累加器很短时才有可能实现全波表,而拥有全波表时决定输出质量的是波表的宽度,这时也不必需在意dds是否有相位抖动了。
这点不同意,理由如上。
以上就是我的结论。另有一项我不大同意。通过波形分析信号虽然很有效,但有时也会给人误解。
比如上图,我们很容易理解为相同时钟下,dds输出频率越低则波形越精密,因而输出质量越好。而实际上是虽然输出高频率时波形很粗糙,但它在奈奎斯特频带内的输出质量与低频是一样的,那些粗糙所造成的杂散(几个伴随频率)都在奈奎斯特带宽之外。
由此我们就非常强调dds的输出滤波器质量,那有关键作用。甚至因为我们难以把握低通滤波器的过渡带,所以人们建议dds的工作范围是0到1/3时钟,也就是0.3奈奎斯特带宽,目的是为滤波器的制造留出一些余量。还有人建议到0.25奈奎斯特带宽,也是同样道理。但这绝不代表dds波形粗糙时信号质量不好,而是出于工程实践的考虑。
以上分析通过fft是很容易理解的,而波形分析往往不占主要地位,这也是我在本贴很少贴波形的原因。

这段是否可理解为波形每周期中有16个点和256个点其fft频谱是差不多的?这个不太理解。
至于fft的谱泄漏,大家再仔细想想。我再次强调,上面那些图片已经说明问题了。
'

也许在高频的情况下对输出波形要求不高?这个我要再看一下。但是我觉得前面的fft频谱信噪比那么高(>100db)可能有点问题。那段matlab程序中输出0.1,也就是每周期只有10个点,且不加滤波器的情况下,还有那么高的信噪比,有点想不通。
离线bd1es
发帖
2096
只看该作者 114楼 发表于: 2008-08-06
不同意没关系,大家一起仿真呗,反正图贴在这里了。:)

关于第二点,大多数人都是觉得点数多代表质量高。然而真的恕我直言,这观点不对。暂时忘掉dds,说说录音机。同样是44.1khz的采样频率,难道我们录得150 hz和15 khz在质量上有什么差异吗?奈奎斯特早就说了,它们质量相同。

再强调,输出滤波器至关重要,那是数字世界通向模拟世界的一扇大门。以15 khz来说,在数字域里看到的波形都不成样子了,简直一塌糊涂,是严重经调制的波形。而经正规手段还原后却与原来一模一样。因为经滤波后那些“边带”被滤出了。

这是采样定理,跟dds无关的。
离线bd1es
发帖
2096
只看该作者 115楼 发表于: 2008-08-06
[quote=一异]在商品dds出来之前,我曾经用ttl加法器搭过28bit dds,dac用的是ns的8bitdac,用作0~1mhz的低频信号发生器。为了能够得到0.02hz的步进,我还专门去订做了5.368,709,12mhz的温度补偿晶体振荡器,受条件限制,做出来效果并不理想。其中,让我最不爽的就是那个晶振。
后来我还设计过10bit,1000进制的累加器,打算用fpga实现,用来做十进制dds。在这里面我用流水线方式处理二-十进制的进位问题,并不影响速度。
由于种种原因,这东西我没有做下去……[/quote]

明白了,应该鼓励,这确实是好创意!
离线bd1es
发帖
2096
只看该作者 116楼 发表于: 2008-08-06
继续解答大家对fft的疑虑。还以昨天的序列为例,16位使用8321,32位使用8321*65536+111

这是不加窗的图像,尽管图像不清晰,但还能看出16位的那个更纯净:
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线bd1es
发帖
2096
只看该作者 117楼 发表于: 2008-08-06
然后我们使用45678作为序列长度做“fft”,虽然此时实际做的是dft,但输出结果一样,唯计算时间比fft长一些。看上去一样了?实际上是频率分辨率下降的结果。

修正一句,也可能不是dft,而是在序列的后面补零,继续以fft计算。这是matlab的内部处理,不影响我们的结果。
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线bd1es
发帖
2096
只看该作者 118楼 发表于: 2008-08-06
然后保持dft长度不变,加上汉宁窗以增加频率分辨率,得到下图:
本主题包含附件,请 登录 后查看, 或者 注册 成为会员
离线bd1es
发帖
2096
只看该作者 119楼 发表于: 2008-08-06
下面3张图是32位dds的,为了得到完全无须担心的频率分辨率,我们把序列增加到456789,用dft去计算。

第一张:置数8321*65536+111
第二张:置数8321*65536+333
第三张:置数8321*65536+3333

请看边带扩展的情况:

顺便说一下,16位的暂不展示了,前面说过,无论置数如何,它的输出都是一根线。