diff --git a/docs/hardware_fft.png b/docs/hardware_fft.png new file mode 100644 index 0000000..5bd8740 Binary files /dev/null and b/docs/hardware_fft.png differ diff --git a/docs/software_fft.png b/docs/software_fft.png new file mode 100644 index 0000000..a70e89f Binary files /dev/null and b/docs/software_fft.png differ diff --git a/microphone_esp8266_fft/Arduino/microphone_esp8266_fft/microphone_esp8266_fft.ino b/microphone_esp8266_fft/Arduino/microphone_esp8266_fft/microphone_esp8266_fft.ino new file mode 100644 index 0000000..bd4c16e --- /dev/null +++ b/microphone_esp8266_fft/Arduino/microphone_esp8266_fft/microphone_esp8266_fft.ino @@ -0,0 +1,117 @@ +#include //https://github.com/kosme/arduinoFFT +// //https://github.com/G6EJD/ESP32-8266-Audio-Spectrum-Display + +#define NUM_BANDS 8 +#define READ_DELAY 50 +#define USE_RANDOM_DATA false + +#include //https://github.com/kitesurfer1404/WS2812FX +#include "custom/VUMeter.h" //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +arduinoFFT FFT = arduinoFFT(); + +#define SAMPLES 512 //Must be a power of 2 +#define SAMPLING_FREQUENCY 40000 //Hz, must be 40000 or less due to ADC conversion time. Determines maximum frequency that can be analysed by the FFT. + +// Use ADC1 so that WiFi stuff doesnt interfere with ADC measurements +#define ADC_PIN 36 // 36 = PIN VP on Lolin D32 + +int amplitude = 200; +unsigned int sampling_period_us; +unsigned long microseconds; +byte peak[] = {0, 0, 0, 0, 0, 0, 0}; +double vReal[SAMPLES]; +double vImag[SAMPLES]; +unsigned long newTime, oldTime; + +// LED Settings +#define LED_COUNT 120 +#define LED_PIN 12 + +WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); + +void displayBand(int band, int dsize) +{ + int dmax = amplitude; + if (dsize > dmax) + dsize = dmax; + if (dsize > peak[band]) + { + peak[band] = dsize; + } +} + +void setup() +{ + Serial.begin(256000); + sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY)); + pinMode(ADC_PIN, INPUT); + + ws2812fx.init(); + ws2812fx.setBrightness(32); + + // setup the custom effect + uint32_t colors[] = {GREEN, YELLOW, RED}; + uint8_t vuMeterMode = ws2812fx.setCustomMode(F("VU Meter"), vuMeter); + ws2812fx.setSegment(0, 0, LED_COUNT-1, vuMeterMode, colors, READ_DELAY, NO_OPTIONS); + + ws2812fx.start(); +} + +void loop() +{ + for (int i = 0; i < SAMPLES; i++) + { + newTime = micros() - oldTime; + oldTime = newTime; + vReal[i] = analogRead(ADC_PIN); // A conversion takes about 1mS on an ESP8266 + vImag[i] = 0; + while (micros() < (newTime + sampling_period_us)) + { + delay(0); + } + } + FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD); + FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD); + FFT.ComplexToMagnitude(vReal, vImag, SAMPLES); + for (int i = 2; i < (SAMPLES / 2); i++) + { // Don't use sample 0 and only first SAMPLES/2 are usable. Each array eleement represents a frequency and its value the amplitude. + if (vReal[i] > 2000) + { // Add a crude noise filter, 10 x amplitude or more + if (i <= 2) + displayBand(0, (int)vReal[i] / amplitude); // 125Hz + if (i > 3 && i <= 5) + displayBand(1, (int)vReal[i] / amplitude); // 250Hz + if (i > 5 && i <= 7) + displayBand(2, (int)vReal[i] / amplitude); // 500Hz + if (i > 7 && i <= 15) + displayBand(3, (int)vReal[i] / amplitude); // 1000Hz + if (i > 15 && i <= 30) + displayBand(4, (int)vReal[i] / amplitude); // 2000Hz + if (i > 30 && i <= 53) + displayBand(5, (int)vReal[i] / amplitude); // 4000Hz + if (i > 53 && i <= 200) + displayBand(6, (int)vReal[i] / amplitude); // 8000Hz + if (i > 200) + displayBand(7, (int)vReal[i] / amplitude); // 16000Hz + } + } + if (millis() % 4 == 0) + { + for (byte band = 0; band < NUM_BANDS; band++) + { + if (peak[band] > 0) + peak[band] /= 2; + } + } // Decay the peak + for (byte band = 0; band < NUM_BANDS; band++) + { + uint16_t value = peak[band]; + vuMeterBands[band] = value < 1 ? 0 : map(value, 1, amplitude, 0, 255); + Serial.print(value); + Serial.print("\t"); + } + Serial.println(); + + ws2812fx.service(); +} \ No newline at end of file diff --git a/microphone_esp8266_fft/platformio.ini b/microphone_esp8266_fft/platformio.ini new file mode 100644 index 0000000..98320c5 --- /dev/null +++ b/microphone_esp8266_fft/platformio.ini @@ -0,0 +1,51 @@ +[platformio] +src_dir = ./Arduino/microphone_esp8266_fft +env_default = esp32dev + +[common] +framework = arduino +build_flags = + -w + -D PIO_PLATFORM +lib_deps = + arduinoFFT + WS2812FX + debsahu/MD_MSGEQ7 +; monitor_speed = 115200 +monitor_speed = 256000 +upload_speed = 115200 +upload_speed_fast = 921600 +targets_eum = erase, upload, monitor +targets_um = upload, monitor + +# see: http://docs.platformio.org/en/latest/platforms/espressif32.html +[common:esp32] +framework = ${common.framework} +platform = espressif32@1.7.0 +;platform = https://github.com/platformio/platform-espressif32.git#feature/stage +build_flags = + ${common.build_flags} + -D ARDUINO_ARCH_ESP32 +monitor_speed = ${common.monitor_speed} +upload_speed = ${common.upload_speed} +upload_speed_fast = ${common.upload_speed_fast} +lib_deps = + ${common.lib_deps} +lib_ignore = + DDUpdateUploadServer + +[env:esp32dev] +; board = esp32dev +board = lolin_d32 +framework = ${common.framework} +platform = ${common:esp32.platform} +monitor_speed = ${common:esp32.monitor_speed} +upload_speed = ${common:esp32.upload_speed_fast} +build_flags = + ${common:esp32.build_flags} +lib_deps = + ${common:esp32.lib_deps} + PubSubClient +lib_ignore = + ${common:esp32.lib_ignore} +;targets = ${common.targets_um} \ No newline at end of file diff --git a/microphone_esp8266_msgeq7/Arduino/microphone_esp8266_msgeq7/microphone_esp8266_msgeq7.ino b/microphone_esp8266_msgeq7/Arduino/microphone_esp8266_msgeq7/microphone_esp8266_msgeq7.ino new file mode 100644 index 0000000..8ebd262 --- /dev/null +++ b/microphone_esp8266_msgeq7/Arduino/microphone_esp8266_msgeq7/microphone_esp8266_msgeq7.ino @@ -0,0 +1,64 @@ +#include //https://github.com/debsahu/MD_MSGEQ7 + +#define NUM_BANDS MAX_BAND +#define USE_RANDOM_DATA false + +#include //https://github.com/kitesurfer1404/WS2812FX +#include "custom/VUMeter.h" //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +// hardware pin definitions - change to suit circuit +#define DATA_PIN 34 +#define RESET_PIN 27 +#define STROBE_PIN 26 + +// frequency reading the IC data +#define READ_DELAY 50 + +// LED Settings +#define LED_COUNT 120 +#define LED_PIN 12 + +MD_MSGEQ7 MSGEQ7(RESET_PIN, STROBE_PIN, DATA_PIN); +WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); + +void setup() +{ + Serial.begin(256000); + Serial.println("[MD_MSG_SEQ7_Serial]"); + MSGEQ7.begin(); + analogReadResolution(10); + + ws2812fx.init(); + ws2812fx.setBrightness(255); + + // setup the custom effect + uint32_t colors[] = {GREEN, YELLOW, RED}; + uint8_t vuMeterMode = ws2812fx.setCustomMode(F("VU Meter"), vuMeter); + ws2812fx.setSegment(0, 0, LED_COUNT-1, vuMeterMode, colors, READ_DELAY, NO_OPTIONS); + + ws2812fx.start(); +} + +void loop() +{ + static long then = 0; + long now = millis(); + + if(now > then + READ_DELAY) { + + MSGEQ7.read(); + + // Serial output + for (uint8_t i=0; i