Created
May 14, 2019 14:07
-
-
Save atuline/437aa9a823a020d0e43a9c81a8920e50 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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