Go Down

Topic: Is my Arduino really doing FFT? (Read 6731 times) previous topic - next topic

Judd_Foster

Quote
Use an 8 or 16-bit integer FFT calculation to make things faster.

I need this for a voice recognition project, so I must have things as accurate as I can get get them. That means more frequency bins. However, if I took out all the float values and had my sine waves and cosine waves calculated beforehand, would it be any faster? I don't need the 8X8 Matrix display in my final project, it's just for testing purposes.

I had an idea to use an UNO for taking input from a mic and putting it into an XBee to transmit to another UNO or even my computer running Processing, so that all the data could be stored there, and maybe put on an SD card from that other UNO. Would this work too? I will need a reliable and fairly large storage space for at least 1MB+ of data, because there are a lot more things I want to implement on this Arduino before I'm finished with my project that need to be stored in the memory.

Thanks

Judd

jremington

#16
Nov 11, 2013, 10:32 pm Last Edit: Nov 11, 2013, 10:44 pm by jremington Reason: 1
If you insist on using an Arduino for voice recognition, you will be forced to make a tradeoff in speed versus accuracy versus data size. A 16 MHz, integer multiply CPU with only a few kilobytes of memory can't perform real time audio signal analysis of the required complexity using floating point arithmetic.

This is quite an ambitious project!

Edit: here is a great overview site on complex algebra, FFTs and other topics: http://www.katjaas.nl/home/home.html

Judd_Foster

I don't need it to do the dft in real time, just after I say a command into the microphone. After I finish speaking, then the Arduino scrambles all the data together and comes back with what I said. My goal was a 1-2 second delay maximum after I finished speaking. I just need a fast, easy way for my Arduino to store approx. 10 seconds maximum of audio sampling. I worked that out to be, if ADC is sampling at 20KHz, to be 20 KB of data for the full 10 seconds. Is there anything on the market that could store this memory fast enough for this sketch to run properly?

I was looking into a Netduino plus 2, which uses an ARM cortex A8, 168MHz, and 100+KB of RAM. Surely this would be enough to analyze my data! Would it be a better option?

Thanks

Judd

Judd_Foster

I have the code from Magician's Audio Input to Arduino http://coolarduino.wordpress.com/2012/06/22/audio-input-to-arduino/ and I have a problem with it. The timer1 and the audio sampling are correct, but I have this weird "bounce" effect that happens whenever I change the value of the analog input.
I have a switch hooked up to the input now just to change the extremes from 0 - 255, but I know that this "bounce effect" is not caused by the switch itself because the Arduino does this when I change the audio input using a potentiometer.
All I have hooked up is a 10K pulldown resistor and the input from the switch going to pin A0. Here is the code I used. I stripped it down to the bare minimum to isolate the problem. I also have a 8X8 LED Matrix hooked up via 74HC595N shift registers. The problem is not in them though because I have the Arduino Serial output into a processing bar graph, which shows the sudden spikes in the values, which look just like a switch de-bouncing. I think the problem is in my code, but I have absolutely no idea where it could be. I don't think magician's original code is supposed to do this.

Code: [Select]
#include "TimerOne.h"

#define FFTSIZE 16
#define ROWS 8

int input[FFTSIZE];
float output[FFTSIZE / 2];
float sine;
float cosine;

boolean finished;

static uint8_t  n_sampl;

int16_t temp;

int counter;
int k;
int threshold;
int rowCounter;

const int latchPin = 8;
const int dataPin = 12;
const int clkPin = 11;

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

void setup() {
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(clkPin, OUTPUT);
  pinMode(13, OUTPUT);

  Serial.begin(9600);

  ADCSRA = 0x87; // freq = 1/128  125 kHz. 13 cycles x 8     usec =  104 usec.
  //ADCSRA = 0x86; // freq = 1/64   250 kHz. 13 cycles x 4     usec =   52 usec.
  //ADCSRA = 0x85; // freq = 1/32   500 kHz. 13 cycles x 2     usec =   26 usec.
  //ADCSRA = 0x84; // freq = 1/16     1 MHz. 13 cycles x 1     usec =   13 usec.
  //ADCSRA = 0x83; // freq = 1/8      2 MHz. 13 cycles x 0.5   usec =  6.5 usec.
  //ADCSRA = 0x82; // freq = 1/4      4 MHz. 13 cycles x 0.25  usec = 3.25 usec.

  ADMUX = 0x40;
  ADCSRA |= (1 << ADSC);

  calibAudio();

  Timer1.initialize(150000);
  Timer1.attachInterrupt(audio);
}

void loop() {

  LEDDisplay();                          // to be filled in later
 
  finished = true;
}

void calibAudio() {
  for(counter = 0; counter < 32; counter++) {
    if(ADCSRA & 0x10) {
      temp = ADCL;
      temp += (ADCH << 8);
      ADCSRA |= (1 << ADSC);
      threshold += temp;
    }
  }
  threshold /= 32;
}

void audio() {
  digitalWrite(13, HIGH);
  if(finished == true) {
    if(ADCSRA & 0x10) {
      temp = ADCL;
      temp += (ADCH << 8);
      ADCSRA |= (1 << ADSC);
      input[n_sampl] = temp - threshold;
    }
    if(++n_sampl >= FFTSIZE) {
      n_sampl = 0;
    }
    finished = false;
  }
  digitalWrite(13, LOW);
}

void LEDDisplay() {
  for(counter = 0; counter < FFTSIZE; counter++) {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clkPin, MSBFIRST, B11111111);
    shiftOut(dataPin, clkPin, MSBFIRST, 255 - input[counter]);
    shiftOut(dataPin, clkPin, MSBFIRST, 255 - input[counter]);
    shiftOut(dataPin, clkPin, MSBFIRST, 255);
    digitalWrite(latchPin, HIGH);
    Serial.println(input[counter]);
  }
}

Any help would be great.

Thanks,

Judd

jremington

To test someone else's code, it is always a good idea to present it with an input where you know the answer, and see if the code reproduces the expected result. That means printed numbers, not displayed on an LED bar graph.

To test FFT code, give it a pure sine wave to start (as if the ADC were sampling a pure tone) and see if the result is a single frequency of the correct amplitude and phase. Then try giving it a square wave, etc.


Judd_Foster

Jremington:

Quote
That means printed numbers, not displayed on an LED bar graph

Like I said, I have the code printing out the raw input values into a processing serial monitor. I also deleted the part of the code where the led display is used. It still does the same thing

All I want my arduino to do is to print out the adc analysis values. No fft or anything involved in this code.

Thanks

Judd

Go Up