Components and supplies
Through Hole Resistor, 300 ohm
5 mm LED: Green
Arduino Pro Mini 328 - 3.3V/8MHz
Perma-Proto Breadboard Half Size
LED, Blue
5 mm LED: Red
Wire, Hook Up
Apps and platforms
Scilab
Project description
Code
Simple nice 3 color, 4 level LIGHT ORGAN with Arduino Pro Mini
c_cpp
1// **************************************************************************** 2// * * 3// * Simple nice 3 color, 4 level LIGHT ORGAN with Arduino Pro Mini * 4// * ver 1.0 * 5// * * 6// **************************************************************************** 7// 8// 9// Vcc = 3.3V 10// ^ 11// | 12// ___|___|___|___|___|___|___ 13// | GND GND VCC RXI TXD DTR | GND 14// |TXD RAW| 15// | | 16// |RXI GND|| 17// | | 18// |RST RST| 19// | | 20// |GND VCC| 21// R1=300R___ red LED1 | | < GND from integrated amplifier's phones output 22// ||___|<||2 A3| 23// R2=300R___ red LED2 | | < signal from integrated amplifier's phones output 24// ||___|<||3 Arduino Pro Mini A2| (since no AGC the volume needs to be adjusted to get appropriate signal level so that the LEDs turn on) 25// R3=300R___ red LED3 | | 26// ||___|<||4 w/ ATMega328 A1|> used only for development (signal to oscilloscope to measure sampling freq.) 27// R4=300R___ red LED4 | | 28// ||___|<||5 8MHz/ 3.3V A0| 29// R5=300R___green LED5 | | blue LED9 ___ R9= 300R 30// ||___|<||6 13||>|___|| 31// R6=300R___green LED6 | | blue LED10 ___ R10=300R 32// ||___|<||7 12||>|___|| 33// R7=300R___green LED7 | | blue LED11 ___ R11=300R 34// ||___|<||8 11||>|___|| 35// R8=300R___green LED8 | | blue LED12 ___ R12=300R 36// ||___|<||9 10||>|___|| 37// |___________________________| 38// 39// 40 41 42#ifndef cbi 43#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) 44#endif 45#ifndef sbi 46#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) 47#endif 48#define bit_is_set(sfr, bit) (_SFR_BYTE(sfr) & _BV(bit)) 49 50//Constants and Global Variables 51 52const int stL1 = 20; // threshold for step1 lowpass out 53const int stL2 = 25; // threshold for step2 lowpass out 54const int stL3 = 30; // threshold for step3 lowpass out 55const int stL4 = 40; // threshold for step4 lowpass out 56const int stM1 = 16; // threshold for step1 bandpass out 57const int stM2 = 25; // threshold for step2 bandpass out 58const int stM3 = 32; // threshold for step3 bandpass out 59const int stM4 = 48; // threshold for step4 bandpass out 60const int st1 = 40; // threshold for step1 highpass out 61const int st2 = 55; // threshold for step2 highpass out 62const int st3 = 70; // threshold for step3 highpass out 63const int st4 = 80; // threshold for step4 highpass out 64 65int samplVal = 0; //initialization of sensor variable, equivalent to EMA Y 66int EMA_SVL = 0; //initialization of EMA_S very low pass 67int EMA_SL = 0; //initialization of EMA_S low pass 68int EMA_SM = 0; //initialization of EMA_S middle pass 69int EMA_SH = 0; //initialization of EMA_S high pass 70int lowpass = 0; 71int bandpass = 0; 72int highpass = 0; 73 74void setup() { 75 76// Turn off PWM timers 77 cbi(TCCR1A, COM1A1); 78 cbi(TCCR1A, COM1B1); 79 cbi(TCCR0A, COM0A1); 80 cbi(TCCR0A, COM0B1); 81 cbi(TCCR2A, COM2A1); 82 cbi(TCCR2A, COM2B1); 83 84// Set the output pins 85pinMode(13, OUTPUT); // Channel_1 low pass level 1 86pinMode(12, OUTPUT); // Channel_1 low pass level 2 87pinMode(11, OUTPUT); // Channel_1 low pass level 3 88pinMode(10, OUTPUT); // Channel_1 low pass level 4 89pinMode(A1, OUTPUT); // cycle output signal to measure sampling rate neccessary for calculating EMA alphas 90pinMode(2, OUTPUT); // Channel_2 high pass level 1 91pinMode(3, OUTPUT); // Channel_2 high pass level 2 92pinMode(4, OUTPUT); // Channel_2 high pass level 3 93pinMode(5, OUTPUT); // Channel_2 high pass level 4 94pinMode(6, OUTPUT); // Channel_3 band pass level 1 95pinMode(7, OUTPUT); // Channel_3 band pass level 2 96pinMode(8, OUTPUT); // Channel_3 band pass level 3 97pinMode(9, OUTPUT); // Channel_3 band pass level 4 98 99// ADC initialization: https://arduino.stackexchange.com/questions/699/how-do-i-know-the-sampling-frequency 100// https://www.instructables.com/id/Girino-Fast-Arduino-Oscilloscope/ 101// Set the sample timer's prescaler to 2, enabling max sample freq = 8000KHz/13/2 (13 is the nr of ADC succ.appr. cycles) 102// actual sample frequency depends on the code (time of operations between sampling - no interrupts applied) in this case it is 20kHz 103// audiophiles should not worry about missing high frequency part, because above 7kHZ there is negligible power - no influence on the lights 104// ADCSRA |= B00000111; 105cbi(ADCSRA, ADPS2); 106cbi(ADCSRA, ADPS1); 107sbi(ADCSRA, ADPS0); 108 109EMA_SL = 0; //set EMA_S. for t=1 110EMA_SVL = 0; 111EMA_SH = 0; 112} 113 114void loop() { 115 samplVal = analogRead_za(); // read the analog input pin A0 116 117// Simple digital filters applied with exponential moving average (EMA) algorythm: 118// https://dsp.stackexchange.com/questions/40462/exponential-moving-average-cut-off-frequency 119// f3db filter frequencies (and the connected EMA alpha coefficients) are selected so that EMA algorythm can be calculated with 120// simple fixed operations (add, sub, bit shift: division by 2,4,8,16,32) to keep speed, float operations avoided 121 122EMA_SVL = (samplVal / 32) + EMA_SVL - (EMA_SVL / 32); // EMA alpha very low = 1/32 -> f3db = 102 Hz @ Fs=20kHz 123EMA_SL = (samplVal / 16) + EMA_SL - (EMA_SL / 16); // EMA alpha low = 1/16 -> f3db = 315 Hz @ Fs=20kHz 124EMA_SM = (samplVal / 8) + (samplVal / 32) + EMA_SM - (EMA_SM / 8)- (EMA_SM / 32); // EMA alpha middle = 5/32 -> f3db = 540 Hz @ Fs=20kHz 125EMA_SH = (samplVal / 2) + (samplVal / 8)+ EMA_SH - (EMA_SH / 2) - (EMA_SH / 8); // EMA alpha high = 5/8 -> f3db = 3400 Hz @ Fs=20kHz 126lowpass = EMA_SL - EMA_SVL; 127bandpass = EMA_SM - EMA_SL; 128highpass = EMA_SH - EMA_SM; 129// PORTB &= B11000000; // turn off all LEDs 130// PORTD &= B00000011; 131digitalWriteB_za (abs(lowpass)); // turn on Channel_1 LEDs according to lowpass value calculated with the latest sample value 132digitalWriteBD_za (abs(bandpass)); // turn on Channel_3 LEDs according to bandbass value calculated with the latest sample value 133digitalWriteD_za (abs(highpass)); // turn on Channel_2 LEDs according to highpass value calculated with the latest sample value 134 135} 136 137// analogRead function 138// the code in he following link has been modified according to this application's requiremets 139// https://garretlab.web.fc2.com/en/arduino/inside/hardware/arduino/avr/cores/arduino/wiring_analog.c/analogRead.html 140 141int analogRead_za() 142{ 143 uint8_t sample_val; // sampled analog value 144 uint8_t tempPC; // temporary value of PORT C 145 146 // set the analog reference (high two bits of ADMUX: REFS1 = 0, REFS0 = 1 -> ADC Vref = 3.3V) 147 // select channel (low 4 bits of ADMUX: 00), sets A0 as analog input pin 148 // set ADLAR (right-adjust result) to 1 149 ADMUX = 0x60; 150 151 // set ready for the AD conversion 152 sbi(ADCSRA, ADSC); 153 154 // ADSC is cleared when the AD conversion finishes 155 while (bit_is_set(ADCSRA, ADSC)); 156 157 // we have to read only ADCH , due to limited accuracy the 2 bits in ADCL are not needed 158 sample_val = ADCH; 159 160 tempPC = PORTC ^ B00000010; // Invert cycle output signal 161 PORTC = tempPC; // Set A1 output which enables to measure sampling rate neccessary for calculating EMA alphas 162 return sample_val; 163} 164 165 166// 3 digital write functions per 3 color channels 167// https://www.arduino.cc/en/Reference/PortManipulation 168 169void digitalWriteB_za (int val) 170{ 171 uint8_t oldSREG = SREG; 172 uint8_t tempPB; // temporary value of PORTB 173 cli(); 174 175 if (val < stL1) { 176 PORTB &= B11000011; // all Channel_1 LEDs off 177 } else { 178 tempPB = PORTB & B11000011; 179 if (val < stL2) { 180 PORTB = tempPB | B00100000; // set pin13 = PB5 to HIGH 181 } else { 182 if (val < stL3) { 183 PORTB = tempPB | B00110000; // set pin13 = PB5, pin12 = PB4 to HIGH 184 } else { 185 if (val < stL4) { 186 PORTB = tempPB | B00111000; // set pin13 = PB5, pin12 = BB4, pin11 = PB3 to HIGH 187 } else { 188 PORTB = tempPB | B00111100; // all Channel_1 LEDs on 189 } 190 } 191 } 192 } 193} 194 195void digitalWriteD_za (int val) 196{ 197 uint8_t oldSREG = SREG; 198 uint8_t tempPD; // temporary value of PORTD 199 cli(); 200 201 if (val < st1) { 202 PORTD &= B11000011; // all Channel_2 LEDs off 203 } else { 204 tempPD = PORTD & B11000011; 205 if (val < st2) { 206 PORTD = tempPD | B00000100; // set pin2 = PD2 to HIGH 207 } else { 208 if (val < st3) { 209 PORTD = tempPD | B00001100; // set pin2 = PD2, pin3 = PD3 to HIGH 210 } else { 211 if (val < st4) { 212 PORTD = tempPD | B00011100; // set pin2 = PD2, pin3 = PD3, pin4 = PD4 to HIGH 213 } else { 214 PORTD = tempPD | B00111100; // all Channel_2 LEDs on 215 } 216 } 217 } 218 } 219 SREG = oldSREG; 220} 221 222void digitalWriteBD_za (int val) 223{ 224 uint8_t oldSREG = SREG; 225 uint8_t tempPD; // temporary value of PORTD 226 uint8_t tempPB; // temporary value of PORTB 227 cli(); 228 229 if (val < stM1) { 230 PORTD &= B00111111; // all Channel_3 LEDS off 231 PORTB &= B11111100; 232 } else { 233 tempPD = PORTD & B00111111; 234 tempPB = PORTB & B11111100; 235 if (val < stM2) { 236 PORTD = tempPD | B01000000; // set pin6 = PD6 to HIGH 237 PORTB = tempPB; 238 } else { 239 if (val < stM3) { 240 PORTD = tempPD | B11000000; 241 PORTB = tempPB; 242 } else { 243 if (val < stM4) { 244 PORTD = tempPD | B11000000; 245 PORTB = tempPB | B00000001; 246 } else { 247 PORTD = tempPD | B11000000; 248 PORTB = tempPB | B00000011; // all Channel_3 LEDs on 249 } 250 } 251 } 252 } 253 SREG = oldSREG; 254} 255
Downloadable files
light organ
the source code file contains the simple text drawing schematics of the circuit
light organ
light organ
the source code file contains the simple text drawing schematics of the circuit
light organ
Comments
Only logged in users can leave comments
aranyzs
0 Followers
•0 Projects
Table of contents
Intro
0
0