Skip to content

Instantly share code, notes, and snippets.

@atuline
Created May 14, 2019 14:07
Show Gist options
  • Save atuline/437aa9a823a020d0e43a9c81a8920e50 to your computer and use it in GitHub Desktop.
Save atuline/437aa9a823a020d0e43a9c81a8920e50 to your computer and use it in GitHub Desktop.
/* File: FFT_Peak
*
* By: Andrew Tuline
*
* Modified from:
*
* Date: May, 2019
*
* Use WEMOS D1 Mini and Sparkfun MEMS microphone.
*
* We sample at 10KHz through the ADC and run it through the FFT library.
*
* Also use FastLED for display routines.
*
* References:
*
* Arduino FFT https://github.com/kosme/arduinoFFT
* FastLED https://github.com/FastLED/FastLED
*
*/
#include "arduinoFFT.h" // ArduinoFFT library.
#include "FastLED.h" // FastLED library.
#if FASTLED_VERSION < 3001000
#error "Requires FastLED 3.1 or later; check github for latest code."
#endif
// Fixed definitions cannot change on the fly.
#define LED_DT D5 // Data pin to connect to the strip.
#define LED_CK D7 // Clock pin for WS2801 or APA102.
#define COLOR_ORDER GRB // It's GRB for WS2812 and BGR for APA102.
#define LED_TYPE WS2812 // Using APA102, WS2812, WS2801. Don't forget to modify LEDS.addLeds to suit.
#define NUM_LEDS 32 // Number of LED's.
uint8_t max_bright = 128; // Overall brightness.
struct CRGB leds[NUM_LEDS]; // Initialize our LED array.
// Palette definitions
CRGBPalette16 currentPalette = PartyColors_p;
CRGBPalette16 targetPalette;
TBlendType currentBlending = LINEARBLEND; // NOBLEND or LINEARBLEND
#define MIC_PIN A0 // Analog port for microphone
#define DC_OFFSET 500 // DC offset in mic signal
arduinoFFT FFT = arduinoFFT(); // Create FFT object.
const uint16_t samples = 64; // This value MUST ALWAYS be a power of 2
const double samplingFrequency = 5000; // Hz, must be less than 10000 due to ADC
unsigned int sampling_period_us;
unsigned long microseconds;
double vReal[samples]; // These are the input and output vectors. Input vectors receive computed results from FFT.
double vImag[samples];
#define SCL_INDEX 0x00
#define SCL_TIME 0x01
#define SCL_FREQUENCY 0x02
#define SCL_PLOT 0x03
void setup() {
Serial.begin(115200);
delay(1000); // Soft startup to ease the flow of electrons.
sampling_period_us = round(1000000*(1.0/samplingFrequency));
LEDS.addLeds<LED_TYPE, LED_DT, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(0xFFB0F0); // Use this for WS2812
FastLED.setBrightness(max_bright);
set_max_power_in_volts_and_milliamps(5, 500); // FastLED Power management set at 5V, 500mA.
Serial.println(" "); Serial.println("*****************Ready***********************");
} // setup()
void loop() {
fadeToBlackBy(leds, NUM_LEDS, 8);
sampler();
FFT.Windowing(vReal, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD); // Weigh data
FFT.Compute(vReal, vImag, samples, FFT_FORWARD); // Compute FFT.
FFT.ComplexToMagnitude(vReal, vImag, samples); // Compute magnitudes.
// Serial.println("Computed magnitudes:");
// PrintVector(vReal, (samples >> 1), SCL_FREQUENCY);
disp_peak();
FastLED.show();
} // loop()
void disp_peak() {
double x;
double v;
FFT.MajorPeak(vReal, samples, samplingFrequency, &x, &v);
// Serial.println(); Serial.print((int)(x/samplingFrequency*32*2)); Serial.print(" ");
// Serial.print(x, 6); Serial.print(", "); Serial.println(v, 6);Serial.println("\n\r");
uint8_t index = (int)(x/samplingFrequency*32*2);
// Serial.print(index); Serial.print(" "); Serial.println(vReal[index]);
leds[index] = ColorFromPalette(currentPalette, index, (int)vReal[index], currentBlending);
} // disp_peak()
void sampler() { // Fill up our array with samples.
microseconds = micros(); // Sampling timer.
for(int i=0; i<samples; i++) {
vReal[i] = analogRead(MIC_PIN) - DC_OFFSET; // Sampling from A0.
vImag[i] = 0;
while(micros() - microseconds < sampling_period_us){ }
microseconds += sampling_period_us;
} // for
}
void PrintVector(double *vData, uint16_t bufferSize, uint8_t scaleType) {
for (uint16_t i = 0; i < bufferSize; i++) {
double abscissa;
switch (scaleType) { // Print abscissa value.
case SCL_INDEX: abscissa = (i * 1.0); break;
case SCL_TIME: abscissa = ((i * 1.0) / samplingFrequency); break;
case SCL_FREQUENCY: abscissa = ((i * 1.0 * samplingFrequency) / samples); break;
default: break;
} // switch
// Serial.print(i);
// Serial.print(" ");
// Serial.print(abscissa, 6);
// if(scaleType==SCL_FREQUENCY) Serial.print("Hz");
// Serial.print(" ");
// Serial.println(vData[i], 4);
} // for
// Serial.println();
} // PrintVector()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment