// Blikani pozicnich svetel pro modely letadel // ----------------------------------------------------- // verze 2 (26.5.2019) // // Prepsani programu z PIC do ATtiny. // Cerpano z clanku: // http://rcmodely.cevaro.sk/index.php?id=996&n=%E2%80%9Etuctove%E2%80%9C-pozicne-osvetlenie // Ovladani je mozne ve dvou rezimech // - rezim s propojkou mezi nohou 3 a 4: // pri vysoke hodnote PWM se LED rozsviti a rozblikaji, pri nizke hodnote LED zhasnou // // - rezim bez propojky: // pri vysoke hodnote se LED rozsviti a rozblikaji, pak se ceka na pokles PWM pod nastavenou uroven. // Pri dalsi vysoke hodnote PWM se LED zhasnou a zase se ceka na pokles pod nastavenou uroven. // // Nastaveni prepinacich PWM urovni se provadi pomoci konstant na zacatku programu // (graficke znazorneni rozdilu mezi rezimy: http://www.astromik.org/raspi/pozicni_svetla) // Ukazka na YouTube: // https://youtu.be/o3EujSRGapM // Zapojeni: //============= // ATtiny13 // +--\__/--+ // (RESET) - PB5 1| |8 Vcc - napajeni 5V // ovladaci vstup od RC - PB3 2| |7 PB2 - nepouzito // volba rezimu zapinani - PB4 3| |6 PB1 - nepouzito // GND 4| |5 PB0 - PWM vystup (blikani LED) // +--------+ // nastaveni prepinacich hodnot PWM na ovladaci pro oba rezimy spousteni a vypinani blikani // pro rezim s propojkou na PB4: #define PWM1_rozsvit 1500 // hodnota PWM, pri ktere se ma zacit blikat #define PWM1_zhasni 1300 // hodnota PWM, pri ktere se ma blikani ukoncit (musi byt nizsi, nez predchozi hodnota) // pro rezim bez propojky na PB4: #define PWM2_prepni 1800 // hodnota PWM, pri jejimz prekroceni se prepne stav LED (blikani/zhasnuto) #define PWM2_pokles 1500 // hodnota PWM, pod kterou musi PWM poklesnout, aby bylo umozneno dalsi prepnuti #define puljas 220 // jak velke PWM se ma nastavit pro polovicni jas LED (0=maximalni jas; 255=zhasnuto) // polovicni jas LED je takovy jas, na ktery budou LED svitit trvale // !!! POZOR na ztratove vykony pri zadani nizkych cisel !!! // --------- globalni promenne ----------- unsigned long sirka; // promenna pro sirku vstupniho pulzu v mikrosekundach unsigned int casovani; // pri rezimu blikani se podle aktualniho stavu promenne 'casovani' prepina mezi 'puljasem' a 100% vykonu boolean rezim_startu; // rezim spousteni a zastavovani blikani // false = prechodem pres hodnotu PWM // true = vysoke PWM zapina a zaroven vypina byte stav; // pomocna promenna pro aktualni stav LED // 0 = zhasnuto // 1 = zhasnuto, ceka na pokles PWM // 2 = blika pri nizkem PWM // 3 = blika, ale ceka na pokles PWM // --------- cinnosti po zapnuti napajeni (po resetu) ----------------- void setup(void) { pinMode(3,INPUT); // pin PB3 (noha 2) je ovladaci vstup od RC pinMode(4,INPUT_PULLUP); // pin PB4 (noha 3) je volba rezimu zapinani a vypinani blikani pinMode(0,OUTPUT); // pin PB0 (noha 5) je PWM vystup pro vykonovy tranzistor TCCR0A = 0b11000011; // rezim FAST PWM; vystup se nastavi do '1' pri dosazeni pozadovaneho cisla TCCR0B = 0b00000001; // FAST PWM, delic zakladni frekvence na 1:1 OCR0A = 255; // hodnota, se kterou se citac porovnava (0 az 255) (255 = zhasnuto) stav = 0; // aktualne jsou LED zhasnute } // --------- hlavni smycka ----------------- void loop(void) { sirka = pulseIn(3 , HIGH , 3000); // Na zacatku smycky se zjisti sirka PWM z ovladaciho RC (maximalni doba testovani je 3 ms) // ---- bezpecnostni blok, ktery testuje problem s PWM signalem z RC ovladace byte pocet_chyb = 0; // pokud by byl nejaky problem s RC ovladacim signalem a behem 3ms by se neobjevil zadny impulz, while (sirka == 0 and pocet_chyb < 100) // provede se jeste 100 pokusu o zjisteni sirky impulzu { sirka = pulseIn(3 , HIGH , 3000); pocet_chyb ++; // pocitadlo chyb se zvetsi o 1 } if (pocet_chyb == 100) // Po 100 chybach v rade (to je po 0,3 sekundach) se LED pro jistotu zhasnou (okamzite, bez stmivani) { OCR0A = 255; stav = 0; // a procesor se uvede do stavu, ve kterem ceka na zvyseni PWM pro rozblikani LED sirka = 1; } // ---------- konec bezpecnostniho bloku --------------------- rezim_startu = digitalRead(4); // urceni rezimu startu podle propojky na PB4 (noha 3) if (rezim_startu == false) // rozsveceni a zhasinani pomoci prechodu pres nejakou uroven PWM { // ---------- rozsvecovaci cast --------------- if (sirka > PWM1_rozsvit and stav == 0) // ovladacem je pri zhasnutem stavu nastaveno rozsviceni { postupne_rozsvit(); // pomale rozsviceni na 'puljas' stav = 2; // znacka, ze uz je rozsviceno } // ---------- zhasinaci cast --------------- if (sirka < PWM1_zhasni and stav == 2) // ovladacem je pri rozsvicenem stavu nastaveno zhasnuti { postupne_zhasni(); // pomale zhasnuti z 'puljas' na zhasnuto stav = 0; // znacka, ze uz je zhasnuto } } else // rozsveceni a zhasinani nastavenim vysoke hodnoty { // ---------- rozsvecovaci cast --------------- if (sirka > PWM2_prepni and stav == 0) // ovladacem je pri zhasnutem stavu nastaveno rozsviceni { postupne_rozsvit(); // pomale rozsviceni na 'puljas' stav = 3; // znacka, ze uz je rozsviceno, ale pred zhasnutim se ceka na pokles ovladaciho PWM } // ---------- cast poklesu PWM pri blikani --------------- if (sirka < PWM2_pokles and stav == 3) // ovladacem je pri rozsvicenem stavu nastavena priprava na zhasnuti { stav = 2; // znacka, ze uz je pripraveno na zhasnuti } // ---------- zhasinaci cast --------------- if (sirka > PWM2_prepni and stav == 2) // ovladacem je pri rozsvicenem stavu nastaveno zhasnuti { postupne_zhasni(); // pomale zhasnuti z 'puljas' na zhasnuto stav = 1; // znacka, ze uz je zhasnuto, ale pro dalsi rozsviceni je treba sjet s PWM dolu } // ---------- cast poklesu PWM pred dalsim rozsvicenim --------------- if (sirka < PWM2_pokles and stav == 1) // ovladacem je pri zhasnutem stavu nastavena priprava na dalsi rozsviceni { stav = 0; // znacka, ze uz je zhasnuto a pristi zvyseni PWM bude znamenat rozsviceni } } // ---------- blikaci cast --------------- if (stav > 1) // kdyz ma probihat blikani (stav 2 nebo 3) { if (casovani == 100) casovani = 0; // cela perioda jednoho dvojbliku je 1 sekunda. Kdyz casovac dobehne na 100 * 10ms = 1s, tak se vynuluje if (casovani == 0) OCR0A = puljas; // na zacatku periody se nastavi mensi jas if (casovani == 60) OCR0A = 0; // v 0,6 sekunde se rozsviti LED na plny jas if (casovani == 65) OCR0A = puljas; // v 0,65 sekunde se LED prepnou na mensi jas if (casovani == 95) OCR0A = 0; // v 0,95 sekunde se rozsviti LED na plny jas a budou svitit az do zacatku dalsiho cyklu casovani ++; } else { casovani = 0; // kdyz je blikani vypnute, zresetuje se casovac pro dvojblik } delay(10); // hlavni casovani (kazda smycka trva 0,01 sekundy) } //---------------------------------------------------------------------- // postupne rozsviceni LED na uroven zadanou v konstante 'puljas' void postupne_rozsvit(void) { for (byte i=255; i > puljas ; i--) { OCR0A = i; delay(20); // rychlost rozsveceni (cim vetsi cislo, tim je rozsviceni pomalejsi) } // vypocet casu rozsvecovani: t [ms] = (255 - puljas) * delay } // pro delay(20) a puljas=220 plati: (255 - 220) * 40 = 0,7 sekundy //---------------------------------------------------------------------- // postupne zhasnuti LED z urovne zadane v konstante 'puljas' void postupne_zhasni(void) { for (byte i=puljas; i < 255 ; i++) { OCR0A = i; delay(20); // rychlost zhasinani (cim vetsi cislo, tim je zhasinani pomalejsi) } // vypocet casu trvani stmivani je stejny jako pri rozsveceni }