Note: This project is only for simple audio device, a Real Spectrum Analyser devices are use in Microwave signal, Radar Signal, Dish Antenna Signal, Cable frequencies Signal, etc. Do not try to use for these proposes your Arduino will burn or crash permanently.
In this blog you are learning about a Arduino Spectrum
Analyzer which follows:
>>SSD1306 Oled Display
>>Needed Parts
>>Libraries in we need to use
>>Super Easy Breadboard connection
>>Complete Code
SSD1306 Oled Display:
This very common and simple OLED Display for Arduino
that very less count of Pin to connect in arduino that called I2C two wire
interface the I2C stands for (I2C=IIC=Inter-Integrated Circuit) and OLED stands
for Organic Light-Emitting Diodes. The size of this oled display is 0.96 inch
that make it too much small and the total pixel is 128X64 px resolution you can
convert a pic to bitmap and program to show in this display. In 16X2 LCD
Display We need a backlight pin but in OLED this pin not required.
OLED Pins : Arduino Pins
Vin | 5V //this is power Pin
GND | GND //this is GND Pin
SCL | A5 // this is I2C Pins
SDA | A4 //this is I2C Pins
Varieties of Arduino Pin If you use:
Arduino Uno: SDA (A4), SCL (A5)
Arduino Nano: SDA (A4), SCL (A5)
Arduino Leonardo: SDA (20), SCL (21)
Arduino MEGA: SDA (20), SCL (21)
Needed Parts:
Arduino Uno
128x68 I2C OLED Display
Jumper Wires
Breadboard
Libraries Used in This Project:
If you are beginner for this project, you need to
download the Adafruit SSD1306 Master zip Library From SSD1306 available in Github
and also need one more Adafruit GFX Library master.zip that is also available in
Github. Open Arduino IDE Software go to the sketch tab, then here click include
library and click Add Zip Library here you can add your downloaded library you
can also download and install from Manage Library Option just search these
library in this box.
And Now for This Project need to download FIX_FFT.h
master zip from fix_fft.h and nano_engine.h library here Nano Engine (This is a built in header file of SSD1306).
Breadboard Connection:
Audio Input:
Complete Code:
// Copyright [2019] [colonelwatch] #include <fix_fft.h> // 8-bit FFT library modified for Arduino #include <ssd1306.h> // library for OLED #include <nano_engine.h> // library for nanoengine (which draws sector-by-sector on OLED because the ATtiny85 can't hold a full buffer) // To get this program to operate, the SDA and SCL pins must be reassigned to 0 and 2 respectively in the library header file // The file is located in libraries\ssd1306\src\intf\i2c\ssd1306_i2c_conf.h // Make sure to undo this if the library will be used again in the future // These are user-adjustable //#define LOG_OUTPUT // Uncomment to enable logarithmic output (exchanges absolute resoluton for more readable output; may require different below params) #define SAMPLING_FREQUENCY 15000 // Sampling frequency (Actual max measured frequency captured is half) #define TIME_FACTOR 3 // Smoothing factor (lower is more dynamic, higher is smoother) ranging from 1 to 10+ #define SCALE_FACTOR 12 // Direct scaling factor (raise for higher bars, lower for shorter bars) #ifdef LOG_OUTPUT const float log_scale = 64./log(64./SCALE_FACTOR + 1.); // Attempts to create an equivalent to SCALE_FACTOR for log function #endif const float coeff = 1./TIME_FACTOR; // Time smoothing coefficients (used to factor in previous data) const float anti_coeff = (TIME_FACTOR-1.)/TIME_FACTOR; const unsigned int sampling_period_us = round(1000000 * (2.0 / SAMPLING_FREQUENCY)); // Sampling period (doubled to account for overclock) int8_t data[64], buff[32]; // used to store FFT input/output and past data unsigned long microseconds; // used for timekeeping int summ, avg; // used for DC bias elimination NanoEngine<TILE_32x32_MONO> engine; // declares nanoengine void setup() { OSCCAL = 240; // Overclocks the MCU to around 30 MHz, set lower if this causes instability, raise if you can/want ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // clear ADC prescaler bits ADCSRA |= bit (ADPS2); // sets ADC clock in excess of 10kHz ADCSRA |= bit (ADPS0); ssd1306_128x64_i2c_init(); // initializes OLED ssd1306_clearScreen(); // clears OLED engine.begin(); // inititalizes nanoengine }; void loop() { summ = 0; for (int i = 0; i < 64; i++) { microseconds = micros(); data[i] = ((analogRead(A0)) >> 2) - 128; // Fitting analogRead data (range:0 - 1023) to int8_t array (range:-128 - 127) summ += data[i]; while (micros() < (microseconds + sampling_period_us)) { // Timing out uC ADC to fulfill sampling frequency requirement } } // Eliminating remaining DC component (produces usable data in FFT bin #0, which is usually swamped by DC bias) avg = summ/64; for (int i = 0; i < 64; i++){ data[i] -= avg; } fix_fftr(data, 6, 0); // Performing real FFT // Time smoothing by user-determined factor and user-determined scaling for(int count = 0; count < 32; count++){ if(data[count] < 0) data[count] = 0; // Eliminating negative output of fix_fftr #ifdef LOG_OUTPUT else data[count] = log_scale*log((float)(data[count]+1)); // Logarithmic function equivalent to SCALING_FACTOR*log2(x+1) #else else data[count] *= SCALE_FACTOR; // Linear scaling up according to SCALE_FACTOR #endif data[count] = (float)buff[count] * anti_coeff + (float)data[count] * coeff; // Smoothing by factoring in past data buff[count] = data[count]; // Storing current output as next frame's past data if(data[count] > 63) data[count] = 63; // Capping output at screen height } // Output to SSD1306 using nanoengine canvas from library engine.refresh(); // Mark entire screen to be refreshed engine.canvas.clear(); // Clear canvas as previous data for(int i = 0; i < 8; i++){ engine.canvas.drawVLine(i*4,31-(data[i]+1),31); // Draw to canvas data for lower-leftest sector (FFT bins 0 - 7, lower half) } engine.canvas.blt(0,32); // Outputs canvas to OLED with an offset (x pixels, y pixels) engine.canvas.clear(); for(int i = 0; i < 8; i++){ if(data[i] > 31) engine.canvas.drawVLine(i*4,31-(data[i]-31),31); // Draw to canvas data for upper-leftest sector (FFT bins 0 - 7, upper half) } engine.canvas.blt(0,0); engine.canvas.clear(); for(int i = 8; i < 16; i++){ engine.canvas.drawVLine((i-8)*4,31-(data[i]+1),31); // FFT bins 8 - 15, lower half } engine.canvas.blt(32,32); engine.canvas.clear(); for(int i = 8; i < 16; i++){ if(data[i] > 31) engine.canvas.drawVLine((i-8)*4,31-(data[i]-31),31); // FFT bins 9 - 15, upper half } engine.canvas.blt(32,0); engine.canvas.clear(); for(int i = 16; i < 24; i++){ engine.canvas.drawVLine((i-16)*4,31-(data[i]+1),31); // FFT bins 16 - 23, lower half } engine.canvas.blt(64,32); engine.canvas.clear(); for(int i = 16; i < 24; i++){ if(data[i] > 31) engine.canvas.drawVLine((i-16)*4,31-(data[i]-31),31); // FFT bins 16 - 23, upper half } engine.canvas.blt(64,0); engine.canvas.clear(); for(int i = 24; i < 32; i++){ engine.canvas.drawVLine((i-24)*4,31-(data[i]+1),31); // FFT bins 24 - 31, lower half } engine.canvas.blt(96,32); engine.canvas.clear(); for(int i = 24; i < 32; i++){ if(data[i] > 31) engine.canvas.drawVLine((i-24)*4,31-(data[i]-31),31); // FFT bins 24 - 31, upper half } engine.canvas.blt(96,0); }
This is not much hard to build just need some simple stuff. That all for guys.
Hi I need some help ? Can I get your email ID? By just sending a mail to iamsasi@gmail.com please
ReplyDeleteNor working,
ReplyDeleteWhat a crap instruction what is wrong with you,
ReplyDeleteIs it possible to connect 2 OLED at one Nano? I want to display the Spectrum for the left and right channel. Can you help me?
ReplyDeleteYes it is possible. Your OLEDS need to have different I2C Adresses
Delete