FFT Serial Monitor prints only "st"

Hi all, I’m working on a spectrum analyzer, but I’ve run into a problem where the only thing printed out into the serial monitor is “st” and I have no clue why.

11:30:13.896 → st

Resetting serial monitor just prints 11:30:44.711 → stst

I’ve checked the ADC values while playing a 600Hz tone, and it prints values between -512 and 511, which is expected since I subtracted a DC offset of 512.

#define LIN_OUT 1
#define FFT_N 256 // set to 256 point fft
#define ANALOG_PIN 0
#define ADC_INTERRUPT_MASK 0x10
#define SAMPLING_FREQ (16000000/(13*32))
#define DC_OFFSET 512

#include "FFT.h" // include the library

void setup() {
  Serial.begin(9600);          //  setup serial
  DIDR0 = 0x01; // turn off the digital input for adc0
  ADMUX = 0x40; // use adc0
  /*
     To get 10bit precision, from 50kHz to 200kHz clock must be supplied to the ADC. The
     chip runs at 16MHHz. If we were set the prescaler value to 128 -> 0b011 as part of the
     ADPS register value, then we get (16MHz/128) = 125kHz as the ADC Input Clock frequency.
     Since it takes 13 input clock cycles to get one Audio sample, the effective sampling
     frequency is 125Khz/13 = 9.6kHz. This is not sufficient as the audio frequency range
     is from 20Hz to 20KHz.
      If we choose a prescaler of 32, then the sampling frequency becomes 16000/(32*13) ~ 38KhZ
      From Nyquist's Theorem, the effective bandwidth is half the sample rate,= 19Khz
  */
  ADCSRA = 0xe5;  //ADC to free running mode

}

void loop() {
  cli();
  while (1) {
    for (int i = 0 ; i < 512 ; i += 2) { // we need 256 samples that represent the real  into 256 bins of the FFT
      while (!(ADC_INTERRUPT_MASK & ADCSRA)); // wait till the interrupt flag is 0. Which means conversion is in process
      ADCSRA = 0xf5; // Set ADIF to 1 and ADSC to 1, as the first conversion was made and we need to be ready for the next conversion
      byte low = ADCL; // fetch adc data
      byte high = ADCH;
      int value = (high << 8) | low; // form into an int
      int adc_val = value - DC_OFFSET;
      fft_input[i] = adc_val; // put real data into even bins
      fft_input[i + 1] = 0; // set odd bins to 0
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_lin(); // take the output of the fft */
    sei();

    Serial.println("start");
    for (byte i = 0 ; i < FFT_N / 2 ; i++) {
        Serial.print("Frequency: "); Serial.print(i * ((SAMPLING_FREQ / 2) / FFT_N)); Serial.print(" ");
        Serial.println(fft_lin_out[i]); // send out the data to the serial port so I can see what it's doing
    }
  }
}

You turned off interrupts. Serial uses interrupts.

[ Actually its more mysterious than that, you do re-enable them, but fail to turn them off around
the acquisition loop - perhaps that's creating deadlock? - why turn off all interrupts at all though, you
only need to turn off ADC interrupts ]

MarkT:
You turned off interrupts. Serial uses interrupts.

[ Actually its more mysterious than that, you do re-enable them, but fail to turn them off around
the acquisition loop - perhaps that’s creating deadlock? - why turn off all interrupts at all though, you
only need to turn off ADC interrupts ]

Hi Mark, thanks for the reply. I’ve actually been referencing the examples provided by the library, which I’ve pasted below.

So I’m not quite sure what is going wrong. Any suggestions would be very appreciated, as this is a bit of a brick wall

/*
fft_adc_serial.pde
guest openmusiclabs.com 7.7.14
example sketch for testing the fft library.
it takes in data on ADC0 (Analog0) and processes them
with the fft. the data is sent out over the serial
port at 115.2kb.
*/

#define LOG_OUT 1 // use the log output function
#define FFT_N 256 // set to 256 point fft

#include <FFT.h> // include the library

void setup() {
  Serial.begin(115200); // use the serial port
  TIMSK0 = 0; // turn off timer0 for lower jitter
  ADCSRA = 0xe5; // set the adc to free running mode
  ADMUX = 0x40; // use adc0
  DIDR0 = 0x01; // turn off the digital input for adc0
}

void loop() {
  while(1) { // reduces jitter
    cli();  // UDRE interrupt slows this way down on arduino1.0
    for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples
      while(!(ADCSRA & 0x10)); // wait for adc to be ready
      ADCSRA = 0xf5; // restart adc
      byte m = ADCL; // fetch adc data
      byte j = ADCH;
      int k = (j << 8) | m; // form into an int
      k -= 0x0200; // form into a signed int
      k <<= 6; // form into a 16b signed int
      fft_input[i] = k; // put real data into even bins
      fft_input[i+1] = 0; // set odd bins to 0
    }
    fft_window(); // window the data for better frequency response
    fft_reorder(); // reorder the data before doing the fft
    fft_run(); // process the data in the fft
    fft_mag_log(); // take the output of the fft
    sei();
    Serial.println("start");
    for (byte i = 0 ; i < FFT_N/2 ; i++) { 
      Serial.println(fft_log_out[i]); // send out the data
    }
  }
}

I figured out what the "st" is. The serial monitor only printed out the first two letters of "start" in this line of code, although I don't know why.

Serial.println("start");