Advertisement
Attilator

32 band spectrum indicator for OLED

Feb 14th, 2020
281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*Copyright (c) 2019 Shajeeb TM
  2. Permission is hereby granted, free of charge, to any person obtaining a copy
  3. of this software and associated documentation files (the "Software"), to deal
  4. in the Software without restriction, including without limitation the rights
  5. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  6. copies of the Software, and to permit persons to whom the Software is
  7. furnished to do so, subject to the following conditions:
  8. The above copyright notice and this permission notice shall be included in all
  9. copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  13. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  14. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  15. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  16. SOFTWARE. */
  17.  
  18. #include <arduinoFFT.h>
  19. #include <SPI.h>
  20. //#include <Adafruit_GFX.h>                           //graphics library for OLED
  21. #include <Adafruit_SH1106.h>                          //OLED driver
  22. #include <Fonts/Picopixel.h>                     //selecting specific font from Adafruit GFX library
  23.  
  24. // SH1106 HW SPI, SDA-MOSI-11, CLK-13
  25. #define OLED_DC     6
  26. #define OLED_CS     7
  27. #define OLED_RESET  8
  28. Adafruit_SH1106 display(OLED_DC, OLED_RESET, OLED_CS);  
  29.  
  30. #define SAMPLES 64            //Must be a power of 2
  31. #define  xres 32              // Total number of  columns in the display, must be <= SAMPLES/2
  32. #define  yres 60  
  33.  
  34. int yvalue;
  35. double vReal[SAMPLES];
  36. double vImag[SAMPLES];
  37. const int buttonPin = 5;               // the number of the pushbutton pin
  38. int state = HIGH;                      // the current reading from the input pin
  39. int previousState = LOW;               // the previous reading from the input pin
  40. //unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
  41. //unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
  42.  
  43. arduinoFFT FFT = arduinoFFT();                                    // FFT object
  44.  
  45. void setup() {
  46. //Serial.begin(9600);
  47.   display.begin(SH1106_SWITCHCAPVCC);
  48.   display.setTextSize(1);                             //set OLED text size to 1 (1-6)
  49.   display.setTextColor(WHITE);                        //set text color to white
  50.   display.clearDisplay();                             //clear display
  51.  
  52.   ADCSRA = 0b11100101;        // Set the Analog Digital Convetor Status Register A to free running mode and set pre-scalar to 32 (0xe5)
  53. //ADCSRA = 0b11100100;        // changed last bit to change division factor from 32 to 16, to spread the display out of the left edge. It might not be as pure as original but visually provides more width.
  54.     ADMUX = 0b00000000;       // use pin A0 and external voltage reference
  55.     pinMode(buttonPin, INPUT);
  56.     delay(50);                // wait to get reference voltage stabilized
  57. /*
  58.     for(int i=0; i<xres; i++)
  59.         {peaks[i]=0;
  60. Serial.print("peaks[i]: "); Serial.print(peaks[i]); Serial.println(" ");
  61.         }
  62. */
  63. }
  64.  
  65. void loop() {
  66.  
  67. char data_avgs[xres];  
  68. int peaks[xres];
  69.  
  70.    // ++ Sampling
  71.    for(int i=0; i<SAMPLES; i++)
  72.     {
  73.       while(!(ADCSRA & 0x10));        // wait for ADC to complete current conversion ie ADIF bit set
  74.       ADCSRA = 0b11110101 ;               // clear ADIF bit so that ADC can do next operation (0xf5)
  75.       int value = ADC - 512 ;                 // Read from ADC and subtract DC offset caused value
  76.       vReal[i]= value/8;                      // Copy to bins after compressing. Division by 8 reduces the amplitude of the measured input so that it can be uniformly (vertical) fit in the display used
  77.       vImag[i] = 0;                        
  78. //Serial.print("value: "); Serial.print(value); Serial.println(" ");
  79.     }
  80.     // -- Sampling
  81.  
  82.  
  83.     // ++ FFT
  84.     FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
  85.     FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
  86.     FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
  87.     // -- FFT
  88.  
  89.    
  90.     // ++ re-arrange FFT result to match with no. of columns on display ( xres )
  91.     int step = (SAMPLES/2)/xres;
  92.     int c=0;
  93.     for(int i=0; i<(SAMPLES/2); i+=step)  
  94.     {
  95.       data_avgs[c] = 0;
  96.       for (int k=0 ; k< step ; k++) {
  97.           data_avgs[c] = data_avgs[c] + vReal[i+k];
  98.       }
  99.       data_avgs[c] = data_avgs[c]/step;
  100.       c++;
  101.     }
  102.     // -- re-arrange FFT result to match with no. of columns on display ( xres )
  103.  
  104.        
  105.     // ++ send to display according measured value
  106.     display.clearDisplay();                             //clear display
  107.     for(int i=0; i<xres; i++)
  108.     {
  109.       data_avgs[i] = constrain(data_avgs[i],0,80);            // set max & min values for buckets
  110.       data_avgs[i] = map(data_avgs[i], 0, 80, 0, yres+26);        // remap averaged values to yres +16 pixels for the title
  111.       yvalue=data_avgs[i];
  112.  
  113. // Serial.print("yvalue: "); Serial.print(yvalue); Serial.println("   ");
  114.  
  115.  
  116.       if (yvalue > peaks[i]) peaks[i] = yvalue ;
  117.           peaks[i] = peaks[i]-1;    
  118.  
  119.  
  120. /*
  121.       peaks[i] = peaks[i]-1;    // decay by one light
  122.       if (yvalue > peaks[i])
  123.           peaks[i] = yvalue ;
  124.       yvalue = peaks[i];    
  125. */  
  126.  
  127.    //Drawing columns    
  128.      display.drawLine(i*4,   yres, i*4,   yres-yvalue, WHITE);  
  129. //   display.drawLine(i*4+1, yres, i*4+1, yres-yvalue, WHITE);  // 2 pixel thick column
  130. //   display.drawLine(i*4+2, yres, i*4+2, yres-yvalue, WHITE);  // 3 pixel thick column
  131. //   display.drawLine(i*4+3, yres, i*4+3, yres-yvalue, WHITE);  // 4 pixel thick column
  132.  
  133. //       display.drawPixel(i*4, yres-peaks[i], WHITE);              //Drawing dots for peaks    
  134.      }
  135.      // -- send to display according measured value
  136.  
  137.  
  138.   display.setFont(&Picopixel);
  139.   display.setCursor(0,4);                             //set cursor to top of screen
  140.   display.print("      32 Channel Spectrum Indicator");             //print title to buffer
  141.   display.display();                                  //show the buffer
  142.  }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement