Components and supplies
Capacitor 470 µF
Resistor 330 ohm
Tactile Switch, Top Actuated
Arduino Nano R3
WS2812B single LEDS
Resistor 10k ohm
Ukulele DIY construction kit
Adafruit Microphone Breakout MAX4466
Rotary Potentiometer, 10 kohm
LED Ring (generic, 16 LEDs)
Tools and machines
Soldering iron (generic)
Drill / Driver, Cordless
Drilling Machine
Saw (tiny, generic)
Wood glue
Sandpaper
Rubber, foam
Craft glue
Solder Wire, Lead Free
Apps and platforms
Arduino IDE
Project description
Code
Arduino code for "UkeOnFire" project
arduino
Sketch used for illuminating a modified ukulele w/ different patterns based on FFT analysis of audio signal. Here code for "smaller" ukulele w/ 20 + 10 LEDs. Can be easily adjusted to more LEDs, see corresponding sections in code.
1/* 2 * 3 * Control of several LED strips mounted to a Ukulele (tuning: G - C - E - A) 4 * - NR1: D3: LED ring @ sound hole of Ukulele (16 LEDs) 5 * - NR2: D5: LED strip @ lower part of fretboad (Frets 6 to 10, lower left LED @ fret 10 (i.e., on A-string) = #1 for adressing. 4 "rows", 5 LEDs per row => 20 LEDs in total) 6 * - lowest row ("A-string") displays intensity of lowest ("bass") frequencies, ..., highest row ("G-string") displays intensity of highest frequencies 7 * - NR3: D6: LED strip @ upper part of fretboad (Frets 1 to 5, lower left LED @ fret 5 (i.e., on G-string) = #1 for adressing. 2 "rows", 5 LEDs per row => 10 LEDs in total) 8 * - lowest row ("E-string") displays intensity of lowest ("bass") frequencies, ..., highest row ("C-string") displays intensity of highest frequencies 9 * 10 * Inputs: 11 * - A0: Audio signal (recorded from a microphone pointing inside the Ukulele) (--> ADMUX = 0x40) 12 * - A1: Brightness of (all) LEDs (selectable via a potentiometer) (--> ADMUX = 0x41) 13 * - D2: Mode selection (determined by counting how often a switch button is pressed) 14 * 15 * Inputs/ideas and (modified) software parts w/ respect to FFT and LED control with Arduino based 16 * - on project by Antoine Rochebois. Thanks ! https://create.arduino.cc/projecthub/AntoineKia/interactive-led-table-for-50-650b83?ref=platform&ref_id=424_trending___&offset=84 17 * - LED fire effect inspired by various examples in the www, e.g., Mark Kriegsman's code under https://pastebin.com/xYEpxqgq 18 * Written by T. Geppert, April/May 2020 19 */ 20 21/* 22 * Constants and alike 23 */ 24 25// LED stuff ============================================================================= 26// LED Ring / Stripe --------------------------------------------------------------------- 27#include <FastLED.h> 28#define NUM_LEDS_NR1 16 // Number of LEDs in ring (aka "NR1") 29#define LED_DATA_PIN_NR1 3 // Data Pin for control of in NR1 30#define NUM_LEDS_NR2 20 // Number of LEDs in strip 1 ("lower" LED strip="closer to body") (aka "NR2") 31#define LED_DATA_PIN_NR2 5 // Data Pin for control of LEDs in NR2 32#define NUM_LEDS_NR3 10 // Number of LEDs in strip 2 ("upper" LED strip="closer to headstock")(aka "NR3") 33#define LED_DATA_PIN_NR3 6 // Data Pin for control of LEDs in NR3 34 35#define NUM_LED_BINS_NR1 1 // number of LED stripes=LED bins in LED strip Nr1 36#define NUM_LED_BINS_NR2 4 // number of LED stripes=LED bins in LED strip Nr2 37#define NUM_LED_BINS_NR3 2 // number of LED stripes=LED bins in LED strip Nr3 38#define NUM_LEDS_PER_LED_BIN_NR1 16 // number of LEDs per FFT bin ("height" of LED_bin) 39#define NUM_LEDS_PER_LED_BIN_NR2 5 // number of LEDs per FFT bin ("height" of LED_bin) 40#define NUM_LEDS_PER_LED_BIN_NR3 5 // number of LEDs per FFT bin ("height" of LED_bin) 41 42CRGB leds_NR1[NUM_LEDS_NR1]; // create array for LED ring (NR1) 43CRGB leds_NR2[NUM_LEDS_NR2]; // create array for strip NR2 44CRGB leds_NR3[NUM_LEDS_NR3]; // create array for strip NR3 45 46#define LED_HUE_STD 13 // STandarD HUE = "color" of LED; 0~red, 32~orange, 64~yellow 47#define LED_SAT_STD 255 // STandarD SATuration = saturation of color of LED; 0~neutral grey, 255~pure color 48#define LED_VAL_STD 75 49 50#define LED_BRIGHT_PIN A1 // controls brightness of LEDs; in code below A0 is addressed via "ADMUX = 0x41" (since operating ADC in special mode) 51int LED_HUE_NR1 = LED_HUE_STD; // HUE used for strip Nr1 52int LED_HUE_NR2 = LED_HUE_STD; // HUE used for strip Nr2 53int LED_HUE_NR3 = LED_HUE_STD; // HUE used for strip Nr3 54int LED_SAT = LED_SAT_STD; // SAT used for FastLED depending on input conditions 55int LED_VAL = LED_VAL_STD; // VAL used for FastLED depending on input conditions 56 57int switchOnDelay = 50; // time (ms) between switchin on subsequent leds 58 59// "LED fire" effect related 60#define COOLING 100 // How much does the air cool as it rises? Less cooling = taller flames. More cooling = shorter flames. Default 55, suggested range 20-100 61#define SPARKING 90 // What chance (out of 255) is there that a new spark will be lit? Higher chance = more roaring fire. Lower chance = more flickery fire. Default 120, suggested range 50-200. 62 63// Audio stuff ============================================================================= 64#define AUDIO_IN_PIN A0 // Audio signal input; in code below A0 is addressed via "ADMUX = 0x40" (since operating ADC in special mode) 65 66// FFT stuff ============================================================================= 67#define LOG_OUT 0 //set output of FFT library to linear not logarithmical 68#define LIN_OUT 1 //set output of FFT library to linear not logarithmical 69#define FFT_N 64 //set to 64 point FFT => 32 frequency bins (assuming input frequencies from ~0...22 000 Hz => ~ 2 x 343 Hz/bin 70 71#include <FFT.h> //include the FFT library; doc found e.g., https://github.com/imagest108/arduino/blob/master/libraries/ArduinoFFT/FFT/fft_read_me.txt 72#include <math.h> //include library for mathematic functions 73 74byte mapFFTBinToLEDBin_NR1[NUM_LED_BINS_NR1+1] = {4, 16}; // mapping of the FFT bins to number of LED stripes; 64 point FFT results in 64/4 bins. here: bundle bins 5-16 (lowest bins lead to flickering of lowest LEDs... so simply remove from being used as basis for evaluation. Reason NOT understood) 75//byte mapFFTBinToLEDBin_NR2[NUM_LED_BINS_NR2+1] = {1, 3, 5, 7, 16}; // mapping of the FFT bins to number of LED stripes; 64 point FFT results in 64/4 bins. here: bundle bins 2-3, 4-5, 6-7, 8-16 (lowest bins lead to flickering of lowest LEDs... so simply remove from being used as basis for evaluation. Reason NOT understood) 76byte mapFFTBinToLEDBin_NR2[NUM_LED_BINS_NR2+1] = {1, 4, 8, 12, 16}; // mapping of the FFT bins to number of LED stripes; 64 point FFT results in 64/4 bins. here: bundle bins 2-3, 4-5, 6-7, 8-16 (lowest bins lead to flickering of lowest LEDs... so simply remove from being used as basis for evaluation. Reason NOT understood) 77 78byte mapFFTBinToLEDBin_NR3[NUM_LED_BINS_NR3+1] = {1, 3, 16}; // mapping of the FFT bins to number of LED stripes; 64 point FFT results in 64/4 bins. here: bundle bins 2-3, 4-16 (lowest bins lead to flickering of lowest LEDs... so simply remove from being used as basis for evaluation. Reason NOT understood) 79byte currentBinHeight_NR1[NUM_LED_BINS_NR1] = {0}; // heigth (=numbers of LEDs ON in LED bin in LED strip 1) 80byte currentBinHeight_NR2[NUM_LED_BINS_NR2] = {0, 0, 0, 0}; // heigth (=numbers of LEDs ON in LED bin in LED strip 2) 81byte currentBinHeight_NR3[NUM_LED_BINS_NR3] = {0, 0}; // heigth (=numbers of LEDs ON in LED bin in LED strip 3) 82float faktoren_NR1[NUM_LED_BINS_NR1] = {1}; //factors to increase the height of each column in strip NR1 83float faktoren_NR2[NUM_LED_BINS_NR2] = {0.7, 0.9, 1.1, 1.3}; //factors to increase the height of each column in strip NR2 84float faktoren_NR3[NUM_LED_BINS_NR3] = {0.8, 1.1}; //factors to increase the height of each column in strip NR3 85 86// Mode selection stuff ============================================================================= 87#define modeSelectorPin 2 // use digital pin 2 for mode selection 88int modeSelectorPinSwitchState = LOW ; // HIGH if external mode selector button is pressed 89int operationMode = 0; // operation mode (e.g., "0" = "all off", "1" = only NR2 controlled by FFT, ...) 90int operationModeMax = 7; // maximum number of operation modes (counting starts w/ "0") 91int operationModeSelectionDelay = 250; // time between subsequent readings of external mode selection button 92 93/* 94 * Subroutines and alike =================================================================================== 95 */ 96 97void blinkTest () { // Light up all LEDs in each ring/strip subsequently (kind of a function check...) 98 //============= 99 for (int i=0; i<NUM_LEDS_NR1; i++) { 100 LED_HUE_NR1 = ( 2 + 10 * i) % 255; 101 // Turn ON leds_NR1 102 leds_NR1[i]=CHSV(LED_HUE_NR1, LED_SAT, LED_VAL); 103 FastLED.show(); 104 delay(switchOnDelay); 105 106 // Turn OFF leds_NR1 107 leds_NR1[i]=CHSV(LED_HUE_NR1, LED_SAT, 0); 108 FastLED.show(); 109 delay(switchOnDelay); 110 } 111 112 for (int i=0; i<NUM_LEDS_NR2; i++) { 113 LED_HUE_NR2 = ( 2 + 10 * i) % 255; 114 // Turn ON leds_NR2 115 leds_NR2[i]=CHSV(LED_HUE_NR2, LED_SAT, LED_VAL); 116 FastLED.show(); 117 delay(switchOnDelay); 118 119 // Turn OFF leds_NR1 120 leds_NR2[i]=CHSV(LED_HUE_NR2, LED_SAT, 0); 121 FastLED.show(); 122 delay(switchOnDelay); 123 } 124 125 for (int i=0; i<NUM_LEDS_NR3; i++) { 126 LED_HUE_NR3 = ( 2 + 10 * i) % 255; 127 // Turn ON leds_NR3 128 leds_NR3[i]=CHSV(LED_HUE_NR3, LED_SAT, LED_VAL); 129 FastLED.show(); 130 delay(switchOnDelay); 131 132 // Turn OFF leds_NR3 133 leds_NR3[i]=CHSV(LED_HUE_NR3, LED_SAT, 0); 134 FastLED.show(); 135 delay(switchOnDelay); 136 } 137} 138 139void allOFF () { // actively turn off all LEDs (set their color to black) 140 for ( int a = 0; a < NUM_LEDS_NR1; a++) { 141 leds_NR1[a] = CRGB::Black; 142 } 143 for ( int a = 0; a < NUM_LEDS_NR2; a++) { 144 leds_NR2[a] = CRGB::Black; 145 } 146 for ( int a = 0; a < NUM_LEDS_NR3; a++) { 147 leds_NR3[a] = CRGB::Black; 148 } 149 FastLED.show(); 150} 151 152void setLEDStrip_NR1 (byte LED_column, byte LED_columnHeight, byte brightness) { 153 byte h = map(LED_columnHeight, 0, 255, 0, NUM_LEDS_PER_LED_BIN_NR1); 154 h = (unsigned char)(h * faktoren_NR1[LED_column]); 155 if (h < currentBinHeight_NR1[LED_column]) { 156 currentBinHeight_NR1[LED_column]--; 157 } 158 else if (h > currentBinHeight_NR1[LED_column]) { 159 currentBinHeight_NR1[LED_column] = h; 160 } 161 if (LED_columnHeight > 150) { 162 LED_HUE_NR1 += 20; //CHANGE THIS VALUE IF YOU WANT THE DIFFERENCE BETWEEN THE COLORS TO BE BIGGER 163 if (LED_HUE_NR1 > 250) LED_HUE_NR1 = 0; 164 } 165 166 for (byte y = 0; y < NUM_LEDS_PER_LED_BIN_NR1; y++) { //set colors of pixels according to column and hue 167 if (currentBinHeight_NR1[LED_column] > y) { 168 if (LED_column % 2 == 0) { 169 leds_NR1[y + (LED_column * NUM_LEDS_PER_LED_BIN_NR1)] = CHSV((LED_HUE_NR1 * NUM_LEDS_PER_LED_BIN_NR1) + (LED_column * NUM_LEDS_PER_LED_BIN_NR1), 255, brightness); 170 } else { 171 leds_NR1[NUM_LEDS_PER_LED_BIN_NR1 - y + (LED_column * NUM_LEDS_PER_LED_BIN_NR1)] = CHSV((LED_HUE_NR1 * NUM_LEDS_PER_LED_BIN_NR1) + (LED_column * NUM_LEDS_PER_LED_BIN_NR1), 255, brightness); 172 } 173 } else { 174 if (LED_column % 2 == 0) { 175 leds_NR1[y + (LED_column * NUM_LEDS_PER_LED_BIN_NR1)] = CRGB::Black; 176 } else { 177 leds_NR1[NUM_LEDS_PER_LED_BIN_NR1 - y + (LED_column * NUM_LEDS_PER_LED_BIN_NR1)] = CRGB::Black; 178 } 179 } 180 } 181} 182 183void setLEDStrip_NR2 (byte LED_column, byte LED_columnHeight, byte brightness) { 184 byte h = map(LED_columnHeight, 0, 255, 0, NUM_LEDS_PER_LED_BIN_NR2); 185 h = (unsigned char)(h * faktoren_NR2[LED_column]); 186 if (h < currentBinHeight_NR2[LED_column]) { 187 currentBinHeight_NR2[LED_column]--; 188 } 189 else if (h > currentBinHeight_NR2[LED_column]) { 190 currentBinHeight_NR2[LED_column] = h; 191 } 192 if (LED_columnHeight > 150) { 193 LED_HUE_NR2 += 20; //CHANGE THIS VALUE IF YOU WANT THE DIFFERENCE BETWEEN THE COLORS TO BE BIGGER 194 if (LED_HUE_NR2 > 250) LED_HUE_NR2 = 0; 195 } 196 197 for (byte y = 0; y < NUM_LEDS_PER_LED_BIN_NR2; y++) { //set colors of pixels according to column and hue 198 if (currentBinHeight_NR2[LED_column] > y) { 199 if (LED_column % 2 == 0) { 200 leds_NR2[y + (LED_column * NUM_LEDS_PER_LED_BIN_NR2)] = CHSV((LED_HUE_NR2 * NUM_LEDS_PER_LED_BIN_NR2) + (LED_column * NUM_LEDS_PER_LED_BIN_NR2), 255, brightness); 201 } else { 202 leds_NR2[NUM_LEDS_PER_LED_BIN_NR2 - y + (LED_column * NUM_LEDS_PER_LED_BIN_NR2)] = CHSV((LED_HUE_NR2 * NUM_LEDS_PER_LED_BIN_NR2) + (LED_column * NUM_LEDS_PER_LED_BIN_NR2), 255, brightness); 203 } 204 } else { 205 if (LED_column % 2 == 0) { 206 leds_NR2[y + (LED_column * NUM_LEDS_PER_LED_BIN_NR2)] = CRGB::Black; 207 } else { 208 leds_NR2[NUM_LEDS_PER_LED_BIN_NR2 - y + (LED_column * NUM_LEDS_PER_LED_BIN_NR2)] = CRGB::Black; 209 } 210 } 211 } 212} 213 214void setLEDStrip_NR3 (byte LED_column, byte LED_columnHeight, byte brightness) { 215 byte h = map(LED_columnHeight, 0, 255, 0, NUM_LEDS_PER_LED_BIN_NR3); 216 h = (unsigned char)(h * faktoren_NR3[LED_column]); 217 if (h < currentBinHeight_NR3[LED_column]) { 218 currentBinHeight_NR3[LED_column]--; 219 } 220 else if (h > currentBinHeight_NR3[LED_column]) { 221 currentBinHeight_NR3[LED_column] = h; 222 } 223 if (LED_columnHeight > 150) { 224 LED_HUE_NR3 += 20; //CHANGE THIS VALUE IF YOU WANT THE DIFFERENCE BETWEEN THE COLORS TO BE BIGGER 225 if (LED_HUE_NR3 > 250) LED_HUE_NR3 = 0; 226 } 227 228 for (byte y = 0; y < NUM_LEDS_PER_LED_BIN_NR3; y++) { //set colors of pixels according to column and hue 229 if (currentBinHeight_NR3[LED_column] > y) { 230 if (LED_column % 2 == 0) { 231 leds_NR3[y + (LED_column * NUM_LEDS_PER_LED_BIN_NR3)] = CHSV((LED_HUE_NR3 * NUM_LEDS_PER_LED_BIN_NR3) + (LED_column * NUM_LEDS_PER_LED_BIN_NR3), 255, brightness); 232 } else { 233 leds_NR3[NUM_LEDS_PER_LED_BIN_NR3 - y + (LED_column * NUM_LEDS_PER_LED_BIN_NR3)] = CHSV((LED_HUE_NR3 * NUM_LEDS_PER_LED_BIN_NR3) + (LED_column * NUM_LEDS_PER_LED_BIN_NR3), 255, brightness); 234 } 235 } else { 236 if (LED_column % 2 == 0) { 237 leds_NR3[y + (LED_column * NUM_LEDS_PER_LED_BIN_NR3)] = CRGB::Black; 238 } else { 239 leds_NR3[NUM_LEDS_PER_LED_BIN_NR3 - y + (LED_column * NUM_LEDS_PER_LED_BIN_NR3)] = CRGB::Black; 240 } 241 } 242 } 243} 244 245void NR1_CtrlViaFFT() { 246 // LED object NR1 (ring) controlled by FFT result 247 // for each of the LED stripes=LED bins, check highest intensity w/i the respective bundle of FFT bins. Based on that result set numbers of LEDs w/i the LED bin to be lit 248 for (byte i =0; i < NUM_LED_BINS_NR1; i++) { 249 byte maxIntensity = 0; 250 for (byte x = mapFFTBinToLEDBin_NR1[i]; x < mapFFTBinToLEDBin_NR1[i+1]; x++) { 251 if ( (unsigned char) fft_lin_out[x] > maxIntensity ) { 252 maxIntensity = (unsigned char) fft_lin_out[x]; 253 } 254 } 255 // set height for each LED strip based on determined maximum intensity w/i each bundle 256 setLEDStrip_NR1 (i, maxIntensity, LED_VAL); 257 } 258} 259 260void NR2_CtrlViaFFT() { 261 // LED object NR2 controlled by FFT result 262 // for each of the LED stripes=LED bins, check highest intensity w/i the respective bundle of FFT bins. Based on that result set numbers of LEDs w/i the LED bin to be lit 263 for (byte i =0; i < NUM_LED_BINS_NR2; i++) { 264 byte maxIntensity = 0; 265 for (byte x = mapFFTBinToLEDBin_NR2[i]; x < mapFFTBinToLEDBin_NR2[i+1]; x++) { 266 if ( (unsigned char) fft_lin_out[x] > maxIntensity ) { 267 maxIntensity = (unsigned char) fft_lin_out[x]; 268 } 269 } 270 // set height for each LED strip based on determined maximum intensity w/i each bundle 271 setLEDStrip_NR2 (i, maxIntensity, LED_VAL); 272 } 273} 274 275void NR3_CtrlViaFFT() { 276 // LED object NR2 controlled by FFT result 277 // for each of the LED stripes=LED bins, check highest intensity w/i the respective bundle of FFT bins. Based on that result set numbers of LEDs w/i the LED bin to be lit 278 for (byte i =0; i < NUM_LED_BINS_NR3; i++) { 279 byte maxIntensity = 0; 280 for (byte x = mapFFTBinToLEDBin_NR3[i]; x < mapFFTBinToLEDBin_NR3[i+1]; x++) { 281 if ( (unsigned char) fft_lin_out[x] > maxIntensity ) { 282 maxIntensity = (unsigned char) fft_lin_out[x]; 283 } 284 } 285 // set height for each LED strip based on determined maximum intensity w/i each bundle 286 setLEDStrip_NR3 (i, maxIntensity, LED_VAL); 287 } 288} 289 290void NR2_LEDFire() { 291 292 static byte heat_NR2 [NUM_LEDS_NR2]; // array for heat values 293 294 // Step 1: Cool down all cells by a somewhat random amount, except the sparking ones (each LED in each LED Bin; no differentiation between different LED bins) 295 for (int a = 0; a < NUM_LED_BINS_NR2; a++) { // each LED Bin 296 for ( int b = 0; b < NUM_LEDS_PER_LED_BIN_NR2; b++) { // each LED 297 heat_NR2[NUM_LEDS_PER_LED_BIN_NR2 * a + b] = qsub8 ( heat_NR2[NUM_LEDS_PER_LED_BIN_NR2 * a + b], random8 (0, (COOLING / NUM_LEDS_PER_LED_BIN_NR2 * 80 ))); // "*4" seems to be a reasonable factor. Play around to get the cooling rate you need to get a nice effect 298 } 299 } 300 301 // Step 2: spread the heat (each LED in each LED Bin); consider only 1 neighbouring LED due to very low number of LEDs (<<10) in each LED bin 302 for (int a = 0; a < NUM_LED_BINS_NR2; a++) { // each LED Bin 303 for ( int b = NUM_LEDS_PER_LED_BIN_NR2-1; b > 0; b--) { // each LED 304 if (a %2 ==0) { 305 heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * a + b ] = ( heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * a + b ] + heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * a + b - 1 ] ) / 1.75; 306 } 307 else { 308 heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * (a+1) - b - 1 ] = ( heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * (a+1) - b - 1 ] + heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * (a+1) - b ] ) / 1.75; 309 } 310 } 311 } 312 313 // Step 3: Randomly ignite new flame sources of heat at the very bottom of each LED bin 314 for (int a = 0; a < NUM_LED_BINS_NR2; a++) { // each LED Bin 315 if( random8() < SPARKING ) { 316 if( a %2 == 0) { // for even LED bins 317 heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * a + 0 ] = qadd8( heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * a + 0 ], random8(50, 75)) ; // Temperature is in arbitrary units from 0 (cold black) to 255 (white hot). 318 } else { // for odd LED bins 319 heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * a + NUM_LEDS_PER_LED_BIN_NR2 - 1 ] = qadd8( heat_NR2[ NUM_LEDS_PER_LED_BIN_NR2 * a + NUM_LEDS_PER_LED_BIN_NR2 - 1 ], random8(50, 75)) ; // Temperature is in arbitrary units from 0 (cold black) to 255 (white hot). 320 } 321 } 322 } 323 324 // Step 4: Map heat array to LED array. Decrease brightness for higher LEDs in each LED bin 325 for (int a = 0; a < NUM_LED_BINS_NR2; a++) { // each LED Bin 326 for( int b = 0; b < NUM_LEDS_PER_LED_BIN_NR2; b++) { 327 leds_NR2[NUM_LEDS_PER_LED_BIN_NR2 * a + b] = HeatColor( heat_NR2[NUM_LEDS_PER_LED_BIN_NR2 * a + b]); 328 leds_NR2[NUM_LEDS_PER_LED_BIN_NR2 * a + b].nscale8_video(LED_VAL); 329 } 330 } 331} 332 333void NR3_LEDFire() { 334 335 static byte heat_NR3 [NUM_LEDS_NR3]; // array for heat values 336 337 // Step 1: Cool down all cells by a somewhat random amount, except the sparking ones (each LED in each LED Bin; no differentiation between different LED bins) 338 for (int a = 0; a < NUM_LED_BINS_NR3; a++) { // each LED Bin 339 for ( int b = 0; b < NUM_LEDS_PER_LED_BIN_NR3; b++) { // each LED 340 heat_NR3[NUM_LEDS_PER_LED_BIN_NR3 * a + b] = qsub8 ( heat_NR3[NUM_LEDS_PER_LED_BIN_NR3 * a + b], random8 (0, (COOLING / NUM_LEDS_PER_LED_BIN_NR3 * 80 ))); // "*4" seems to be a reasonable factor. Play around to get the cooling rate you need to get a nice effect 341 } 342 } 343 344 // Step 2: spread the heat (each LED in each LED Bin); consider only 1 neighbouring LED due to very low number of LEDs (<<10) in each LED bin 345 for (int a = 0; a < NUM_LED_BINS_NR3; a++) { // each LED Bin 346 for ( int b = NUM_LEDS_PER_LED_BIN_NR3-1; b > 0; b--) { // each LED 347 if (a %2 ==0) { 348 heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * a + b ] = ( heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * a + b ] + heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * a + b - 1 ] ) / 1.75; 349 } 350 else { 351 heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * (a+1) - b - 1 ] = ( heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * (a+1) - b - 1 ] + heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * (a+1) - b ] ) / 1.75; 352 } 353 } 354 } 355 356 // Step 3: Randomly ignite new flame sources of heat at the very bottom of each LED bin 357 for (int a = 0; a < NUM_LED_BINS_NR3; a++) { // each LED Bin 358 if( random8() < SPARKING ) { 359 if( a %2 == 0) { // for even LED bins 360 heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * a + 0 ] = qadd8( heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * a + 0 ], random8(50, 75)) ; // Temperature is in arbitrary units from 0 (cold black) to 255 (white hot). 361 } else { // for odd LED bins 362 heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * a + NUM_LEDS_PER_LED_BIN_NR3 - 1 ] = qadd8( heat_NR3[ NUM_LEDS_PER_LED_BIN_NR3 * a + NUM_LEDS_PER_LED_BIN_NR3 - 1 ], random8(50, 75)) ; // Temperature is in arbitrary units from 0 (cold black) to 255 (white hot). 363 } 364 } 365 } 366 367 // Step 4: Map heat array to LED array. Decrease brightness for higher LEDs in each LED bin 368 for (int a = 0; a < NUM_LED_BINS_NR3; a++) { // each LED Bin 369 for( int b = 0; b < NUM_LEDS_PER_LED_BIN_NR3; b++) { 370 leds_NR3[NUM_LEDS_PER_LED_BIN_NR3 * a + b] = HeatColor( heat_NR3[NUM_LEDS_PER_LED_BIN_NR3 * a + b]); 371 leds_NR3[NUM_LEDS_PER_LED_BIN_NR3 * a + b].nscale8_video(LED_VAL); 372 } 373 } 374} 375 376/* 377 * End of Subroutines and alike =================================================================================== 378 */ 379 380/* 381 * Setup =================================================================================== 382 */ 383void setup() { 384 FastLED.addLeds<NEOPIXEL, LED_DATA_PIN_NR1>(leds_NR1, NUM_LEDS_NR1); // setup LED strip NR1 385 FastLED.addLeds<NEOPIXEL, LED_DATA_PIN_NR2>(leds_NR2, NUM_LEDS_NR2); // setup LED strip NR2 386 FastLED.addLeds<NEOPIXEL, LED_DATA_PIN_NR3>(leds_NR3, NUM_LEDS_NR3); // setup LED strip NR3 387 388 pinMode(LED_DATA_PIN_NR1, OUTPUT); 389 pinMode(LED_DATA_PIN_NR2, OUTPUT); 390 pinMode(LED_DATA_PIN_NR3, OUTPUT); 391 392 pinMode(LED_BRIGHT_PIN, INPUT); 393 pinMode(AUDIO_IN_PIN, INPUT); 394 395 pinMode(modeSelectorPin, INPUT); 396 397 // setup Arduino Nano registers 398 ADCSRA = 0xe5; //set the ADC to free running mode 399 ADMUX = 0x40; //use pin A0 400 DIDR0 = 0x03; //turn off the digital input for Pins A0 (audio signal input) and A1 (LED brightness) 401 analogReference(DEFAULT); //set aref to DEFAULT (was EXTERNAL in example, however, due to lack of schematics, I guess analogReference was connected to +5V, however not sure. In order to avoid potential damage to the ATmega - since I am not quite sure whats's going on inside and since I'm a novice to this Arduino topics, I chose to go for DEFAULT - although wasting some bits 402 403 //check if all LEDs are controllable (only in case switch button is pressed during startup) 404 modeSelectorPinSwitchState = digitalRead(modeSelectorPin); 405 if ( modeSelectorPinSwitchState == HIGH) { 406 blinkTest(); 407 } 408 409 LED_HUE_NR1 = 0; // reset LED HUE value 410 LED_HUE_NR2 = 0; // reset LED HUE value 411 LED_HUE_NR3 = 0; // reset LED HUE value 412 413 allOFF(); // actively turn off all LEDs (set their color to black) 414 415 delay(500); 416 417} 418 419/* 420 * End of Setup =================================================================================== 421 */ 422 423 424 425/* 426 * Main Loop =================================================================================== 427 */ 428 429void loop() { 430 // Data acquisition and FFT ---------------------------------------------------------------------------------------------- 431 // ----------------------------------------------------------------------------------------------------------------------- 432 // Collect FFT data using input signal @ Pin A0 433 for (int i = 0 ; i < 2 * FFT_N ; i += 2) { //save FFT_N samples 434 while (!(ADCSRA & 0x10)); //wait for adc to be ready (i.e., current sampling finished) 435 ADMUX = 0x40; //use pin A0 436 ADCSRA = 0xf5; //restart adc 437 byte m = ADCL; //fetch adc data 438 byte j = ADCH; 439 int k = (j << 8) | m; //form into an int 440 k -= 0x0200; //form into a signed int 441 k <<= 6; //form into a 16b signed int 442 fft_input[i] = k; //put real data into even bins 443 fft_input[i+1] = 0; //set odd bins to 0 444 } 445 446 // Do FFT processing 447 fft_window(); // window the data for better frequency response 448 fft_reorder(); // reorder the data before doing the fft 449 fft_run(); // process the data in the fft 450 fft_mag_lin(); // take the output of the fft 451 452 fft_lin_out[0] = 0; 453 fft_lin_out[1] = 0; 454 455 // set LED brightness ---------------------------------------------------------------------------------------------- 456 // ----------------------------------------------------------------------------------------------------------------- 457 // since ADC is in free running mode, switch input pin via ADMUX. Also add slight delay (otherwise - for whatever reason - data will not be passed to variable) 458 while (!(ADCSRA & 0x10)); //wait for adc to be ready (i.e., current sampling finished) 459 ADMUX = 0x41; //use pin A1 460 delay(1); 461 byte m = ADCL; //fetch adc data 462 byte j = ADCH; 463 int k = (j << 8) | m; //form into an int 464 LED_VAL = map (k, 0, 1023, 255, 0); // map potentiometer to allowed brightness for FastLED 465 sei(); // turn on interrupts 466 467 // select behaviour based on operating mode ------------------------------------------------------------------------ 468 // ----------------------------------------------------------------------------------------------------------------- 469 modeSelectorPinSwitchState = digitalRead(modeSelectorPin); // HIGH = button for selection of operating mode has been pressed 470 471 if ( modeSelectorPinSwitchState == HIGH ) { 472 operationMode = operationMode+1; // switch to next operation mode 473 if (operationMode > operationModeMax) { 474 operationMode = 0; 475 } 476 delay (operationModeSelectionDelay); // prevent increasing operationMode in case of external mode selection button is pressed too long 477 478 // Turn OFF all LEDs (to ensure only LEDs according to selected operation mode are on 479 // actively turn off all LEDs (set their color to black) 480 allOFF(); 481 } 482 483 switch (operationMode) { 484 /* 485 * # button pressed | | | | | | | 486 * (= case below) | FFT NR1 | FFT NR2 | FFT NR3 | FIRE NR1 | FIRE NR2 | FIRE NR3 | 487 * -------------------------------------------------------------------------------- 488 * 0 | - | - | - | - | - | - 489 * 1 | - | X | - | - | - | - 490 * 2 | - | X | X | - | - | - 491 * 3 | X | X | X | - | - | - 492 * 4 | X | - | - | - | - | - 493 * 5 | - | - | - | - | X | - 494 * 6 | - | - | - | - | - | X 495 * 7 | - | - | - | - | X | X 496 */ 497 case 0: 498 break; 499 case 1: 500 NR2_CtrlViaFFT(); 501 break; 502 case 2: 503 NR2_CtrlViaFFT(); 504 NR3_CtrlViaFFT(); 505 break; 506 case 3: 507 NR1_CtrlViaFFT(); 508 NR2_CtrlViaFFT(); 509 NR3_CtrlViaFFT(); 510 break; 511 case 4: 512 NR1_CtrlViaFFT(); 513 break; 514 case 5: 515 NR2_LEDFire(); 516 delay(50); 517 break; 518 case 6: 519 NR3_LEDFire(); 520 delay(50); 521 break; 522 case 7: 523 NR2_LEDFire(); 524 delay(20); 525 NR3_LEDFire(); 526 delay(30); 527 break; 528 } 529 530 FastLED.show(); 531 532delay(10); 533 534} 535/* 536 * End of Main Loop =================================================================================== 537 */ 538
Downloadable files
Schematics for UkeOnFire
Schematics for UkeOnFire
Schematics for UkeOnFire
Schematics for UkeOnFire
Comments
Only logged in users can leave comments
Torschtele
0 Followers
•0 Projects
Table of contents
Intro
3
0