Components and supplies
USB-A to Mini-USB Cable
Arduino Nano R3
Resistor 4.75k ohm
Resistor 100k ohm
Male-Header 36 Position 1 Row- Long (0.1")
Tactile Switch, Top Actuated
Jumper wires (generic)
Breadboard (generic)
Resistor 10k ohm
Tools and machines
Soldering iron (generic)
Apps and platforms
Arduino IDE
Project description
Code
32_Band_LED_Spectrum_Analyzer-009.ino
arduino
Feel free to modify / customize to suit your need, on my customization part code (re-mapping data, marked with comment).
1// Modified code by Christian Suryanto, from (c) 2019 Shajeeb TM 2// HAZI TECH 3// Updated by Christian Suryanto 4// 5 6#include <arduinoFFT.h> 7#include <MD_MAX72xx.h> 8#include <SPI.h> 9#include <EEPROM.h> 10 11#define HARDWARE_TYPE MD_MAX72XX::FC16_HW // Set display type so that MD_MAX72xx library treets it properly 12#define CLK_PIN 13 // Clock pin to communicate with display 13#define DATA_PIN 11 // Data pin to communicate with display 14#define CS_PIN 10 // Control pin to communicate with display 15 16#define SAMPLES 64 // Must be a power of 2 17#define MAX_DEVICES 4 // Total number display modules 18#define xres 32 // Total number of columns in the display, must be <= SAMPLES/2 19#define yres 8 // Total number of rows in the display 20 21#define PREV 0xFF02FD // address is FFA25D but 0x is added because this is how the arduino is told that it is HEXADECIMAL. 22#define NEXT 0xFFC23D // control stop code 23#define PWR 0xFFA25D // control Power 24 25int audio_response = 35; // put a value between 10 and 80. Smaller the number, higher the audio response 26 27double vReal[SAMPLES]; 28//double vReal2[SAMPLES]; 29double vImag[SAMPLES]; 30char data_avgs[xres]; 31 32int yvalue; 33int displaycolumn , displayvalue; 34int peaks[xres]; 35const int buttonPin = 6; // the number of the pushbutton pin 36int state = HIGH; // the current reading from the input pin 37int previousState = LOW; // the previous reading from the input pin 38int displaymode; 39unsigned long lastDebounceTime = 0; // the last time the output pin was toggled 40unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers 41 42int MY_ARRAY[]={0, 128, 192, 224, 240, 248, 252, 254, 255}; // default = standard pattern 43//int MY_MODE_1[]={0, 128, 192, 224, 240, 248, 252, 254, 255}; // standard pattern 44//int MY_MODE_2[]={0, 128, 64, 32, 16, 8, 4, 2, 1}; // only peak pattern 45//int MY_MODE_3[]={0, 128, 192, 160, 144, 136, 132, 130, 129}; // only peak + bottom point 46//int MY_MODE_4[]={0, 128, 192, 160, 208, 232, 244, 250, 253}; // one gap in the top , 3rd light onwards 47 48bool EQ_ON = true; // set to false to disable eq 49 50byte eq1[32] = {40, 45, 50, 60, 65, 70, 75, 95, 51 110, 110, 110, 110, 110, 110, 110, 110, 52 130, 130, 130, 130, 130, 130, 130, 130, 53 145, 155, 170, 180, 215, 220, 245, 255 54 }; 55 56 57byte eq2[11] = {40, 70, 75, 110, 110, 140, 145, 220, 220, 230, 250}; 58 59 60MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, CS_PIN, MAX_DEVICES); // display object 61arduinoFFT FFT = arduinoFFT(); // FFT object 62 63 64void setup() { 65 EEPROM.update(1,1); //(memory address, value), RUN THIS FOR THE FIRST TIME 66 displaymode = EEPROM.read(1); 67 //displaymode = 1; 68 ADCSRA = 0b11100101; // set ADC to free running mode and set pre-scalar to 32 (0xe5) 69 ADMUX = 0b00000000; // use pin A0 and external voltage reference 70 pinMode(buttonPin, INPUT); 71 mx.begin(); // initialize display 72 mx.control(MD_MAX72XX::INTENSITY, 0); // set LED intensity 73 delay(50); // wait to get reference voltage stabilized 74} 75 76void loop() { 77 // ++ Sampling 78 79 int numData; 80 double rSum; 81 82 for(int i=0; i<SAMPLES; i++) 83 { 84 while(!(ADCSRA & 0x10)); // wait for ADC to complete current conversion ie ADIF bit set 85 ADCSRA = 0b11110101 ; // clear ADIF bit so that ADC can do next operation (0xf5) 86 int value = ADC - 512 ; // Read from ADC and subtract DC offset caused value 87 value = value / 8; 88 vReal[i]= value; // Copy to bins after compressing 89 vImag[i] = 0; 90 } 91 // -- Sampling 92 93 94 //++ FFT 95 FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD); 96 FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD); 97 FFT.ComplexToMagnitude(vReal, vImag, SAMPLES); 98 // -- FFT 99 100 int step = (SAMPLES)/xres; 101 102// re-mapping data - Customize by Christian Suryanto /// 103 switch (displaymode) 104 { 105 case 1 : 106 { 107 numData = 32; 108 data_avgs[0] = (vReal[0] + vReal[0])/2; 109 data_avgs[1] = (vReal[1] + vReal[63])/2; 110 data_avgs[2] = (vReal[2] + vReal[62])/2; 111 data_avgs[3] = (vReal[3] + vReal[61])/2; 112 data_avgs[4] = (vReal[4] + vReal[60])/2; 113 data_avgs[5] = (vReal[5] + vReal[59])/2; 114 data_avgs[6] = (vReal[6] + vReal[58])/2; 115 data_avgs[7] = (vReal[7] + vReal[57])/2; 116 data_avgs[8] = (vReal[8] + vReal[56])/2; 117 data_avgs[9] = (vReal[9] + vReal[55])/2; 118 data_avgs[10] = (vReal[10] + vReal[54])/2; 119 data_avgs[11] = (vReal[11] + vReal[53])/2; 120 data_avgs[12] = (vReal[12] + vReal[52])/2; 121 data_avgs[13] = (vReal[13] + vReal[51])/2; 122 data_avgs[14] = (vReal[14] + vReal[50])/2; 123 data_avgs[15] = (vReal[15] + vReal[49])/2; 124 data_avgs[16] = (vReal[16] + vReal[48])/2; 125 data_avgs[17] = (vReal[17] + vReal[47])/2; 126 data_avgs[18] = (vReal[18] + vReal[46])/2; 127 data_avgs[19] = (vReal[19] + vReal[45])/2; 128 data_avgs[20] = (vReal[20] + vReal[44])/2; 129 data_avgs[21] = (vReal[21] + vReal[43])/2; 130 data_avgs[22] = (vReal[22] + vReal[42])/2; 131 data_avgs[23] = (vReal[23] + vReal[41])/2; 132 data_avgs[24] = (vReal[24] + vReal[40])/2; 133 data_avgs[25] = (vReal[25] + vReal[39])/2; 134 data_avgs[26] = (vReal[26] + vReal[38])/2; 135 data_avgs[27] = (vReal[27] + vReal[37])/2; 136 data_avgs[28] = (vReal[28] + vReal[36])/2; 137 data_avgs[29] = (vReal[29] + vReal[35])/2; 138 data_avgs[30] = (vReal[30] + vReal[34])/2; 139 data_avgs[31] = (vReal[31] + vReal[33])/2; 140 } 141 break; 142 143 case 2 : 144 { 145 numData = 11; 146 data_avgs[0] = (vReal[0] + vReal[0])/2; 147 data_avgs[1] = (vReal[0] + vReal[0] + vReal[1] + vReal[63]) / 4; 148 data_avgs[2] = ( vReal[1] + vReal[63] + vReal[2] + vReal[62] + vReal[3] + vReal[61])/6; 149 data_avgs[3] = (vReal[2] + vReal[62] + vReal[3] + vReal[61] + vReal[4] + vReal[60])/6; 150 data_avgs[4] = (vReal[5] + vReal[59] + vReal[6] + vReal[58] + vReal[7] + vReal[57])/6; 151 data_avgs[5] = (vReal[8] + vReal[56] + vReal[9] + vReal[55] + vReal[10] + vReal[54] + vReal[11] + vReal[53])/8; 152 data_avgs[6] = (vReal[12] + vReal[52] + vReal[13] + vReal[51] + vReal[14] + vReal[50] + vReal[15] + vReal[49])/8; 153 data_avgs[7] = (vReal[16] + vReal[48] + vReal[17] + vReal[47] + vReal[18] + vReal[46])/6; 154 data_avgs[8] = (vReal[19] + vReal[45] + vReal[20] + vReal[44] + vReal[21] + vReal[43] + vReal[22] + vReal[42])/8; 155 data_avgs[9] = (vReal[23] + vReal[41] + vReal[24] + vReal[40] + vReal[25] + vReal[39] + vReal[26] + vReal[38] + vReal[27] + vReal[37])/10; 156 data_avgs[10] = (vReal[28] + vReal[36] + vReal[29] + vReal[35] + vReal[30] + vReal[34] + vReal[31] + vReal[33])/8; 157 } 158 break; 159 } 160// re-mapping data - Customize by Christian Suryanto /// 161 162 for(int i=0; i<numData; i++) 163 { 164 data_avgs[i] = data_avgs[i] / 2; 165 if (EQ_ON) 166 switch (displaymode) 167 { 168 case 1 : data_avgs[i] = (data_avgs[i]) * (float)(eq1[i]) / 100; //apply eq filter 169 break; 170 171 case 2 : data_avgs[i] = (data_avgs[i]) * (float)(eq2[i]) / 100; //apply eq filter 172 break; 173 } 174 175 data_avgs[i] = constrain(data_avgs[i],0,audio_response); // set max & min values for buckets 176 data_avgs[i] = map(data_avgs[i], 0, audio_response, 0, yres); // remap averaged values to yres 177 178 yvalue=data_avgs[i]; 179 180 peaks[i] = peaks[i]-1; // decay by one light 181 if (yvalue > peaks[i]) 182 peaks[i] = yvalue ; 183 yvalue = peaks[i]; 184 displayvalue=MY_ARRAY[yvalue]; 185 186 switch (displaymode) 187 { 188 case 1: 189 { 190 displaycolumn=31-i; 191 mx.setColumn(displaycolumn, displayvalue); // for left to right 192 } 193 break; 194 case 2: 195 { 196 displaycolumn=31-(3*i); 197 mx.setColumn(displaycolumn-1, displayvalue); // for left to right 198 mx.setColumn(displaycolumn, displayvalue); // for left to right 199 } 200 break; 201 } 202 } 203 // -- send to display according measured value 204 205 displayModeChange (); // check if button pressed to change display mode 206} 207 208void displayModeChange() { 209 int reading = digitalRead(buttonPin); 210 if (reading == HIGH && previousState == LOW && millis() - lastDebounceTime > debounceDelay) // works only when pressed 211 { 212 switch (displaymode) 213 { 214 case 1: // move from mode 1 to 2 215 displaymode = 2; 216 mx.clear(); 217 delay(200); 218 EEPROM.update(1,2); 219 break; 220 case 2: // move from mode 2 to 3 221 displaymode = 1; 222 mx.clear(); 223 delay(200); 224 EEPROM.update(1,1); 225 break; 226 } 227 lastDebounceTime = millis(); 228 } 229 previousState = reading; 230}
Downloadable files
spa-001_bb_sAnrP2iJqa.png
spa-001_bb_sAnrP2iJqa.png
spa-001_bb_sAnrP2iJqa.png
spa-001_bb_sAnrP2iJqa.png
Comments
Only logged in users can leave comments
chrissurya
0 Followers
•0 Projects
Table of contents
Intro
1
0