Go Down

### Topic: Question about magnitude (Read 6605 times)previous topic - next topic

#### Noisecontrol

#30
##### Jun 14, 2018, 03:06 pmLast Edit: Jun 14, 2018, 03:27 pm by Noisecontrol
Hello
Maximum adc is 1024 then why  when adc analized by fft ,magnitude value in per bin frequency could be greater than 1024 ?
If magnitude in per frequency should not
be less than 1024 ?

#31
Quote
No, 1023.

#### Noisecontrol

#32
##### Jun 14, 2018, 03:50 pm
How can i fft result ( magnitude)convert to voltage in per frequency bin?

#### vffgaston

#33
##### Jun 14, 2018, 03:54 pm
...fft result ...
¿Fast Fourier Transform?

#34

#### DVDdoug

#35
##### Jun 14, 2018, 04:41 pm
I don't know how it's scaled, but if you can't find it in the documentation you can calibrate it.

For example, feed-in a 1V, 1kHz, signal and see what you get.    Then, you can use the map() function to map the values to voltage.   If you feed-in a 1V, 100Hz, signal you should get (about) the same reading in the 100Hz bin.  And if you mix the two signals both bins should still read (about) the same as before.

Choose frequencies that are in the center of the bin frequencies.

...If you need a way to generate sine waves, Audacity can make a WAV file. that you can play on your soundcard.     You can also mix in Audacity so you can try with two (or more) known frequencies.   But since mixing is done by summation, you'll want to generate waves at -6dB (half of the maximum) or less.    And, you'll need a multimeter to measure the voltage.

#### Noisecontrol

#36
##### Jun 14, 2018, 05:01 pm

But when fft analized a signal , we have expected that get amplitud in per frequency base that factor analized. in other word if adc is amplitude of a signal in per time we have expected frequncies have same unit amplituid

#### jremington

#37
##### Jun 14, 2018, 05:38 pmLast Edit: Jun 14, 2018, 05:40 pm by jremington
Quote
Presumably you mean DAC, which standard Arduinos do not have, but why would anyone bother to document something so simple?

Code: [Select]
`    analogWrite(pin,bin_value);`

#### jremington

#38
##### Jun 14, 2018, 05:53 pmLast Edit: Jun 14, 2018, 06:27 pm by jremington
Quote
Maximum adc is 1024 then why  when adc analized by fft ,magnitude value in per bin frequency could be greater than 1024 ?
Possibly, depending on how the FFT results are scaled. Different FFT subroutine packages scale the output differently.

Here is an idea: write some simple programs and learn how the FFT works.

That way you can answer questions like this yourself, and learn something in the process.

Example using the OpenMusicLabs FFT library:
Code: [Select]
`/*  fft_test_constant  example sketch for testing the fft library.  This generates a constant data set demonstrating the DC  offset term. Enable the fft_window() line to see the effect of  windowing.*/// do #defines BEFORE #includes#define LIN_OUT 1 // use the lin output function#define FFT_N 32 // set to 32 point fft#include <FFT.h> // include the libraryvoid setup() {  int i, k;  Serial.begin(9600); // output on the serial port  for (i = 0 ; i < FFT_N ; i++) { // create data samples    fft_input[2 * i] = 1000; // put real data into even bins    fft_input[2 * i + 1] = 0; // set odd bins to 0  }  //  fft_window();  //Try with and without this line, it smears  fft_reorder(); // reorder the data before doing the fft  fft_run(); // process the data using the fft  fft_mag_lin(); // calculate the magnitude of the output  // print the frequency index and amplitudes  Serial.println("bin  amplitude");  for (i = 0; i < FFT_N / 2; i++) {    Serial.print(i);    Serial.print("       ");    Serial.println(fft_lin_out[i]);  }  Serial.println("Done");}void loop() {}`

Output:
Code: [Select]
`bin  amplitude0       10001       02       03       04       05       06       07       08       09       010       011       012       013       014       015       0Done`

#### Noisecontrol

#39
##### Jun 14, 2018, 06:21 pm
Presumably you mean DAC, which standard Arduinos do not have, but why would anyone bother to document something so simple?

Code: [Select]
`    analogWrite(pin,bin_value);`
No i want to convert fft results in per bin to voltage

#### jremington

#40
##### Jun 14, 2018, 06:31 pmLast Edit: Jun 14, 2018, 06:32 pm by jremington
Quote
No i want to convert fft results in per bin to voltage
Explain this comment, and explain why you think analogWrite() does not do what you want.

#### PieterP

#41
##### Jun 14, 2018, 06:34 pmLast Edit: Jun 14, 2018, 07:21 pm by PieterP

You even started a third thread on the topic.

You have to correct for a couple of things:
• Subtract the bias voltage (expressed in ADC units) from the sampled signal
• Use the complex modulus of the FFT result to get the magnitude
• Divide by the number of samples to correct for the FFT processing gain
• Multiply by 2 to account for magnitude "lost" in negative part of the spectrum
• Divide by the average amplitude of the windowing function
• Convert the magnitude in ADC units to a voltage (*5/1024)

Here's a MATLAB/Octave script that does exactly that, together with the result, to get an understanding of what's going on. See line 58 for the actual conversion.
Code: [Select]
`%% Setupclose all;N = 128;  % 128 samples → 128 frequency binssamples = (0:N-1)';f_s = 256;     % 256 Hz sample frequencyf   = 64;      % Sine wave with a frequency of 64 HzA   = 1.25;    % and amplitude of 1.25 V peakV_bias = 2.5;V_ref = 5;ADC_bits = 10;ADC_factor = 2^ADC_bits;t = samples / f_s;     % Generate a vector with timesine_V = A*sin(2*pi*f*t); % Sine wave in voltssine_V = sine_V + V_bias; % Bias sine = sine_V * ADC_factor / V_ref; % Sine wave as sampled by the Arduinosubplot(2,2,1);plot(samples, sine, '-o');axis([0 N 0 ADC_factor])title('Original 1.25 V peak, 64 Hz sine wave (ADC Units)');%% DC offset correctionsine = sine - V_bias * ADC_factor / V_ref; % Subtract bias again%% Windowingwindow = hamming(N);mean_window = mean(window);windowed_sine = window.*sine; % Apply window functionsubplot(2,2,3);hold on;plot(samples, windowed_sine, '-o');plot(samples, ADC_factor * window / 2, '-k');plot(samples, -ADC_factor * window / 2, '-k');title('Sine wave after applying window');axis([0 N -ADC_factor/2 ADC_factor/2])%% FFTfft_sine = fft(windowed_sine);freq = samples * f_s / N;subplot(2,2,2);stem(freq, abs(fft_sine));axis([0 f_s 0 inf]);title('Magnitude per frequency bin after FFT');corrected_fft = fft_sine / N * 2 / mean_window * V_ref / ADC_factor;subplot(2,2,4);half = length(freq) / 2;stem(freq(1:half), abs(corrected_fft(1:half)));axis([0 f_s / 2 0 inf]);title('Magnitude per frequency bin after FFT (corrected)');`

Here's the result:

If you're using a dB scale, express the divisions as a sum of constant logarithms, using the identities log(x*y) = log(x)+log(y) and log(x/y) = log(x) - log(y).

Pieter

#42

#### Noisecontrol

#43
##### Jun 14, 2018, 08:17 pmLast Edit: Jun 14, 2018, 08:23 pm by Noisecontrol
You have to correct for a couple of things:
• Subtract the bias voltage (expressed in ADC units) from the sampled signal
• Use the complex modulus of the FFT result to get the magnitude
• Divide by the number of samples to correct for the FFT processing gain
• Multiply by 2 to account for magnitude "lost" in negative part of the spectrum
• Divide by the average amplitude of the windowing function
• Convert the magnitude in ADC units to a voltage (*5/1024)

If you have source code of this process for arduino please share it.
I dont know MATLAB code

#### PieterP

#44
##### Jun 14, 2018, 08:38 pm
If you have source code of this process for arduino please share it.
I dont know MATLAB code
I don't have the Arduino code for this, and I can't test it.
The principle is explained in my post, you can look at the MATLAB implementation for inspiration.
You should be able to read it, even if you don't know the exact syntax. Line 58 is the most important line.
Can you explain what you don't understand?

Like I said before, using FFT doesn't seem to be the standard way to perform A-weighting, you should probably look into digital filters instead.

Go Up