Advertisement
Attilator

OLED Spectrum analyzer FHT

Feb 24th, 2020
624
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* fht_adc.pde
  2. guest openmusiclabs.com 9.5.12 example sketch for testing the fht library.
  3. it takes in data on ADC0 (Analog0) and processes them with the fht.
  4. the data is sent out over the serial port at 115.2kb.  
  5. there is a pure data patch for visualizing the data.
  6. // http://wiki.openmusiclabs.com/wiki/ArduinoFHT */
  7.  
  8. // https://cassiopeia.hk/spectrumanalyser/
  9. //#define OCT_NORM 0                           // 0: no normalisation, more high freq 1: divided by number of bins, less high freq
  10. //#define OCTAVE 1
  11. // https://github.com/ayavilevich/ArduinoSoundLevelMeter/blob/master/ArduinoSoundLevelMeter.ino
  12. //#define LIN_OUT8 1 // use the linear byte output function
  13.  
  14. #define LOG_OUT 1                           // use the log output function
  15. #include <FHT.h>                            // include the library
  16. #define FHT_N 256                           // set to 256 point fht
  17. #include <Wire.h>                           // I2C library for OLED
  18. #include <Adafruit_GFX.h>                   // graphics library for OLED
  19. #include <Fonts/Picopixel.h>                //selecting specific font from Adafruit GFX library
  20. #include <Adafruit_SSD1306.h>               // OLED driver
  21. #define OLED_RESET 4                        // OLED reset, not hooked up but required by library
  22. Adafruit_SSD1306 display(OLED_RESET);       // declare instance of OLED library called display
  23. //char x = 0, ylim = 60;                    // variables for drawing the graphics - 128*64 pixels Display: 0-127 x 0-63
  24. char x = 0, ylim = 31;                      // variables for drawing the graphics - 128*32 pixels Display: 0-127 x 0-31
  25. const byte noise_level = 80;
  26. char title_height =7;                       // reserve the TOP rows for the title, 6 pixels high for picopixel +1 pixel for empty line
  27.  
  28. void setup() {
  29. //  Serial.begin(115200);                   // use the serial port
  30. //  Serial.begin(9600);                     // use the serial port
  31.   display.begin(SSD1306_SWITCHCAPVCC,0x3C); // begin OLED @ hex addy 0x3C
  32.   display.setTextSize(1);                   // set OLED text size to 1 (1-6)
  33.   display.setTextColor(WHITE);              // set text color to white
  34.   display.clearDisplay();                   // clear display
  35. //  analogReference(DEFAULT);               // Use default (5v) aref voltage.
  36.   analogReference(EXTERNAL);                // Use 3.3V pin as aref voltage to enable to display low amplitude signals. Connect 5k resistor between 3.3V and AREF PINs.
  37.  
  38. //  setFreeRunMode();
  39.   TIMSK0 = 0;                               // turn off timer0 for lower jitter
  40.   ADCSRA = 0xE5;                            // "ADC Enable", "ADC Start Conversion", "ADC Auto Trigger Enable"; 32 prescaler for 38.5KHz; 0xE4 for 16 prescaler; 0xE6 for 64 prescaler
  41. //ADMUX = 0x40;                             // b0100 0000; use adc0, right-align, use the full 10 bits resolution
  42.   ADMUX = 0x00;                             // b0000 0000; use external reference, connect 3.3V PIN and AREF via 5k resistor.
  43.   DIDR0 = 0x01;                             // turn off the digital input for adc0  
  44. }
  45.  
  46. void loop() {
  47.   while(1) {                                  // reduces jitter
  48.     cli();                                    // NO for TIMING
  49.     // unsigned long start_time = micros();   // YES for TIMING
  50.     for (int i = 0 ; i < FHT_N ; i++) {       // save 128 samples
  51.       while(!(ADCSRA & 0x10));                // wait for adc to be ready (ADIF)
  52.       ADCSRA = 0xf5;                          // restart adc
  53.       byte m = ADCL;                          // fetch adc data, the ADCL register first because reading the ADCH causes to ADC to update
  54.       byte j = ADCH;
  55.       int k = (j << 8) | m;                   // form into an int
  56.       k -= 0x0200;                            // form into a signed int
  57.       k <<= 6;                                // form into a 16b signed int
  58.       fht_input[i] = k;                       // put real data into bins
  59.     }
  60.  
  61.  
  62.     // Serial.println(micros()-start_time);   // yes for TIMING
  63.     fht_window();                             // window the data for better frequency response
  64.     fht_reorder();                            // reorder the data before doing the fht
  65.     fht_run();                                // process the data in the fht
  66.     // fht_mag_octave();                      // take the output of the fht
  67.     fht_mag_log();                            // take the output of the fht
  68.    // fht_mag_lin8();                         // take the output of the fht
  69.     sei();                                    // NO for TIMING
  70.    // Serial.write(255);                      // send a start byte
  71.    // Serial.write(fht_log_out, FHT_N/2);     // send out the data
  72.  
  73.    // OLED display
  74.        display.clearDisplay();                                    // clear display
  75.        for (int i=0; i< FHT_N/2; i+=2) {                          // output even bins because oled is 128x64 when FHT_N=256; use "(int i=2; i<FHT_N; i++)" when the first 2 bins contain noise
  76.             int dat = max((fht_log_out[i] - noise_level) / 4, 0); // scale the height
  77.                 dat = constrain(dat,0,ylim-title_height);         // "-title_height" protects the title area from the bars interference
  78.             display.drawLine(i+x, ylim, i+x, ylim-dat, WHITE);    
  79.             }
  80.       display.setFont(&Picopixel);
  81.       display.setCursor(0,4);                                    // define the left upper top of the screen for this font
  82.       //display.setCursor(0,4);                                  // set cursor to left top of the display
  83.       display.print("@ttila 64-channel Spectrum Analyzer");      // print title to buffer for regular fonts
  84.       display.display();        
  85.  
  86.   }  // end while  
  87. } // end loop
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement