Projekt Bouřkového mraku
Obsah
Bouřkový mrak
Vizualizace různých úrovní hlasitosti hudby pomocí LED diod – VRNI, LS 2015/2016
Členové týmu
Jana Ada Kubíčková, Anna Řezníčková, David Vávra
Inspirace projektu
Inspirací projektu byl produkt Richarda Clarksona "Cloud" http://www.richardclarkson.com/shop/cloud, zejména pak jeho cena, která nás přiměla přemýšlet o tom, jak stejný produkt získat s minimální počáteční investicí. Nebyli jsme první, kdo měl podobný záměr, tudíž se nám na stránce makeuseofit.com podařilo dokonce najít i podrobný návod DIY.
Použitý materiál
1x Breadbord 1x UNO R3 SMD + propojovací USB A-B kabel (Ekvivalent Arduino UNO) 1x Mikrofon 9x 5V LED Cca 25x propojovací kabel 1x polystyrenová deska (tloušťka 2 cm) tavná pistole 1x Polyesterová výplň do polštářů 1x drátěné ramínko 1x Powerbanka Použitý software Arduino IDE 1.6.9 ovladače pro Mac OS
Zapojení
Vlastní zdrojový kód
/* Lighting Cloud Mood Lamp By James Bruce View the full tutorial and build guide at http://www.makeuseof.com/ Sound sampling code originally by Adafruit Industries. Distributed under the BSD license. This paragraph must be included in any redistribution. */ #include "FastLED.h" #define NUM_LEDS 9 #define LED_MODE WS2812B #define LED_ORDER GRB // Mode enumeration - if you want to add additional party or colour modes, add them here; you'll need to map some IR codes to them later; // and add the modes into the main switch loop enum Mode { CLOUD, ACID, OFF, ON, RED, GREEN, BLUE, FADE}; Mode mode = CLOUD; Mode lastMode = CLOUD; // Mic settings, shouldn't need to adjust these. #define MIC_PIN 0 // Microphone is attached to this analog pin #define DC_OFFSET 0 // DC offset in mic signal - if unusure, leave 0 #define NOISE 10 // Noise/hum/interference in mic signal #define SAMPLES 10 // Length of buffer for dynamic level adjustment byte volCount = 0; // Frame counter for storing past volume data int vol[SAMPLES]; // Collection of prior volume samples int n, total = 30; float average = 0; // used to make basic mood lamp colour fading feature int fade_h; int fade_direction = 1; // Define the array of leds CRGB leds[NUM_LEDS]; // Makes all the LEDs a single colour, see https://raw.githubusercontent.com/FastLED/FastLED/gh-pages/images/HSV-rainbow-with-desc.jpg for H values void single_colour(int H, int d = 500) { for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV( H, 255, 255); } FastLED.show(); //avoid flickr which occurs when FastLED.show() is called - only call if the colour changes if (lastMode != mode) { FastLED.show(); lastMode = mode; } delay(d); } void colour_fade() { //mood mood lamp that cycles through colours for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV( fade_h, 255, 255); } if (fade_h > 254) { fade_direction = -1; //reverse once we get to 254 } else if (fade_h < 0) { fade_direction = 1; } fade_h += fade_direction; FastLED.show(); delay(100); } // utility function to turn all the lights off. void reset() { for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV( 0, 0, 0); } FastLED.show(); } void detect_thunder() { n = analogRead(MIC_PIN); // Raw reading from mic n = abs(n - 512 - DC_OFFSET); // Center on zero n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum vol[volCount] = n; // Save sample for dynamic leveling if(++volCount >= SAMPLES) volCount = 0; // Advance/rollover sample counter total = 0; for(int i=0; i<SAMPLES; i++) { total += vol[i]; } // If you're having trouble getting the cloud to trigger, uncomment this block to output a ton of debug on current averages. // Note that this WILL slow down the program and make it less sensitive due to lower sample rate. for(int t=0; t<SAMPLES; t++) { //initial data is zero. to avoid initial burst, we ignore zero and just add the current l Serial.print("Sample item "); Serial.print(t); Serial.print(":"); Serial.println(vol[t]); } Serial.print("total"); Serial.println(total); Serial.print("divided by sample size of "); Serial.println(SAMPLES); Serial.print("average:"); Serial.println(average); Serial.print("current:"); Serial.println(n); average = (total/SAMPLES)+2; if(n>average){ Serial.println("TRIGGERED"); reset(); //I've programmed 3 types of lightning. Each cycle, we pick a random one. switch(random(1,3)){ //switch(3){ case 1: thunderburst(); delay(random(10,500)); Serial.println("Thunderburst"); break; case 2: rolling(); Serial.println("Rolling"); break; case 3: crack(); delay(random(50,250)); Serial.println("Crack"); break; } } } void acid_cloud() { // a modification of the rolling lightning which adds random colour. trippy. //iterate through every LED for (int i = 0; i < NUM_LEDS; i++) { if (random(0, 100) > 90) { leds[i] = CHSV( random(0, 255), 255, 255); } else { leds[i] = CHSV(0, 0, 0); } } FastLED.show(); delay(random(5, 100)); reset(); //} } void rolling() { // a simple method where we go through every LED with 1/10 chance // of being turned on, up to 10 times, with a random delay wbetween each time for (int r = 0; r < random(2, 10); r++) { //iterate through every LED for (int i = 0; i < NUM_LEDS; i++) { if (random(0, 100) > 90) { leds[i] = CHSV( 0, 0, 255); } else { //dont need reset as we're blacking out other LEDs her leds[i] = CHSV(0, 0, 0); } } FastLED.show(); delay(random(5, 100)); reset(); } } void crack() { //turn everything white briefly for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CHSV( 0, 0, 255); } FastLED.show(); delay(random(10, 100)); reset(); } void thunderburst() { // this thunder works by lighting two random lengths // of the strand from 10-20 pixels. int rs1 = random(0, NUM_LEDS / 2); int rl1 = random(10, 20); int rs2 = random(rs1 + rl1, NUM_LEDS); int rl2 = random(10, 20); //repeat this chosen strands a few times, adds a bit of realism for (int r = 0; r < random(3, 6); r++) { for (int i = 0; i < rl1; i++) { leds[i + rs1] = CHSV( 0, 0, 255); } if (rs2 + rl2 < NUM_LEDS) { for (int i = 0; i < rl2; i++) { leds[i + rs2] = CHSV( 0, 0, 255); } } FastLED.show(); //stay illuminated for a set time delay(random(10, 50)); reset(); delay(random(10, 50)); } } // basically just a debug mode to show off the lightning in all its glory, no sound reactivity. void constant_lightning() { switch (random(1, 5)) { case 1: Serial.println("Thunderburst"); thunderburst(); delay(random(10, 500)); break; case 2: Serial.println("Rolling"); rolling(); break; case 3: Serial.println("Crack"); crack(); delay(random(50, 250)); break; case 4: acid_cloud(); Serial.println("Acid"); delay(random(50, 250)); break; } } void setup() { // this line sets the LED strip type - refer fastLED documeantion for more details https://github.com/FastLED/FastLED FastLED.addLeds<LED_MODE, 3, LED_ORDER>(&leds[0], 3); FastLED.addLeds<LED_MODE, 5, LED_ORDER>(&leds[3], 2); FastLED.addLeds<LED_MODE, 6, LED_ORDER>(&leds[5], 2); FastLED.addLeds<LED_MODE, 9, LED_ORDER>(&leds[7], 1); FastLED.addLeds<LED_MODE, 10, LED_ORDER>(&leds[8], 1); // starts the audio samples array at volume 15. memset(vol, 15, sizeof(vol)); Serial.begin(115200); } void test_lights() { for (int i = 0; i < NUM_LEDS; i++) { leds[i] = CRGB(255, 127, 127); FastLED.show(); delay(500); leds[i] = CHSV( 0, 0, 0); FastLED.show(); } } void loop() { //constant_lightning(); detect_thunder(); reset(); //{ /*int r = random(10000); if (r < 5) { Serial.println("random trigger"); rolling(); }*/ //} /* // Maps mode names to code functions. switch(mode){ case CLOUD: detect_thunder();reset();break; case ACID: acid_cloud();reset();break; case OFF:reset();break; case ON: constant_lightning();reset();break; case RED: single_colour(0);break; case BLUE: single_colour(160);break; case GREEN: single_colour(96);break; case FADE: colour_fade();break; default: detect_thunder(); reset();break; } */ }
Popis vývoje a konečná verze vlastního produktu
Pro vstupy, které následně generují vzorec blikání, jsme využili mikrofon. Ten zachytí zvuk z prostředí a na základě jeho hlasitosti (v principu rozlišuje tři úrovně hlasitosti - “blesk”, “hrom” a “hřmění”) rozbliká LED. LED diody i mikrofon jsou skrz breadboard vedeny do “arduina”, které je naprogramováno výše zmíněným kódem. Veškeré prvky jsou umístěny v polystyrenové kostře obalené polyesterovou náplné do polštářů tak, aby vypadala jako mrak. Napájení je zajištěno power bankou, takže zařízení je soběstačné a mobilní.
Zhodnocení
Práce na projektu i výsledný výstup předčil naše očekávání. V průběhu práce na projektu jsme museli čelit několika přkážkám - původně zamýšlené LED diody nešly použít kvůli vysokým energetickým nárokům, nikdo z našeho týmu neuměl efektivně pájet, mrak nedělal to, co jsme chtěli, aby dělal. I přes tato dílčí příkoří se však podařilo uspěšně sestrojit mrak, který reaguje na zvuky (bouřky) tak, že budí dojem skutečného bouřkového mraku. Do budoucna bychom chtěli projekt nadále rozšiřovat - zejména přidat bluetooth ovládání a reproduktor.
Fotodokumentace
Videogalerie
https://www.facebook.com/UnicornsAreReal/videos/10209519726973865/?l=3361546968519763848