Arduino – Časování pomocí intervalů

IMG_8754_webPokud to považuji za vhodné, tak v některých projektech používám platformu Arduino. Koncepce programové konstrukce aplikace pro Arduino spočívá ve dvou hlavních metodách – setup() a loop(), ve které program neustále běží. Pro pohodlnější práci s obsluhou periodických procesů jsem napsal jednoduchou knihovnu, která tyto úkoly umožňuje napsat velmi elegantním způsobem.Knihovna interval vytváří časovací objekty a zpřístupňuje dvě metody – metodu set a metodu expired. Metoda set se používá k nastavení timeoutu a definici začátku časování, metoda expired pak slouží k ověření, zda nastavený interval již vypršel. Zajímavostí je, že knihovna korektně ošetřuje přetečení vnitřního milisekundového čítače, takže nehrozí nebezpečí špatného časování i při velmi dlouhé době chodu zařízení.

Příklad použití – modifikované demo BlinkWithoutDelay.ino

54 komentářů u „Arduino – Časování pomocí intervalů“

  1. Celkem dobrý, je nutný aby se ta funkce jmenovala blink, nebo to bude fungovat i s jinými názvy pro více úrovní časování?

    1. Blink je jen symbolické pojmenování vytvořené instance. Pojmenovat ji je možné jakkoliv – dle konvencí C++, a těchto instancí může být také více. Omezení je pouze dostupná RAM…

      1. Ahoj, vyzkoušel jsem se dvěma instancemi, jedna 1000 a druhá 2000 milis, vždy po expiraci se vypíše která instance expirovala, ale vypisuje se následovně:
        Expirace1
        Expirace2
        Expirace1
        Expirace1
        Expirace2

        Tedy, po druhé expiraci první instance, se nevypíše expirace té druhé, pak to zase funguje a tak stále dokola, nějaká rada?

        1. Ahoj. To, co vidím je ale správně ne? První výpis je (předpokládám) začátek, kdy oba intervaly expirovaly. Následně 2x expiruje ten, co je nastavený na 1 sekundu a hned za ním ten, co je nastavený na 2 sekundy…

  2. odzkoušeno, celkem zjednodušení programu při časování různých událostí (čtení senzorů, výpis na displej, na web…)
    dobrá práce.

  3. Dobrý den, chtěl bych požádat o obecnou radu. Z Vašeho blogu je jasné, že s Arduinem „dost kamarádíte“. Já s ním začínám a upřímně řečeno, jejich IDE mi příliš nevyhovuje. Zvykl jsem si u pokročilejších nástrojů na různé nápovědy a automatické doplňování přímo při psaní kódu. Našel jsem si Code Blocks, kde mi základní věci chodí, ale některé dodatečně instalované knihovny jsem nerozchodil. Prosím, jaké IDE používáte Vy? Co by jste doporučil? A ještě jedna prosba. Pokud je kód delší, jak ho lze jednoduše rozdělit do více souborů? Například: deklarace v jednom souboru, funkce v druhém a vlastní program ve třetím. Děkuji za radu. David

    1. Dobrý den, jako IDE pro Arduino projekty jsem vyzkoušel Maria Mole, ArduinoCodeBlocks, Arduino Sublime a IDE4Arduino – originální „IDE“ mi také nevyhovuje, jenomže jsem nakonec u něj stejně skončil. Co se týče pořadí, jak moc jsem jednotlivé nástroje používal, tak je to asi takhle:
      ArduinoCodeBlocks – rychlé, funkční, knihovny mohly být součástí projektu, takže se nic nemuselo doinstalovávat do IDE a dalo se vše poslat v jednom ZIPu – používal jsem asi nejvíce.
      Maria Mole – relativně nový projekt, který ale ustrnul (nevím jak teď) a neměl spoustu věcí, co CodeBlocks ano.
      Arduino Sublime – velmi nadějně vypadající, chystal jsem se ho začít používat jenže nastaly důvody, které proberu na závěr.
      Ostatní jmenované jsem ani moc podrobně nezkoušel, protože – a teď přijdou ty důvody – nastoupilo Arduino pro ESP8266 moduly. Jediná reálná funkční konfigurace, o které vím, je standardní IDE (používám verzi 1.6.5 v konfiguraci „Portable“) s pluginem pro překlad pro ESP8266, takže jsem byl dotlačený do originálního „IDE“. Ve skutečnosti texty edituji v Notepad++.
      Co se týče dělení, tak se snažím o klasické dělení – deklarace (a dokumentace) v .h souboru, výkonné funkce v .cpp a hlavní program stejně musí být v .ino. Pokud je to větší projekt a jen trošku to jde, tak v .ino mám jen setup() a loop(), ve kterých jsou použity objekty z jiných souborů.
      Pavel

    1. Dobrý večer. Každá z těch knihoven byla vytvořená pro jiný účel – můj interval slouží jako jednoduchá eliminace delay() v kódu a tím „znehybnění“ zbytku aplikace, zatímco tasker umožňuje zdánlivě paralelní spuštění více vláken. Interval bude mít jednodušší použití, zatímco tasker nabízí více možností, jak celý program postavit a rozdělit na jednotlivá vlákna. Co zase tasker neumí a můj interval v poslední (zatím neuveřejněné verzi) ano, je zjištění kolik ze zadaného intervalu zbývá času a kolik času již uběhlo od začátku časování.

      1. Po delší době zkouším zkompilovat progámky s toto funkcí na novém pc, IDE1.6.10, knihovnu interval mám nainstalovanou, a při kompilaci hlásí tuhle chybu: /home/karel/Arduino/libraries/interval/interval.cpp:6:21: fatal error: arduino.h: No such file or directory
        #include
        co s tím?

        1. Podle cesty k souboru jde o překlad pod linuxem – je třeba arduino.h nahradit Arduino.h – Linux je totiž citlivý na velikost písmen a já v tomto měl chybu, protože jsem původně pracoval jen pod Windows.

  4. Dík, to mě nenapadlo, ale je fakt, že tohle mě občas potrápí, jsem taky původně dlouholetý uživatel windows…

  5. Dobrý den
    Vím že můj příspěvek nesouvisí přímo s tímto článkem ale nevím na koho se obrátit. Chci vytvořit bargraph, s buzením pře I2C. Zkusil jsem využít tuto knihovnu http://playground.arduino.cc/Code/LcdBarGraph ale vůbec se mi ji nedaří zprovoznit ani příklady v ní. Prosím mohl by jste mi pomoci se setsavením knihoven tak, aby aby i tato zmíněná knihovna fungovala nebo lze bargraph přes I2C vytvořit i jinak? Díky za jakoukoliv odpověd.

  6. Dobrý den,
    s arduinem se teprve učím a tak vás prosím jestli by jste mi mohl vysvětlit jak se vaše knihovna používá nějak to nemůžu pochopit.Potřeboval bych udělat zvukovou signalizaci na rozvícení světla s prodlevou pokud tam dám delay tak po zhasnutí zařízení píská dokud neuběhne daná prodleva.
    Předem děkuji za odpověd

    1. Dobrý večer,
      knihovna přímo obsahuje příklad použití, ale pokud nedostačuje, tak to můžeme rozebrat. Takže přesně potřebujete co? Nebojte se rozepsat podrobněji co máte hotové, co je kam připojené a jak si představujete výsledek…

  7. takže kod:
    #include
    #include „interval.h“
    int hodnota = 1;
    Interval blink;

    void setup() {
    Serial.begin(9600);
    pinMode(2,INPUT);
    pinMode(5,INPUT);
    pinMode(4,OUTPUT);

    }

    void loop() {
    Serial.println(set()/2);
    int stav = digitalRead (5);
    if(stav == 0){
    if (blink.expired()) {
    blink.set(set()*30000);
    tone(4, 392);}}
    if(stav == 1){noTone (4);}

    }

    float set(){

    int tl1;
    tl1 = digitalRead(2);
    hodnota = EEPROM.read(0);
    if(tl1 == 0){ hodnota = hodnota + 1; }
    if(hodnota > 10){ hodnota = 1; }
    EEPROM.update(0, hodnota);
    delay(100);
    return hodnota;

    }

    na pin 2 je připojene tlačítko kterým se nastabje prodleva
    na pin 3 repruduktor
    a na pin 5 světelné čidlo

    jde o zařízení do lednice která má udělat zvukovou signalizaci když někdo nechá otevřené dveře ale musí se nastavit prodleva aby zařízení nepípalo při každém otevření ledničky

    1. Jistě – nefunguje to proto, protože časovač (interval) běží stále. Zkuste udělat to, že za příkaz noTone(4); dáte blink.set(set() * 30000); a nastavení časovače před tone(4, 392) odstraníte. Pak celý skript bude pracovat tak, že se neustále nastavuje časovač na potřebnou dobu a ve chvíli otevření dveří se teprve začne hlídat a testovat, jestli nevypršel.
      Další věcí je, že používáte všude int a neuvedl jste typ používaného Arduina. Pokud to je některé s procesorem AVR 8 bitů (Leonardo, Nano, Micro, Mega, …), tak je int definován v rozmezí -32767 až +32768, což může zmást kompilátor při násobení * 30000. Navíc proměnnou hodnota máte nadeklarovanou jako int a přitom set() má výstup float. Doporučuji tedy další následující úpravy:
      1. uint32_t hodnota = 1;
      2.
      uint32_t set()
      {
      hodnota = EEPROM.read(0);
      if (0 == digitalRead(2))
      ++hodnota;
      if (10 < hodnota) hodnota = 1; EEPROM.update(0, (uint8_t)hodnota); return hodnota; } Důvody, proč jsem udělal tyto změny konstrukce: 1. rozsah proměnné hodnota koresponduje s vstupním rozsahem objektu blink 2. zápis porovnání (0 == digital.....), který vypadá "obrácený" je záměr - pokud opomenete vynechat jedno rovnátko ve Vašem zápisu, tak to kompilátor nezahlásí, protože výraz tl1 = 0 je platnou konstrukcí jazyka C/C++ a budete honit chybu, která nebude zřetelná, zatímco v mém zápisu pokud zapomenete napsat dvě rovnítka vyhlásí překladač chybu 3. přetypování (uint8_t) je opět z toho důvodu, že Arduino maskuje varování překladače, takže se nedozvíte, jakou konverzi použil, protože parametr EEPROM.update v položce dat je jeden byte (uint8_t) Vyzkoušejte a dejte vědět výsledek...

  8. Dobrý den,
    Chtěl jsem se zeptat jestli neumíte sestavit program pro arduino uno. Použití fotorezistoru s odporem 10k se zapojením A0 a výstupem na který koli pin se zapojeným mosfetem. Použití soumrakový spínač na led pásek, ale od setmění dojde k sepnutí a s možností nastavení času v programu jak dlouho má byt sepnutý obvod po setmění. Přiklad: Setmi se Ardurino sepne obvod s časem nastavením 3hod jak se rozední obvod vypne nebo bude vypnut podle daného času a tak dokola. Jsem laik ,ale něco maličko umím našel jsem nějake programy na fotorezitor ale ten čas k tomu dát neumím a nikde sem to nenašel. Předem díky.

    1. Dobrý den,
      zkuste použít stavový automat – v prvním stavu budete testovat, zda je intenzita osvětlení pod Vámi specifikovanou úrovní, pokud ne, tak testujete stále dokola, pokud ano, tak inicializujete interval na požadovaný čas, rozsvítíte LED a přejdete na stav 2. Ve stavu 2 budete jen testovat, zda vypršel interval – pokud ne, tak testujete stále dokola, pokud ano, tak zhasnete LED a přejdete do stavu 3. Ve stavu 3 budete testovat intenzitu osvětlení a čekat, až stoupne nad Vámi specifikovanou úroveň (čekáte na rozednění), pokud je světla málo, tak stále testujete a čekáte, pokud je světla dostatek, tak přejdete do stavu 1. Algoritmus se dá doplnit o ošetření přechodů světlo<->tma tak, aby to při přechodech neblikalo.

      1. Našel jsem tento program byl ve španělštině trochu jsem ho přegoglil a nahrál do arduina s testovací svítivou led diodou misto spinaciho tranzistoru funguje dobře , ale tady končím neumin napsat ten spínací čas.Poradíte..???. s těmi přikazy sem mimo. Děkuji.

        //nastavte proměnné

        int luz = 0;

        int odpor = 0;

        int limit = 50;

        //vytvořit porty (pin)

        void setup()

        {

        Serial.begin(9600);

        pinMode(6, OUTPUT);

        pinMode(A0, INPUT);

        }

        void loop()

        {

        //přijímat informace od fotorezisty

        odpor = analogRead(A0);

        luz = (5.0 * odpor * 100.0) / 1024.0;

        //tisknout hodnoty

        Serial.print(luz);

        Serial.println(“ LUZ“);

        Serial.print(odpor);

        Serial.println(“ Ohms“);

        delay(300);

        //podmínky pro zapnutí světla

        if (luz limit) {

        digitalWrite(6, 0);

        }

        }

        1. Dobrý den,
          myslím, že jsem poradil, ale vypadá to, že spíš chcete, aby to někdo napsal za Vás… 🙁 Zkuste si něco nastduovat a moje rady aspoň nějak zapracovat do kódu. Mimochodem WordPress zkresluje příspěvky, protože to není fórum, takže možná bude lepší zvolit komunikaci mailem.

  9. Ahoj.
    Prosimtě chci se zeptat…. Nevim jak z toho ven….
    Používam interval od tebe. Chci ho použít v programu jako tzv. Delay On a taky jako Delay Off. Takže pri pruběhu programu dokola, potřebuju nastavit ten čas pouze jednou a až potom změnit vystup. Jenže jak ten program jede dokola, tak nevim jakou podminku dat k tomu přikazu set.
    Je nějaké snadné řešení jak z toho ven?? Aby to udělalo vždy jen jednou v programu? Díky za rady 🙂

    Tuším, psal jsi že maš nejakou nezveřejněnou verzi ktera ukazuje i kolik času zbyva…..nedalo by se to využít zrovna pro moji potřebu?

    1. Ahoj,
      chapu to tak, ze cas chces zadavat jen jednou? Pokud ano, tak uprav objekt intreval tak, aby .set uschoval do pomocne promenne tu hodnotu a dopln metodu treba .reload, ktera pouzije uschovanou hodnotu ze .set

  10. ahoj,
    neslo by upravit tvou knihovnu tak, aby nemuseli byt pouzivany funkce .expired a .set? Prijde mi to zbytecne prodlouzeni kodu. Pokud funkci volam, tak bud rovnou s parametrem = nastavi cas, nebo bez parametru = vrati true/false podle stavu.

    Nebo to ma nejaky duvod, ktery nevidim?

    1. Ahoj,
      vždycky jsem si myslel, že jménem se volá pouze konstruktor objektu, pro volání vnitřních metod je tečková konvence, takže nevím, jak to udělat jinak. Jedině snad sloučit .expired a .set do jedné metody, ale ta se bude muset volat tečkovaně také…

      1. jo, vcera zkousel neco vymyslet a nakonec jsem to vzdal. Tak jsem aspon zkratil „.expired“ na „.exp“ 🙂

        jeste jsem uvazoval o tom pridat funkci, ktera by pri kazde expiraci prepnula mezi true/false. Usetrilo by to dost kodu pri konstrukci ruznych blikacu a tak. Misto deklarovani bool promenne a jejiho prenastavovani by stacilo zeptat na stav.

        1. 🙂 . To s tím přepínáním není špatný nápad – kdyby se to spojilo s autoreload automatikou a ukládáním původní hodnoty, jak už v diskuzi také zaznělo. Možná je už fakt čas, abych aspoň Interval hodil na github – tam by se ta knihovna asi spravovala nejsnadněji.

          1. takze Interval
            .set(xxx) – nastavi cas na xxx ms
            .reset – znovu spusti s naposled nastavenym casem
            .exp – overi expiraci
            .out – overi sudy/lichy interval
            .left – zbyvajici cas v ms do expirace

            //to .out se mi uplne nelibi, ale nic lepsiho me nenapada 🙂

    1. Tak knihovna Interval je na githubu (https://github.com/Pablo2048/Interval). Ještě budu upravovat readme.md, ale jinak je tam všechno. V každém případě ale bude muset zůstat zachované .expired – já a asi ani nikdo další, kdo knihovnu používá nebude upravovat stávající projekty 🙂 …

      1. hmm, mas recht. Skoda ze ArduinoIDE neumi provadet nejake pokrocilejsi „najit&nahradit“, pokud by zjistilo ze ma novejsi knihovnu nez byla pouzita v projektu 🙂
        —————–
        K tomu doplneni knihovny o dlasi funkce se taky dostanes?

        1. Nóóó, já to myslel tak, že můžeš udělat pull-request a já to schválím 🙂 proto jsem to dal na github…

  11. Takže původní funkčnost je zachována a jsou tam další „feature“? to asi zkusím využít, mám tuhle knihovnu v mnoha projektech. Pro nás méně chápavý by byly fajn i další příklady na ty rozšířený funkce…

    1. Release verze v0.0.1 je původní, uveřejněná zde. Master už má doplněnou funkčnost .restart, jak prošlo tady diskuzí. Další věci (toggle) doplním, ale bylo by dobrý, kdyby se Míra ozval, ať to nějak koordinujeme. Příklady budu muset teprve vyrobit.

  12. Ahoj Pavle. Píšu pro kamaráda nějaký program na řízení serv. Standardní knihovna Servo tvrdí, že je možné řídit až 12 serv.
    Používám v programu asi tři intervaly založené na tvojí knihovně. Program běží na Arduino ProMini ATmega328p/16MHz. Všechno funguje perfektně pokud neaktivuji více jak tři serva. Pak se serva začnou třást a začne to být nepoužitelné. Nechci po tobě, abys louskal můj program. Chci se jen zeptat, jestli nemůže knihovna Servo nějak kolidovat s knihovnou Interval.
    V každém případě Ti přeji krásné Vánoce a hodně štěstí a radosti v roce 2019.
    Pavel

    1. Ahoj Pavle,
      nenapadá mě, kde by mohl být problém. Zkusil bych se na Tvůj kód podívat, ale mám neskutečně málo času – i teď sedím u PC a pracuji (proto taky nejsou žádné nové články). Pokud by stačilo, že se na to kouknu nejdřív ve čtvrtek příští týden, tak mi to pošli. Hezké Vánoce i Tobě a Tvým blízkým a hodně štěstí v roce 2019.
      Pavel

  13. Dobrý den,
    začínám a bez angličtiny to není vůbec jednoduché..
    Hledám něco, co jednoduše nahradí delay.
    Představoval bych si třeba :
    Time1(1000)
    …V sestupu by se definoval požadované zpoždění Time1,Time2,….
    Je něco takového?
    Děkuji Honza

    1. Dobrý den Honzo,
      úplně přesně Vás nechápu, ale pokusím se nějak poradit – zkuste se podívat na knihovnu ticker. Nenapsal jste ani, na jakou architekturu to potřebujete (AVR, ESP8266, ESP32, STM, …), takže knihovna ticker je součástí core ESP8266 a ESP32 pro jiné architektury asi bude nutné doinstalovat https://github.com/sstaub/Ticker .

      1. Rozumím, že začátečníku nerozumíte :-)..
        Tohle je začátečnická klasika:
        void setup() {

        pinMode(LED_BUILTIN, OUTPUT);
        }

        void loop() {
        digitalWrite(LED_BUILTIN, HIGH);
        delay(1000);
        digitalWrite(LED_BUILTIN, LOW);
        delay(1000);
        }

        A já bych se chtěl vyhnout delay, millis, a ifům…hledám tedy knihovnu, která by umožnila kód napsat takto:
        void setup() {

        pinMode(LED_BUILTIN, OUTPUT);
        }

        void loop() {
        digitalWrite(LED_BUILTIN, HIGH);
        Time(1000);
        digitalWrite(LED_BUILTIN, LOW);
        Time(1000);
        }
        Tedy -abych se nemusel o nic starat a řešit, jen dosazovat čas a Time požadavek obslouží bez delay, millis, if…..
        Děkuji za trpělivost, Honza

        1. Pokud si přečtete to, co jste napsal tak zjistíte, že jediný rozdíl je v tom, že místo delay() máte napsané Time() s naprosto stejnou funkčností včetně blokování běhu (což je právě důvod, proč nemám rád delay), takže opravdu nechápu pointu. Pokud tedy opravdu chcete nahradit delay() za Time(), tak nejsnadnější zápis je tento #define Time(a) delay(a) , ale význam to nemá prakticky žádný.

          1. Jsem opravdu nesrozumitelný, omlouvám se. Ale jde mi o to, aby výraz Time (nebo podobný) reprezentoval proceduru, kterou spustí a ta zajistí zpoždění, samozřejmě tak, že nezastaví běh programu. Tedy nebude používat delay, millis(obava z přetečení).
            Už jsem se vyjádřil přesněji?
            Nakonec jsem se to snažil vyjádřit naposledy přibližně takto:

            „Tedy -abych se nemusel o nic starat a řešit, jen dosazovat čas a procedura Time zajistí požadavek na zpoždění bez delay, millis, if…..“

            Děkuji

          2. Potíž je v tom, že v příkladech, které jste uvedl prakticky žádný „program“ není, takže to z toho není zjevné. Obávám se, že knihovna, která nějak automagicky rozkouskuje aplikaci do časových okamžiků a nebudete muset nic řešit neexistuje. To, co naznačujete ukazuje spíš na vícevláknovou aplikaci, protože řešení, které jste naznačil, kdy by Time() „viselo“ někde v aplikaci po dobu 1 + 1 sekundy by například na architektuře ESP8266 spolehlivě vedlo k restartu kvůli software WDT. Existují knihovny pro threading a pseudo-threading (protothreads), ale mají několik nevýhod: Pokud jste začátečník, tak začínat programování rozjezdem thread scheduleru, nebo studiem toho, že nesmíte zapomenout, že všechny lokální proměnné pro protothreads musí být deklarované jako static, není dobrý nápad. Multithreading obecně vece k větší spotřebě paměti RAM – pokud použijete „opravdové“ vícevláknové řešení (nějaký RTOS, nebo vlastní scheduler), tak každé vlákno bude vyžadovat svůj stack v RAM, v případě protothreadů to není tak kritické, ale v RAM musí být umístěné všechny lokální proměnné. Pro začátečníka bych doporučil přezkoumání filozofie přístupu ke struktuře aplikace, protože třeba zrovna to uvedené blikání LED je vhodnější přesunout na pozadí a vlastní aplikaci nechat běžet na popředí – tohle dá s pomocí knihovny Ticker napsat na pár řádků (a nebude tam žádné if a millis(), nastavíte to jednou a víc se nemusíte starat).

  14. Díky za snahu 🙂 Programátor ze mne v tomhle životě asi nebude 🙂
    Ale jste obdivuhodný člověk…takových je málo.
    Ještě jednou-díky moc…

  15. Ahoj Pavle,
    prosím o pomoc s projektem. Potřebuju po sepnutí tlačítka „pauzu“ 3 minuty a pak sepnout relé na vteřinu a zase vypnout. Zkoušel jsem použít tvojí knihovnu, ale nějak se mi to nedaří rozchodit. Mohl bys prosím kouknout na můj kód co dělám špatně?
    Kód:
    #include

    /*GPIO 00 – BUTTON_1 1
    GPIO 04 – Relay 3
    GPIO 05 – Relay 2
    GPIO 09 – BUTTON_1 2
    GPIO 10 – BUTTON_1 3
    GPIO 12 – Relay 1
    GPIO 13 – WiFi LED
    GPIO 14 – BUTTON_1 4
    GPIO 15 – Relay 4*/

    #define RELAY_1 12
    #define RELAY_2 5
    #define RELAY_3 4
    #define RELAY_4 15
    #define BUTTON_1 0
    #define BUTTON_1_2 9
    #define BUTTON_1_3 10
    #define BUTTON_1_4 14
    #define BUTTON_1_5 13

    Interval blink;

    const long blinkinterval = 18000;

    const long blinkinterval_2 = 1000;

    void setup(){

    Serial.begin(9600);
    pinMode(RELAY_1, OUTPUT);
    pinMode(BUTTON_1, INPUT);
    pinMode(RELAY_2, OUTPUT);
    pinMode(BUTTON_1_2, INPUT);
    pinMode(RELAY_3, OUTPUT);
    pinMode(BUTTON_1_3, INPUT);
    pinMode(RELAY_4, OUTPUT);
    pinMode(BUTTON_1_4, INPUT);
    pinMode(BUTTON_1_5, INPUT);
    digitalWrite(RELAY_1, LOW);
    digitalWrite(RELAY_2, LOW);
    digitalWrite(RELAY_3, LOW);
    digitalWrite(RELAY_4, LOW);
    delay(2000);
    Serial.println(„start“);
    }

    void loop() {

    if(digitalRead(BUTTON_1) == LOW){
    blink.set(blinkinterval);
    if (blink.expired()) {
    Serial.println(„cas vyprsel“);
    digitalWrite(RELAY_1, HIGH); // zapni rele
    Serial.println(„rele sepnuto“);

    blink.set(blinkinterval_2);
    if (blink.expired()) {
    digitalWrite(RELAY_1, LOW); // vypni rele
    Serial.println(„rele vynuto“);

    }
    }
    }
    }

    Děkuji
    Honza

    1. Ahoj Honzo,
      chyba je v tom, že v každém průchodu loop() smyčkou voláš nastavení intervalu funkcí .set. Program musíš přepracovat tak, aby se .set volal jen jednou, protože každým zavoláním se čas zase nastaví a tím se oddálí čas vypršení.
      Pavel

      1. Ahoj Pavle,
        díky za rychlou reakci. Zkoušel jsem už všechno možný, ale pořád bez úspěchu.(buď to špatně počítá, nebo to vůbec nefunguje) Nemohl bys mi prosím(až budeš mít chvilku) hodit laso? Jsem v tomhle směru úplný začátečník(do téhle doby jsem používal delay) tak v tom trochu plavu.
        Děkuju
        Honza

        1. Ahoj Honzo,
          píšu to z hlavy, ale zkus Tvůj loop() nahradit tímhle:

          void loop(void)
          {
          static int state = 0;

          if (digitalRead(BUTTON_1) == LOW){
          if (0 == state) {
          if (blink.expired()) {
          Serial.println(F(“cas vyprsel”));
          digitalWrite(RELAY_1, HIGH); // zapni rele
          Serial.println(F(“rele sepnuto”));
          blink.set(blinkinterval_2);
          state = 1;
          }
          }
          } else {
          if (0 == state)
          blink.set(blinkinterval); // startujeme casovani na 30 sekund
          }
          if (1 == state) {
          if (blink.expired() {
          state = 0;
          digitalWrite(RELAY_1, LOW); // vypni rele
          Serial.println(F(“rele vypnuto”));
          }
          }
          }

          Mělo by to být podle Tvého zadání a podle toho, co bylo naprogramované. Já bych to sice udělal asi tak, že to tlačítko nemusíš držet stisknuté celé ty 3 minuty, ale tak jsi to napsané neměl 😉 …
          Pavel

          1. V podstatě je to co potřebuju, jenom ještě nefunguje druhý interval. Pokud je stisknuté tlačítko, tak je pořád sepnuto relé a vypne hned po uvolnění (bez intervalu). Jinak by to mělo simulovat koncák vrat, pokud je tma a je otevřeno, tak po třech minutách dát impuls relé k zavření. Mám to postavené na Sonoff dual.
            Díky moc za tvůj čas.
            Honza

Komentáře nejsou povoleny.