Created
November 1, 2019 09:39
-
-
Save CelliesProjects/1edb773fbe7a41895139fd8e50526f0b to your computer and use it in GitHub Desktop.
FFT demo on M5Stack-Fire in Arduino IDE.
This file contains hidden or 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
| #include "arduinoFFT.h" | |
| //#include <M5Stack.h> | |
| #include <esp_wifi.h> | |
| #include <TFT_eSPI.h> | |
| //#include <M5Display.h> // This library is a lot faster! But also a lot larger. | |
| #define microphone 34 | |
| #define speaker 25 | |
| #define backlight 32 | |
| #define bufferSize 256 | |
| #define imgWidth 140 | |
| #define imgHeight 100 | |
| #define SAMPLING_FREQUENCY 22000 | |
| double vReal[bufferSize]; | |
| double vImag[bufferSize]; | |
| static volatile uint16_t currentSample = 0; | |
| static volatile bool bufferFilled = false; | |
| static hw_timer_t * sampleTimer = NULL; | |
| static portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; | |
| unsigned int sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQUENCY)); | |
| arduinoFFT FFT = arduinoFFT(); | |
| TFT_eSPI tft = TFT_eSPI(); | |
| TFT_eSprite img = TFT_eSprite(&tft); | |
| //this ISR should run on core 0 | |
| static void IRAM_ATTR _sampleISR() { | |
| if ( bufferFilled ) return; | |
| vReal[currentSample] = analogRead( microphone ); | |
| vImag[currentSample] = 0; | |
| portENTER_CRITICAL_ISR(&timerMux); | |
| currentSample++; | |
| portEXIT_CRITICAL_ISR(&timerMux); | |
| if (currentSample == bufferSize ) bufferFilled = true; | |
| } | |
| void setup() { | |
| pinMode( microphone, INPUT ); | |
| dacWrite( speaker, 0); | |
| ledcAttachPin( backlight, 0); | |
| ledcSetup( 0, 1300, 16 ); | |
| ledcWrite( 0, 0xFFFF / 16 ); //dimming the backlight will produce more base noise | |
| sampleTimer = timerBegin( 0, 80, true ); | |
| timerAttachInterrupt( sampleTimer, &_sampleISR, true ); | |
| timerAlarmWrite( sampleTimer, sampling_period_us, true ); | |
| timerAlarmEnable( sampleTimer ); | |
| esp_wifi_set_mode(WIFI_MODE_NULL); | |
| xTaskCreatePinnedToCore( | |
| updateTFT, /* Function to implement the task */ | |
| "updateTFT", /* Name of the task */ | |
| 3000, /* Stack size in words */ | |
| NULL, /* Task input parameter */ | |
| 5, /* Priority of the task */ | |
| NULL, /* Task handle. */ | |
| 0); | |
| } | |
| void loop() { | |
| vTaskDelete(NULL); | |
| } | |
| uint16_t fps; | |
| time_t previous; | |
| void updateTFT( void * pvParameters ) { | |
| tft.init(); | |
| tft.setRotation( 1 ); | |
| tft.fillScreen( TFT_BLUE ); | |
| tft.setTextSize( 2 ); | |
| img.setColorDepth( 8 ); | |
| img.setTextColor( TFT_WHITE); | |
| img.createSprite( imgWidth, imgHeight ); | |
| while ( true ) { | |
| if ( bufferFilled ) { | |
| img.fillScreen( TFT_BLACK ); | |
| // https://github.com/kosme/arduinoFFT | |
| FFT.Windowing(vReal, bufferSize, FFT_WIN_TYP_HAMMING, FFT_FORWARD); | |
| FFT.Compute(vReal, vImag, bufferSize, FFT_FORWARD); | |
| FFT.ComplexToMagnitude(vReal, vImag, bufferSize); | |
| for (int i = 2; i < (bufferSize/2); i++){ | |
| if (i<=2 ) displayBand(0,(int)vReal[i]); // 125Hz | |
| if (i >2 && i<=4 ) displayBand(1,(int)vReal[i]); // 250Hz | |
| if (i >4 && i<=7 ) displayBand(2,(int)vReal[i]); // 500Hz | |
| if (i >7 && i<=15 ) displayBand(3,(int)vReal[i]); // 1000Hz | |
| if (i >15 && i<=40 ) displayBand(4,(int)vReal[i]); // 2000Hz | |
| if (i >40 && i<=70 ) displayBand(5,(int)vReal[i]); // 4000Hz | |
| if (i >70 && i<=288 ) displayBand(6,(int)vReal[i]); // 8000Hz | |
| if (i >288 ) displayBand(7,(int)vReal[i]); // 16000Hz | |
| } | |
| portENTER_CRITICAL(&timerMux); | |
| bufferFilled = false; | |
| currentSample = 0; | |
| portEXIT_CRITICAL(&timerMux); | |
| img.pushSprite( 90, 10 ); | |
| } | |
| if ( time(NULL) != previous ) { | |
| tft.setCursor(105, 120); | |
| tft.printf( "%5.i fps", fps); | |
| previous = time(NULL); | |
| fps = 0; | |
| } | |
| fps++; | |
| delay(1); | |
| } | |
| } | |
| static inline void displayBand( const int band, const int dsize ){ | |
| img.fillRect( band * 20 + 5, imgHeight - dsize / ( bufferSize * 3 ) + 10 , 10, imgHeight, TFT_GREEN ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment