Close

Fourier Transform

A project log for Radar Sensor

This project will be using an InnoSent IPM 165C and / or IVS 362 module to sense distance and motion towards / away from the observer.

capt-flatus-oflahertyCapt. Flatus O'Flaherty ☠ 05/12/2021 at 10:370 Comments

On the right hand side is displayed readings from the oscilloscope with red being the output trianglular wave which feeds into the varactor input of the radar module. The blue trace is the output from the radar, amplified by the 2 stage op amp. The signal generator on the 'scope is not great quality, as can be seen by it's severe grainyness. However, on the left hand side, the FT generated by the Feather M4 expres still manages to seperate the poignant frequencies that give an indication of object size and distance from the sensor. Code for the FT is given below.
 /* This example shows the most basic usage of the Adafruit ZeroFFT library.
 * it calculates the FFT and prints out the results along with their corresponding frequency
 * 
 * The signal.h file constains a 200hz sine wave mixed with a weaker 800hz sine wave.
 * The signal was generated at a sample rate of 8000hz.
 * 
 * Note that you can print only the value (coment out the other two print statements) and use
 * the serial plotter tool to see a graph.
 */

#include "Adafruit_ZeroFFT.h"
#include "signal.h"

//the signal in signal.h has 2048 samples. Set this to a value between 16 and 2048 inclusive.
//this must be a power of 2
// #define DATA_SIZE 1024
#define DATA_SIZE 1024 // This is compatible with Arduino serial plotter where x axis ring buffer cant be changed from 500.
// To make the actual plot, data size is reduced to 1000 and then divided by 2.

// the sample rate:
#define FS 39700 // Limited by speed of analogRead

int16_t data[DATA_SIZE];
int16_t bigData[DATA_SIZE];

// the setup routine runs once when you press reset:
void setup() 
{
  Serial.begin(115200);
  while(!Serial); //wait for serial to be ready

 /*  // run the FFT
  ZeroFFT(signal, DATA_SIZE);

  // data is only meaningful up to sample rate/2, discard the other half
  for(int i=0; i<DATA_SIZE/2; i++)
  {
    
    //print the frequency
    //Serial.print(FFT_BIN(i, FS, DATA_SIZE));
    //Serial.print(" Hz: ");

    //print the corresponding FFT output
    //Serial.println(signal[i]);
  }
 */
}

void loop() 
{

  for(int i=0; i<DATA_SIZE; i++)
  {
    bigData[i] = 0;
  }

  int32_t avg = 0;
  unsigned long beforeMicros = micros();
  int k = 50;

  for(int j=0; j<k; j++)
  {
    for(int i=0; i<DATA_SIZE; i++)
    {
      int16_t val = analogRead(A2);
      // delayMicroseconds(50);
      // delayMicroseconds(10); // ( 1u = 1MHz, 10u = 100 KHz, 100u = 10KHz)
      avg += val;
      data[i] = val;
    }
    unsigned long afterMicros = micros();
    float totalMicros = afterMicros - beforeMicros;

    //remove DC offset and gain up to 16 bits
    avg = avg/DATA_SIZE;
    for(int i=0; i<DATA_SIZE; i++) data[i] = (data[i] - avg) * 64;
    
    //run the FFT
    ZeroFFT(data, DATA_SIZE);

    for(int i=0; i<DATA_SIZE; i++)
    {
      bigData[i] = data[i] + bigData[i];
    }
  }
  
  int dataMax = 0;
  int dataMaxIndex = 600;

  for(int i=0; i<DATA_SIZE; i++)
  {
    data[i] = bigData[i]/k;
    // Find whichvalue of i gives the fundamental frequency:
    if(data[i] > dataMax)
    {
      dataMax = data[i];
      dataMaxIndex = i;
    }
  }

  int fundamental_center = dataMaxIndex;
  int fundamental_1 = fundamental_center - 4;
  int fundamental_2 = fundamental_center - 3;
  int fundamental_3 = fundamental_center - 2;
  int fundamental_4 = fundamental_center - 1;
  int fundamental_5 = fundamental_center + 0;
  int fundamental_6 = fundamental_center + 1;
  int fundamental_7 = fundamental_center + 2;
  int fundamental_8 = fundamental_center + 3;
  int fundamental_9 = fundamental_center + 4;

  //data is only meaningful up to sample rate/2, discard the other half
  for(int i=0; i<(DATA_SIZE-24)/2; i++) // The '-24' is to try get the data to fit in Arduino serial plot window.
  {
    // Try and remove the fundamental frequency from the plot:
    if((i==fundamental_1)||(i==fundamental_2)||(i==fundamental_3)||(i==fundamental_4)||(i==fundamental_5)||(i==fundamental_6)||(i==fundamental_7)||(i==fundamental_8)||(i==fundamental_9))
    {
      data[i] = 0;
      // Serial.println(data[i]);
    }
    if(data[i]<0)
    {
      data[i]=0;
      // Serial.print(" negative value detected at index: ");Serial.println(i);
    }
    // print the frequency
    // Serial.print(FFT_BIN(i, FS, DATA_SIZE));
    // Serial.print(" Hz: ");

    // print the corresponding FFT output
    Serial.println(data[i]);
  }

  // delayMicroseconds(1000);
  // Serial.print(" Total micro seconds: ");Serial.println(totalMicros);
  // Serial.print(" Data size: ");Serial.println(DATA_SIZE);
  // Serial.print(" Time per analogRead: ");Serial.print(totalMicros/DATA_SIZE);Serial.println(" micro seconds");
  // Serial.print(" analogRead frequency: ");Serial.print((1/((totalMicros/DATA_SIZE)/1000000))/1000);Serial.print(" KHz");
  // Serial.print(" dataMaxIndex value: ");Serial.println(dataMaxIndex);


  // delay(1000);
}
People might notice a rather clumsily coded high pass filter which takes out some of the frequency bands around the fundamental frequency. Needs to be improved with something a bit more elegant, I think.

Discussions