Go Down

Topic: FFT with DUE and TFT (Read 3644 times) previous topic - next topic


Aug 07, 2014, 06:00 pm Last Edit: Aug 07, 2014, 09:14 pm by vile Reason: 1
Hello everyone,

after hours of searching, testing and frustrating I ask for your help.
I have a 7 inch TFT driven by an Arduino DUE using UTFT and I want to see a FFT diagramm. I have directly connected the audio signal (smartphone) to an analog in and ground of course.

I have tried the Radix4 library (http://coolarduino.wordpress.com/), the 8-bit one from here http://forum.arduino.cc/index.php/topic,38153.0.html and tried to do this tutorial http://www.instructables.com/id/LoL-Shield-Audio-Spectrum-VU-Meter/?ALLSTEPS.
The 8-bit library only shows noise, the Radix4 with FFT size 2048 (seems to work, but I don't need such a large FFT) is too slow and I can't get it working with 256.
At the moment I'm trying to get this one to work (same 8 bit lib) https://www.youtube.com/watch?v=jJ7lzkrQIFk, until now it shows also only noise using a signal generator.

I'm trying to get something like this https://www.youtube.com/watch?v=VENd0LmTK2c to my TFT.
As soon as I get an array with the correct values, visualisation is no problem.

Btw.: Do I have to use an OpAmp for the audio signal in order to get it from say -2.5...2.5V to 0..5V or does a simple diode do the job?

Is there anyone who has done this before? I need your help!

Edit: I can't get the 8 bit library work correctly. Here's my code if anyone wants to try
Code: [Select]
#include <fix_fft.h>

char im[128], data[128];
byte i;

#include <UTFT.h>
#include <UTouch.h>
extern uint8_t BigFont[];
extern uint8_t SmallFont[];
UTFT myGLCD(SSD1963_800ALT, 25, 26, 27, 28);
UTouch  myTouch( 6, 5, 4, 3, 2);

void setup()
 myGLCD.setBackColor(255, 255, 255);
 myGLCD.setColor(255, 255, 255);
 myGLCD.fillRect(1, 1, 800, 480);

void loop()
 for (i = 0; i < 128; i++) {
   data[i] = (analogRead(A0) / 4) - 128;
   im[i] = 0;
 fix_fft(data, im, 7, false);
 myGLCD.setColor(255, 255, 255);
 myGLCD.fillRect(0, 0, 800, 480);
 for (i = 1; i < 64; i++) {
   data[i] = sqrt(data[i] * data[i] + im[i] * im[i]);
   myGLCD.setColor(0, 0, 0);
   myGLCD.drawLine(i * 4, 0, i * 4, data[i]);

Even if the analog input is connected to ground I get such FFT diagram (still mirrored on x axis):

Edit 2: Also this code from here http://mcclanahoochie.com/blog/portfolio/music-visualization-with-an-arduino/, almost the same, won't work with the DUE. Does not seem to be the script but the DUE...


Were the FFT libraries you tried specifically written to run on the DUE? If not, there may be problems with the different size of 'int' on the DUE (32 bits) and on earlier Arduinos (16 bits). You could try changing all occurrences of 'int' in the library to 'int16_t' and any occurrence of 'unsigned int' to 'uint16_t'.

Don't send me technical questions via Private Message.


Aug 08, 2014, 05:00 am Last Edit: Aug 08, 2014, 07:40 am by tmd3 Reason: 1
How is the analog signal connected now?  Your question about an op amp or diode suggests that there may be a problem with that connection.  Please be specific.

The Due doesn't want a 5V input - it wants something between 0V and 3.3V.  See the warning on the product page, here:http://arduino.cc/en/Main/ArduinoBoardDue.

Running the FFT with calculated data will eliminate uncertainty about the analog input.  I'd suggest getting it working with known data before trying to integrate it with analog acquisition.  I'd also recommend acquiring and printing raw analog data, to make sure that you're getting the analog inputs you expect, and get that working before trying to integrate it with the FFT.

You can get by without an op amp, but, as far as I know, a diode won't help you.  The canonical method for connecting a bipolar analog signal to an analog input is to use a voltage divider connected between 3.3V and 0V, and capacitively couple the input signal to the midpoint of the divider, and take the analog input from that point.  That method provides no protection for the input, though - it'll be up to you to make sure that the input signal doesn't go out of range.  

You seem to have access to a signal generator.  Those usually have a DC offset that you can set to 1.65V, and it will still be up to you to set the amplitude to avoid a signal excursion outside the safe range.  

Finally, I don't see anything about the frequency of the input signal, and I don't see anything controlling the analogRead() frequency other than the time it takes to get a reading.  If your input frequency is low, and the analogRead() speed is fast, you might be seeing only part of the input cycle, with weird results.


Aug 08, 2014, 08:47 am Last Edit: Aug 08, 2014, 09:51 am by vile Reason: 1
Thank you for the replies.

@ pete: The library is not explicitly written for the DUE. I think I will try your recommended modification.

@ tmd3: I meant of course the range 0...3.3V.
At the moment, the signal is directly (one channel) connected to the analog pin 0 and signal ground to Arduino ground. At first I thought a diode would protect the analog in, since the negative halfwave is cut off, but then of course the FFT is wrong, so lets forget about this.
I am thinking about an input circuit after I found this: http://www.instructables.com/id/Arduino-Audio-Input/?ALLSTEPS.

Unfortunately my signal source is my smartphone using a freqency generator app and I am working with single sine waves for the beginning.
I will try coupling the audiosignal via voltage divider.
You are right, there is nothing controlling the analogRead frequency, but this doesn't seem to be a problem in the examples I found.

The Radix4_Due library seems to be perfect, it also has a constant sampling rate (48kHz) and works with the DUE. But I just can't find more information about it than on this page https://coolarduino.wordpress.com/2014/03/11/fft-library-for-arduino-due-sam3x-cpu/ and in the library itself.
The example runs, but only at a buffer size of 2048. If I try to change it in the libraries, the DUE does nothing.

So the question should be now, how to work with the Radix4_Due library and change the array size.

Edit: circuit is a voltage divider with 2x10k and signal coupling with 100nF. Average voltage then is 1,637V and my smartphone puts out ~0,165V AC.
Using the example from the Radix4_Due, it outputs this buffer at 3,5kHz (plotted in excel):

In detail it looks like this (point at the middle, samples 1000...1050):

The FFT looks like this: .

That means it is correctly working and the input circuit does well.

And now the same thing for 256 array size...


The example runs, but only at a buffer size of 2048. If I try to change it in the libraries, the DUE does nothing.

If you could tell us, specifically, what you did to change the array size, it might lead to a solution.


I got it working. Had to change these values in Radix4.h:

Code: [Select]
#define    FFT_SIZE         256 // change from 2048 to 256
#define    NWAVE             256 // change from 2048 to 256

and also the array const int16_t  Sinewave[NWAVE] had to be changed: simply comment the large array out and take the smaller one. Same for const uint32_t  Hamming[FFT_SIZE].

Do this change in the sketch:
Code: [Select]
const       int         dc_offset       = 255; //change from 2048 to 256

and it works!


DUE has 12-bits ADC, so dc_offset should be 2047 if you biased inputs to Vcc/2.
There is one more,
Code: [Select]
#define    LOG2_FFT           X                     /* log2 FFT_SIZE */

Should I tell you what is correct value fot fft = 256?


I've been trying to use this library to do some beat detection - however, I've found that the documentation for this library is pretty light so I'm having some trouble adapting the code to my project.

How can I adapt the code so that there is only 16 or 32 bins? I need the FFT to run as fast as possible and I don't need as many bins as this library is currently pumping out.


Go Up