Phil_D Posted April 5, 2019 Share Posted April 5, 2019 Does the Waveforms spectrum analyzer have options for zero padding? I've seen in other FFT applications that increased zero padding can improve the look of an FFT at low frequencies when monitoring over a wide frequency range, like 10kHz to 20MHz. Link to comment Share on other sites More sharing options...
attila Posted April 9, 2019 Share Posted April 9, 2019 Hi @Phil_D There is no zero padding option but it can be done with Script like this: var rg = Spectrum.Channel1.data // channel 1 time domain data var c = rg.length var t = rg[c-1] // last sample for(var i = 0; i < c; i++) rg.push(t) // 2x padding var rghz = Spectrum.Trace1.frequency var hz = 2.0*rghz[rghz.length-1] //var hz = 2.0*Spectrum.Frequency.Stop.value // scope sample rate Spectrum.Trace5.setSamples(rg, hz) Some other suggestions to improve the resolution: 1. For lower frequencies, with 1MHz sampling you can use the Scope to perform a longer recording. This will highly improve the resolution in the FFT view. 2. With AD you can select the second device configuration to have 16k Scope buffer. 3. You can select a higher bandwidth window, like rectangular or cosine. 4. In the latest beta version with CZT algorithm you can select higher number of bins, higher resolution.https://forum.digilentinc.com/topic/8908-waveforms-beta-download/ Here: - T1 is CZT BlackmanHarris 10x BINs, 244Hz resolution - T2 is FFT BlackmanHarris 4k BINs 2.4kHz resolution - T3 is FFT Cosine 4k BINs 2.4kHz resolution Link to comment Share on other sites More sharing options...
Phil_D Posted April 11, 2019 Author Share Posted April 11, 2019 Thanks @attila! Is there a way to have the zero padded trace continue to run and be averaged? Link to comment Share on other sites More sharing options...
attila Posted April 11, 2019 Share Posted April 11, 2019 Hi @Phil_D It can be done like this: const NAVG = 10 Spectrum.run() var sum = [] for(var acq = 1; acq <= NAVG && Spectrum.wait(); acq++){ var hz = Spectrum.Channel1.dataRate // WF v3.11.2 { // padding in Trace 5 var rg = Spectrum.Channel1.data // channel 1 time domain data var c = rg.length var t = rg[c-1] // last sample for(var i = 0; i < c; i++) rg.push(t) // 2x padding Spectrum.Trace5.setSamples(rg, hz) } { // averaging in Trace 6 var rg = Spectrum.Trace5.magnitude if(acq==1){ sum = rg; Spectrum.Trace6.Clone(Spectrum.Trace5) }else{ rg.forEach(function(v,i){ sum[i] += v;}) // sum sum.forEach(function(v,i){ rg[i] = v/acq;}) // average Spectrum.Trace6.setMagnitude(rg, 0, hz/2) } } } Spectrum.stop() Link to comment Share on other sites More sharing options...
Phil_D Posted April 12, 2019 Author Share Posted April 12, 2019 This is great! Thanks @attila! Does this script end up with a rectangular window? The padded, averaged result from the script looks very different from our previous unpadded result. Is there a way to set the type of windowing function that is used in your script? We'd like to use a Hann window. I tried to look through other objects/functions with cntrl+space, but didn't see any way to set the window type. Also, if I wanted more than 2x padding, would I do something like for(var i = 0; i < 2*c; i++) rg.push(t) //4x padding??? Thanks! Link to comment Share on other sites More sharing options...
attila Posted April 12, 2019 Share Posted April 12, 2019 Hi @Phil_D You can configure the window for Trance 5 in the Spectrum interface. The script feeds the time domain data to T5 and this performs the FFT. The script takes magnitude array from T5, performs averaging and sets this to T6. I'm not sure if the padding is useful. To improve or artificially increase the resolution you should use the other options I pointer out in the first reply. For 4x padding you should append 3x more samples to the end of the buffer: for(var i = 0; i < 3*c; i++) rg.push(t) Adding much padding will push the effective signal to the edge of the window, damping and attenuating it further. Here to demonstrate the effect: M1 generates a Hann window, M2 applies it on the data. The originally +5.3dBV signal is seen as -11dBV. Link to comment Share on other sites More sharing options...
Phil_D Posted April 13, 2019 Author Share Posted April 13, 2019 Thank you for the continued support on this, @attila! However, I think that the FFT window function is not working right when we pad before doing the windowing function. I'll explain: I'm using another signal processing program called Sigview, and I can add zero padding there as well. I did a bunch of exporting and graphing in Excel to compare padding between Sigview and Waveforms: These are the two FFTs I'm getting in Waveforms, no padding in red and 2x padding in green. You can see that the 2x padding trace in green does not look at all like the red trace without padding. This graph below is comparing Waveforms and Sigview, both Hann windows, both using no padding. They are basically identical, except for a 3dB offset. I used magnitude in Sigview and RMS (dB) in Waveforms, which I think accounts for that 3dB. But the important thing is that the shape of the FFTs is identical. Same data in both cases, same window (Hann), both programs produce the same FFT. Now, I add padding in Sigview. Blue is 2x padding, magenta is no padding. The traces are nearly identical, except the padding in the blue trace helps smooth out the peaks. I think this is how the padding should work. We were wondering if it would be possible to do the math to apply the Hann window on the data array in the script *before* adding the padding? So the order of operations would be: 1. Apply the Hann window to the data 2. Add zero padding 3. Take the FFT It looks like you added the padding, then did the window, then did the FFT. As you mentioned, applying the window after the padding really attenuates the actual data and adds more emphasis to the 0's. I would like to add the padding in Waveforms so we can take advantage of the averaging. With Sigview, I'd have to import many static datasets, process each one separately, and then average in C++, which would be much more laborious and time consuming. We found a couple of links that talk about this padding and windowing:https://dsp.stackexchange.com/questions/13736/zero-pad-before-or-after-windowing-for-fft/13740 http://www.mechanicalvibration.com/Zero_Padding_FFTs.html Thanks! Link to comment Share on other sites More sharing options...
attila Posted April 15, 2019 Share Posted April 15, 2019 Hi @Phil_D Sure, it makes more sense to apply the window only on the real data section. const NAVG = 10 const NPAD = 2 Spectrum.Trace5.Window.text = "Rectangular" // disable windowing Spectrum.run() var win = [] var sum = [] for(var acq = 1; acq <= NAVG && Spectrum.wait(); acq++){ var hz = Spectrum.Channel1.dataRate // WF v3.11.2 { // padding in Trace 5 var rg = Spectrum.Channel1.data // channel 1 time domain data var c = rg.length if(acq==1){ // create window var w = 0 for(var i = 0; i < c; i++) { var v = pow(sin(PI*i/(c-1)), 2.0) // Hann w += v win.push(v) } w /= c*NPAD for(var i = 0; i < c; i++) { // normalize win[i] /= w } } for(var i = 0; i < c; i++) rg[i] = win[i]*rg[i] // apply window for(var i = 0; i < c*(NPAD-1); i++) rg.push(0) // padding Spectrum.Trace5.setSamples(rg, hz) } { // averaging in Trace 6 var rg = Spectrum.Trace5.magnitude if(acq==1){ sum = rg; Spectrum.Trace6.Clone(Spectrum.Trace5) }else{ rg.forEach(function(v,i){ sum[i] += v;}) // sum sum.forEach(function(v,i){ rg[i] = v/acq;}) // average Spectrum.Trace6.setMagnitude(rg, 0, hz/2) } } } Spectrum.stop() Here you can see that CZT produces the same result as the padding: The noise floor difference is due to different captures. The FFT works on power of two + 1 BINs, with CZT you can specify arbitrary number of BINs, setting fine resolution: Link to comment Share on other sites More sharing options...
Phil_D Posted April 16, 2019 Author Share Posted April 16, 2019 Thank you @attila! The windowing before the padding seems to have worked. We'll have to experiment with the CZT to see if it will meet our needs and perhaps be easier than an FFT with the padding script. Link to comment Share on other sites More sharing options...
Phil_D Posted April 16, 2019 Author Share Posted April 16, 2019 One more hopefully quick question here: I would like to export the data after all of the windowing/padding/averaging is complete. I'm using: Spectrum1.Export("C:/Users/User/pjm_2019/data.txt") ...but this gives me the results for Trace1, Trace5, and Trace 6. Is there a way to export only Trace 6? I tried: Spectrum1.Trace6.Export("C:/Users/User/pjm_2019/data.txt") but that gave me an error. Thanks! Link to comment Share on other sites More sharing options...
attila Posted April 17, 2019 Share Posted April 17, 2019 Hi @Phil_D You can export the BINs under Trace options or by script with: FileWrite("~/Desktop/data.txt", Spectrum.Trace6.magnitude) Link to comment Share on other sites More sharing options...
attila Posted April 17, 2019 Share Posted April 17, 2019 Hi @Phil_D In WF v3.11.4 you can also call: Spectrum.Export("~/Desktop/data.csv", "Trace 6") https://forum.digilentinc.com/topic/8908-waveforms-beta-download/ Link to comment Share on other sites More sharing options...
Question
Phil_D
Does the Waveforms spectrum analyzer have options for zero padding?
I've seen in other FFT applications that increased zero padding can improve the look of an FFT at low frequencies when monitoring over a wide frequency range, like 10kHz to 20MHz.
Link to comment
Share on other sites
11 answers to this question
Recommended Posts
Archived
This topic is now archived and is closed to further replies.