/* Snow 13, verze 1.0 Efekt padajících sněhových vloček/kapajících rampouchů pomocí 20 LEDek zapojených pomocí Charlieplexingu na 5 vývodů mikrořadiče ATTiny13 Zapojení vývodů ATtiny13 1 Reset, přes rezistor 10k na Vcc 2 Vrchol Charlieplexingu 3 3 Vrchol Charlieplexingu 4 4 GND 5 Vrchol Charlieplexingu 0 6 Vrchol Charlieplexingu 1 7 Vrchol Charlieplexingu 2 8 Vcc = +5V Při programování mikrořadiče nezapomeňte nastavit Fuses pomocí funkce "Vypálit zavaděč" v Arduino IDE ! Název funkce je na první pohled nelogický, protože do ATtiny13 se zavaděč nedá vypálit, ale u vyšších mikrořadičů to jde a kromě něj se nastavují i Fuses pro selekci zdroje a rychlosti hodin. */ // Definice tabulky pro rozsvícení příslušné LEDky; první vývod do High, druhý do Low const byte LED[20][2] = { { 4, 3 }, // 0 { 0, 3 }, // 1 { 1, 3 }, // 2 { 2, 3 }, // 3 { 3, 4 }, // 4 { 0, 4 }, // 5 { 1, 4 }, // 6 { 2, 4 }, // 7 { 3, 0 }, // 8 { 4, 0 }, // 9 { 1, 0 }, // 10 { 2, 0 }, // 11 { 3, 1 }, // 12 { 4, 1 }, // 13 { 0, 1 }, // 14 { 2, 1 }, // 15 { 3, 2 }, // 16 { 4, 2 }, // 17 { 0, 2 }, // 18 { 1, 2 } // 19 }; // Aktuální pozice vločky byte current = 0; // Inicializace generátoru náhodných čísel = Seed; Pokud budeme mít více ozdob vedle sebe, je vhodné pro každý mikrořadič naprogramovat jiné Seed int random_number = 0xABA9; void setup() { bitSet(MCUCR, 6); // Set PUD = 6. bit v MCUCR do 1 = globální zákaz Pull-Up Rezistoru } void loop() { unsigned long loopCount = 0; // používá se pro úpravu střídy = snížení intenzity svitu stopy unsigned long timeNow = millis(); // aktuální čas unsigned long displayTime = 10 + (generate_random() & 0x7F); // rychlost padání je ovlivňována náhodným číslem while(millis()- timeNow < (displayTime+current*2)) { // zpomalování padání ke konci stopy loopCount++; // Vlastní vločka svítí naplno if (current > 19) charlieON(19); // pro zobrazení koncového dosvitu else charlieON(current); // Dosvit = stopa svítí s nižší intenzitou - emulováno pomocí střídy if(!(loopCount % 3)) if(current-1 >=0 && current-1 < 19) charlieON(current-1); if(!(loopCount % 6)) if(current-2 >=0 && current-2 < 19) charlieON(current-2); if(!(loopCount % 9)) if(current-3 >=0 && current-3 < 19) charlieON(current-3); if(!(loopCount % 12)) if(current-4 >=0 && current-4 < 19) charlieON(current-4); } current++; if(current==23) { // nyni zobraz koncový dosvit LEDky 19 for(int dutyCycle = 3; dutyCycle <= 15; dutyCycle += 3) { loopCount = 0; timeNow = millis(); while(millis() - timeNow < (displayTime+current*2)) { // zpomalování padání ke konci stopy loopCount++; if(!(loopCount % dutyCycle)) charlieON(19); else { // Zhasni vsechny LEDky DDRB = 0x00; // Nastav celý port B jako vstupní; PUD nastaven, není nutné odepínat interní pull-up rezistory zapsáním 0 } } } current = 0; // a zase od začátku // Zhasni vsechny LEDky DDRB = 0x00; // Nastav celý port B jako vstupní; PUD nastaven, není nutné odepínat interní pull-up rezistory zapsáním 0 delay(100 + 8 * generate_random()); // Čekej náhodně generovaný časový interval na nové padání } } // -------------------------------------------------------------------------------- // Rozsviť LEDku thisLED a zhasni všechny ostatní // void charlieON(byte thisLED) { // Zhasni vsechny LEDky DDRB = 0x00; // Nastav celý port B jako vstupní PORTB = 0x00; // Zapsaním 0 odepni interní pull-up rezistory - není nutné, nastaven PUD + priprav, ze po prepnuti na vystupni bude na obou portech LOW !!! // Rozsviť LEDku thisLED if(thisLED >= 0 && thisLED <= 19) { pinMode(LED[thisLED][0], OUTPUT); pinMode(LED[thisLED][1], OUTPUT); digitalWrite(LED[thisLED][1], HIGH); digitalWrite(LED[thisLED][0], LOW); // pro jistotu, ale 0 by tam už měla být zapsána příkazem PORTB = 0x00; } } // -------------------------------------------------------------------------------- // Vygeneruj pseudonáhodné číslo // byte generate_random() { random_number = (random_number >> 0x01u) ^ (-(random_number & 0x01u) & 0xB400u); return lowByte(random_number); }