Audio Spectrum Analyzer Display
In this Intractable I am going to show how to make a program in Processing that analyzes sound on your speaker and sends data to an Arduino that controls an LED matrix to show the spectrum analysis with out any wire connection.
Components:
1) Arduino Nano: https://roboman.in/59h4
2) Arduino Nano Type C : https://roboman.in/xkfu
3) TP-4056 Module : https://roboman.in/oa0m
4) DC-DC Boost Converter LM2587 or XL6019 : https://roboman.in/kkuj
5) MAX7219 Dot Matrix 4 in 1 Display Module: https://roboman.in/jekd
6) Sound Sensor : Sound Sensor :https://roboman.in/vs1e
7) 18650 Lithium Battery 2500mah 3C :https://roboman.in/utwc
7) 18650 Lithium Battery 2600mah 3C : https://roboman.in/mmab
7) 18650 Lithium Battery 2200mah 1C :https://roboman.in/70b5
7) 18650 Lithium Battery 2000mah 1C :https://roboman.in/7em9
7) 18650 Lithium Battery 1800mah 1C :https://roboman.in/ywss
Diagram:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
#include <arduinoFFT.h> #include <MD_MAX72xx.h> #include <SPI.h> #include <EEPROM.h> #define SAMPLES 64 // Must be a power of 2 #define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW // Set display type so that MD_MAX72xx library treets it properly #define MAX_DEVICES 4 // Total number display modules #define CLK_PIN 13 // Clock pin to communicate with display #define DATA_PIN 11 // Data pin to communicate with display #define CS_PIN 10 // Control pin to communicate with display #define xres 32 // Total number of columns in the display, must be <= SAMPLES/2 #define yres 8 // Total number of rows in the display int audio_response = 10; // put a value between 10 and 80. Smaller the number, higher the audio response int MY_ARRAY[]={0, 128, 192, 224, 240, 248, 252, 254, 255}; // default = standard pattern int MY_MODE_1[]={0, 128, 192, 224, 240, 248, 252, 255, 255}; // standard pattern int MY_MODE_2[]={0, 128, 64, 32, 16, 8, 4, 2, 1}; // only peak pattern int MY_MODE_3[]={0, 128, 192, 160, 144, 136, 132, 130, 129}; // only peak + bottom point int MY_MODE_4[]={0, 128, 192, 160, 208, 232, 244, 250, 253}; // one gap in the top , 3rd light onwards int MY_MODE_5[]={0, 1, 3, 7, 15, 31, 63, 127, 255}; // standard pattern, mirrored vertically double vReal[SAMPLES]; double vImag[SAMPLES]; char data_avgs[xres]; int yvalue; int displaycolumn , displayvalue; int peaks[xres]; const int buttonPin = 5; // the number of the pushbutton pin int state = HIGH; // the current reading from the input pin int previousState = LOW; // the previous reading from the input pin int displaymode = 1; unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // display object arduinoFFT FFT = arduinoFFT(); // FFT object void setup() { EEPROM.update(1,1); //(memory address, value), RUN THIS FOR THE FIRST TIME displaymode = EEPROM.read(1); ADCSRA = 0b11100101; // set ADC to free running mode and set pre-scalar to 32 (0xe5) ADMUX = 0b00000000; // use pin A0 and external voltage reference pinMode(buttonPin, INPUT); mx.begin(); // initialize display delay(50); // wait to get reference voltage stabilized } void loop() { // ++ Sampling for(int i=0; i<SAMPLES; i++) { while(!(ADCSRA & 0x10)); // wait for ADC to complete current conversion ie ADIF bit set ADCSRA = 0b11110101 ; // clear ADIF bit so that ADC can do next operation (0xf5) int value = ADC - 512 ; // Read from ADC and subtract DC offset caused value vReal[i]= value/8; // Copy to bins after compressing vImag[i] = 0; } // -- Sampling // ++ FFT FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD); FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD); FFT.ComplexToMagnitude(vReal, vImag, SAMPLES); // -- FFT // ++ re-arrange FFT result to match with no. of columns on display ( xres ) int step = (SAMPLES/2)/xres; int c=0; for(int i=0; i<(SAMPLES/2); i+=step) { data_avgs[c] = 0; for (int k=0 ; k< step ; k++) { data_avgs[c] = data_avgs[c] + vReal[i+k]; } data_avgs[c] = data_avgs[c]/step; c++; } // -- re-arrange FFT result to match with no. of columns on display ( xres ) // ++ send to display according measured value for(int i=0; i<xres; i++) { data_avgs[i] = constrain(data_avgs[i],0,80); // set max & min values for buckets data_avgs[i] = map(data_avgs[i], 0, 80, 0, yres); // remap averaged values to yres yvalue=data_avgs[i]; peaks[i] = peaks[i]-1; // decay by one light if (yvalue > peaks[i]) peaks[i] = yvalue ; yvalue = peaks[i]; displayvalue=MY_ARRAY[yvalue]; displaycolumn=31-i; mx.setColumn(displaycolumn, displayvalue); // for left to right } // -- send to display according measured value displayModeChange (); // check if button pressed to change display mode } void displayModeChange() { int reading = digitalRead(buttonPin); if (reading == HIGH && previousState == LOW && millis() - lastDebounceTime > debounceDelay) // works only when pressed { switch (displaymode) { case 1: // move from mode 1 to 2 displaymode = 2; EEPROM.update(1,2); for (int i=0 ; i<=8 ; i++ ) { MY_ARRAY[i]=MY_MODE_2[i]; } break; case 2: // move from mode 2 to 3 displaymode = 3; EEPROM.update(1,3); for (int i=0 ; i<=8 ; i++ ) { MY_ARRAY[i]=MY_MODE_3[i]; } break; case 3: // move from mode 3 to 4 displaymode = 4; EEPROM.update(1,4); for (int i=0 ; i<=8 ; i++ ) { MY_ARRAY[i]=MY_MODE_4[i]; } break; case 4: // move from mode 4 to 5 displaymode = 5; EEPROM.update(1,5); for (int i=0 ; i<=8 ; i++ ) { MY_ARRAY[i]=MY_MODE_5[i]; } break; case 5: // move from mode 5 to 1 displaymode = 1; EEPROM.update(1,1); for (int i=0 ; i<=8 ; i++ ) { MY_ARRAY[i]=MY_MODE_1[i]; } break; } lastDebounceTime = millis(); } previousState = reading; } |