Go Down

Topic: digital low-pass filtering and fft for accelerometer data (Read 857 times) previous topic - next topic

shiwshwa

Hi,

I need some guidance on how to implement a digital low-pass filter that has a cutoff frequency of around 50Hz.

Also, i really need help to know how to plot a running fft plot on a LCD from accelerometer data for vibration readings. I tried using the fft library from openmusiclabs: http://wiki.openmusiclabs.com/wiki/ArduinoFFT but to be honest I dont really understand how to use the library, or whether it can even be used for accelerometer data.

Some info on hardware I'm using:
1) accelerometer is LSM303DLHC from ST which interfaces with Arduino Uno by i2c, as such the raw data is not from 0-1023 like ADC but actually from -32000 to 32000 (+/- 2g)
2) the data rate from the accelerometer is 100Hz, and the baud rate i need it set at 9600

I intend to plot a fft from 1-50Hz, with each bin representing 1Hz. May i know the steps i can take to do this?






jremington

The FFT functions operate on 16 bit integer data, and come with a clear example http://wiki.openmusiclabs.com/wiki/Example

Have you tried it? Mr. Google will gladly point you to many examples of creating a low pass digital filter for Arduino.

shiwshwa

Thanks for your reply,

Yes i did try it out and i keep seeing gibberish messages on the serial monitor, is it because i need to use Processing to see the plot?

Also, I did google a lot for digital low-pass filters, but I can't seem to find any that would allow me to have a cut-off frequency i wanted.

jremington

What plot? The FFT example just outputs numbers to the serial monitor.
You will probably have to understand how the low pass filter examples work, and modify them to fit your needs.

shiwshwa

Yep, i think the digital filtering shouldn't be an issue for me once i figure it out.

So then what do those numbers from the example represent?

jremington

If your input data are in the form of a time series, then the result of an FFT calculation is a list of number pairs representing the amplitudes and phases of frequency components that make up that time series.

If you don't know how to interpret the output, you will need to read about the theory of Fourier transforms. The ArduinoFFT site gives some links.

g_u_e_s_t

the output is in binary, not ascii characters, which is why it looks like gibberish.  you can change serial.write to serial.print and it should be readable, although you might have to go through and output each number, one at a time, rather than the batch operation shown.

you should also take a look at the equations for calculating the number of bands, band width, and sampling rate.

finally, the FHT on that site is a lower overhead program that does the same thing

shiwshwa

Thanks for the info, are the equations available on the website?

Anyway i tried using something like this:

for (int j=0;j<128;j++){
     
     Serial.print(fft_log_out[j]); // send out the data
    }

But i still get gibberish. May i know what i did wrong? Thanks in advance.

jremington

#8
Feb 09, 2014, 09:05 pm Last Edit: Feb 09, 2014, 09:21 pm by jremington Reason: 1
The library contains instructions on how to run the programs, please read them!
What you did above should have worked, but of course everything will be run together.
To print each value on a separate line, use
Code: [Select]
Serial.println(fft_log_out[j]); // send out the data
Note that there are only N/2 unique values, where N is the number of samples input to the FFT operation.

Quote
fft_mag_log() - This gives the magnitude of each bin in the FFT. It sums the squares of the imaginary and real, and then takes the square root, and then takes the log base 2 of that value. Therefore, the output is compressed in a logarithmic fashion, and is essentially in decibels (times a scaling factor). It takes no variables, and returns no variables. It uses a lookup table to calculate the log of the square root, and scales the output over the full 8b range {the equation is 16*(log2((img2 + real2)1/2))}. It is only an 8b value, and the values are taken from fft_input[], and returned in fft_log_out[]. The output values are in sequential order of FFT frequency bins, and there are only N/2 total bins, as the second half of the FFT result is redundant for real inputs.

shiwshwa

Thanks, after reading through the website I have a good idea on how to use the library.

However, using Serial.println does not help too. The problem is that after 13 numbers, the rest are gibberish, not that there were numbers in running order, which i do find weird.

pito


shiwshwa

Code: [Select]

/*
fft_adc.pde
guest openmusiclabs.com 8.18.12
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.  there is a pure data patch for
visualizing the data.
*/

#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.write(255); // send a start byte
    //Serial.write(fft_log_out,128);
    for (int j=0;j<128;j++){
      Serial.println(fft_log_out[j]); // send out the data
    }
  }
}


Basically i added in the last two lines and commented off the Serial.write commands which were originally in the code, thanks.

pito

#12
Feb 09, 2014, 10:16 pm Last Edit: Feb 09, 2014, 10:24 pm by pito Reason: 1
So do you measure signal on adc(0)? What kind of signal?

shiwshwa

This is just an example code from the openmusiclabs website. It intends to take input from the adc(0) pin and output fft values. I intend to use my accelerometer to detect vibrations, hence the need for a FFT plot.

jremington

Post an example of the output that you consider to be gibberish.

If you don't have anything connected to the ADC, you might expect random nonsense in the FFT output, or mostly zeros.
Doesn't it make sense to test the program with a known signal, to see if it produces the expected output?

Go Up