I have code working that generates pink noise on the dac, plays it to a surface exciter (via an amp), and then reads it back in on an adc pin via a piezo sensor.
The purpose is to be able to tell if the structure to which the sensor is attached is touched, since that presumably alters the power distribution in the FFT-derived frequency bins. Detection ideally would occur quickly (10ms?).
This leads to two main questions:
1) Is pink (or white) noise really the way to do this, because, being random, I assume that a large number of FFT cycles must be performed to get good average power distributions?
Further, this is on a 3D printer which is going to have electrical noise and vibrations from the motors, perhaps causing false positives. I am using pink/white noise because this is what was suggested by someone else who did this project, but I'm wondering if perhaps a couple individual frequencies would have more deterministic behavior and thus deviation from the baseline signal could be more quickly and accurately recognized.
2) Regardless of the answer to #1 above, how does one determine what constitutes "different" to distinguish a "touch" from "no touch" situation? I could see applying conventional statistics to the FFT data points to get a p value, but I'm guessing this is not how it is done with sound. However, I can't find an example of just how it is done, although I know similar techniques are used for, for example, listening to motors and bearings to see if a change in the frequency amplitudes indicate problems.
This code works great as far as it goes, but I don't know how to make a reliable decision based on the data gathered:
==================================
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// Set up input, outputs, filters, connections and FFT object
// Uncomment one noise source
// AudioSynthNoisePink noise;
AudioSynthWaveformSine noise;
AudioInputAnalog adc1(A8);
AudioOutputAnalog dac1; // only available on A14, takes no pin
AudioFilterStateVariable filter1;
AudioAnalyzeFFT1024 myFFT;
// AudioConnection parameters take form (source, sourcePort, destination, destinationPort)
// Some objects only have one port, in which case 0's can be optional
AudioConnection patchCord1(noise, 0, filter1, 0);
AudioConnection patchCord2(filter1, 0, dac1, 0);
AudioConnection patchCord3(adc1, 0, myFFT, 0);
void setup() {
// Audio memory must be allocated in blocks. A block is 128 samples, or about 2.9ms.
AudioMemory(12);
// Configure the FFT window algorithm to use (AudioWindowHanning1024 is generally advised), but
// http://www.ni.com/white-paper/4278/en/ suggests that no windowing should be used for white noise
myFFT.windowFunction(NULL);
// Set frequency corner of filter
//filter1.frequency(1000);
// For pure tone set frequency, comment if using white/pink noise
noise.frequency(200);
// Won't play until amplitude is non-zero
noise.amplitude(1);
}
void loop() {
float n;
int i;
if (myFFT.available()) {
// each time new FFT data is available, print first X bins to Serial Monitor
Serial.print("FFT: ");
for (i=0; i<30; i++) {
n = myFFT.read(i);
if (n >= 0.01) {
Serial.print;
Serial.print(" ");
} else {
Serial.print(" - "); // don't print "0.00"
}
}
Serial.println();
}
}
The purpose is to be able to tell if the structure to which the sensor is attached is touched, since that presumably alters the power distribution in the FFT-derived frequency bins. Detection ideally would occur quickly (10ms?).
This leads to two main questions:
1) Is pink (or white) noise really the way to do this, because, being random, I assume that a large number of FFT cycles must be performed to get good average power distributions?
Further, this is on a 3D printer which is going to have electrical noise and vibrations from the motors, perhaps causing false positives. I am using pink/white noise because this is what was suggested by someone else who did this project, but I'm wondering if perhaps a couple individual frequencies would have more deterministic behavior and thus deviation from the baseline signal could be more quickly and accurately recognized.
2) Regardless of the answer to #1 above, how does one determine what constitutes "different" to distinguish a "touch" from "no touch" situation? I could see applying conventional statistics to the FFT data points to get a p value, but I'm guessing this is not how it is done with sound. However, I can't find an example of just how it is done, although I know similar techniques are used for, for example, listening to motors and bearings to see if a change in the frequency amplitudes indicate problems.
This code works great as far as it goes, but I don't know how to make a reliable decision based on the data gathered:
==================================
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// Set up input, outputs, filters, connections and FFT object
// Uncomment one noise source
// AudioSynthNoisePink noise;
AudioSynthWaveformSine noise;
AudioInputAnalog adc1(A8);
AudioOutputAnalog dac1; // only available on A14, takes no pin
AudioFilterStateVariable filter1;
AudioAnalyzeFFT1024 myFFT;
// AudioConnection parameters take form (source, sourcePort, destination, destinationPort)
// Some objects only have one port, in which case 0's can be optional
AudioConnection patchCord1(noise, 0, filter1, 0);
AudioConnection patchCord2(filter1, 0, dac1, 0);
AudioConnection patchCord3(adc1, 0, myFFT, 0);
void setup() {
// Audio memory must be allocated in blocks. A block is 128 samples, or about 2.9ms.
AudioMemory(12);
// Configure the FFT window algorithm to use (AudioWindowHanning1024 is generally advised), but
// http://www.ni.com/white-paper/4278/en/ suggests that no windowing should be used for white noise
myFFT.windowFunction(NULL);
// Set frequency corner of filter
//filter1.frequency(1000);
// For pure tone set frequency, comment if using white/pink noise
noise.frequency(200);
// Won't play until amplitude is non-zero
noise.amplitude(1);
}
void loop() {
float n;
int i;
if (myFFT.available()) {
// each time new FFT data is available, print first X bins to Serial Monitor
Serial.print("FFT: ");
for (i=0; i<30; i++) {
n = myFFT.read(i);
if (n >= 0.01) {
Serial.print;
Serial.print(" ");
} else {
Serial.print(" - "); // don't print "0.00"
}
}
Serial.println();
}
}