OK

Při poskytování služeb nám pomáhají soubory cookie. Používáním našich služeb vyjadřujete souhlas s naším používáním souborů cookie. Více informací

Úvodní stránka » Arduino » Nextion display - V.díl – časovač a dialogová okna

Nextion display -V.díl – časovač a dialogová okna

Navážeme na předchozí článek a ukážeme si nastavení prodlevy, kdy se zaměříme hlavně na displej. Převážnou část funkcí prostě přeneseme do displeje. Ukážeme si jak používat timer a cyklovat zobrazení hodnot na displeji. Arduino k tomu potřebovat budeme.

I k tomuto projektu se Vám bude hodit fyzický kus displeje Nextion, jinak neuvidíte reakci.

Časovač - Timer

Pro automatické ztmavení displeje, použijeme interní časovač displeje a funkci timer. Každá stránka dostane svůj timer, který po otevření stránky začne odpočítávat čas. Když čas doběhne do konce, displej se vrátí na úvodní stránku a sníží svůj jas na minimální nastavenou úroveň. Pokud se dotknete displeje, či jakéhokoliv tlačítka, timer se restartuje a čas poběží od začátku. Zatím to necháme nastavené tak, že pro nastavení času využijeme čas v timeru a ne globální proměnnou.

Toto je pouze ukázka, jak funguje časovač. Využít se dá k zavírání dialogových oken, omezení času pro zadání např. kódu, automatického zámku po uplynutí času od stisku, animacím, prostě co Vás napadne a potřebujete měřit čas. Na jedné stránce můžete mít více časovačů a řídit tak více operací. Je to pouze na Vás a nijak s tím nemusíte zatěžovat Arduino. Jenom myslete na to, že je stále dobré, aby Arduino vědělo na jaké stránce jste a neodesílalo třeba data, která se Vám mohou krýt s jinými daty. Jinak ho ale k tomuto příkladu nepotřebujeme.

Aby jste viděli, že to opravdu funguje, je zapotřebí fyzicky připojit displej.

HMI soubor je ke stažení zde.

Timer se nastavuje tak, že do proměnné "tim" zadáváme čas, po jehož uplynutí se stane nějaká akce. V našem případě zobrazí stranu 0 a současně sníží jas na hodnotu 20. Když projdete všechny tlačítka, všimněte si, že ke každému tlačítku musíme přidat funkci resetu časovače. Jinak to nebude fungovat. Jedinému, kterému to nemusíme říkat, je posun na další stránku, tam si časovač spouštíme po načtení stránky. Přestože nemáme interakci s Arduinem, nechal jsem tam po načtení stránky odeslat příkaz sendme.

Dialogová okna

Stisknu tlačítko a něco se má stát. Třeba odesílám SMS a pak se zobrazím výsledek. Dá se k tomu využít předchozí příklad. Pak se doba časovače nastaví jako globální proměnná a můžeme měnit i dobu zobrazení, ale proč to nedát na jednu stránku.

Vytvoříme si tedy stránku se dvěma tlačítky, které nám budou simulovat konečné stavy a i dobu zobrazení dialogového okna.

Teď už jsem dal do kódu poznámky. Jak vypadá struktura kódu v displeji. Po otevření strany si nejdříve skryjeme dialogová okna. Pak to stisku tlačítka, provedeme sadu akcí, nastavíme proměnnou va0 – říká nám co má pak zobrazit, nastavíme čas zobrazení, zapneme časovač, zakážeme dotyk a zobrazíme dialogového okno. Pak co doběhne časovač, spustí akci dle hodnoty proměnné va0. Tedy drtivou část funkcí převzal časovač a opět Arduino vůbec nepotřebujeme.

HMI soubor je ke stažení zde.

! POZOR ! Timer není delay(). Přeložit se to dá tak, počítej čas a až uplyne něco udělej a to opakuj tak dlouho, dokud mě nevypneš.

Tedy v praxi můžete spustit časovač a dělat cokoliv jiného. Mimo jiné i přijímám příkazy z Arduina. Je tedy zapotřebí zajistit, aby nás Arduino neposlalo na jinou stránku, či nepřepsalo proměnou se kterou pracuje časovač, tedy pakliže to sami nechceme.

Jinak je to jednoduché, jenom si musíte dávat pozor, aby to bylo všude a správně. V tomto je Nextion Editor poněkud nepřehledný.

Dialogová okna – interakce s Arduinem

A konečně první použitelný příklad. Začátek je stejný jako v předchozím příkladě. Rozdíl je v tom co se děje po stisku tlačítka. Jenom zakážeme dotyk, zobrazíme úvodní dialogové okno a odešle informaci o tom že jsme stiskli tlačítko a čekáme na zpětnou vazbu od Arduina. Arduino provede požadovanou akci a pak nastaví které dialogové okno se má zobrazit, nastaví čas časovače a spustí ho. Ostatní za nás zajistí časovač. Samozřejmě můžeme dialogová okna zobrazovat a skrývat příkazy z Arduina, je to na Vás jak k tomu přistoupíte.

HMI soubor je ke stažení zde.

#define nextion Serial // port pro komunikaci s displejem Nextion
//------------------------------------------------------------------
boolean akce = true; // promenne rpo zpracovani vysledku akce
int prodleva_casovace; // doba prodlevy spusteni casovace
//------------------------------------------------------------------
void setup() {
  nextion_init(9600); // inicializace displeje a nastaveni rychlosti
}
//------------------------------------------------------------------
void loop() {
  //------------------------------------------------------------------
  check_display(); // kontrola prijatych dat
  //------------------------------------------------------------------
}
//------------------------------------------------------------------
void touch_Return(String page_ID, String component_ID, String touch_event) {
  if (page_ID == "0") {
    //------------------------------------------------------------------
    if (component_ID == "1") {
      // tady provedeme akci - odesleme treba SMS, ziskame navratovou hodnotu a podle toho odesleme
      // my to udelame tak, ze spustime funkci a podle navratove hodnoty budeme zobrazovat prislusne okno
      //------------------------------------------------------------------
      if (odesli_SMS()) { // kdyz se akce povedla
        send_value("va0", 1); // nastav promennou na dialogove okno OK
      }
      else { // kdyz se akce nepovedla
        send_value("va0", 2); // nastav promennou na dialogove okno CHYBA
      }
      //------------------------------------------------------------------
      prodleva_casovace = 2000; // nastavime cas behu casovace
      timer_Time("tm0", prodleva_casovace); // odesleme cas behu casovace
      timer_Start("tm0", true); // nova funkce, spust casovac a tim se zobrazi dialogove okno dle promenne
      delay(prodleva_casovace); // jen pro tento priklad, zajistime aby nam do disleje neodesla zadna data po dobu behu casovace
    }
    //------------------------------------------------------------------
    else if (component_ID == "2") { // no a tady udelame to same, kdyz uz mame ty dve tlacitka
      // tady zase neco delame
      //------------------------------------------------------------------
      if (odesli_SMS()) { // kdyz se akce povedla
        send_value("va0", 1); // nastav promennou na dialogove okno OK
      }
      else { // kdyz se akce nepovedla
        send_value("va0", 2); // nastav promennou na dialogove okno CHYBA
      }
      //------------------------------------------------------------------
      prodleva_casovace = 2000; // nastavime cas behu casovace
      timer_Time("tm0", prodleva_casovace); // odesleme cas behu casovace
      timer_Start("tm0", true); // nova funkce, spust casovac a tim se zobrazi dialogove okno dle promenne
      delay(prodleva_casovace); // jen pro tento priklad, zajistime aby nam do disleje neodesla zadna data po dobu behu casovace
    }
  }
}
//------------------------------------------------------------------
boolean odesli_SMS() { // odesilame SMS
  delay(2000); // tu funkci nahradime cekanim
  akce = !akce; // nastavime si hodnotu pro dalsi stisk - jen pro tento priklad
  return akce; // vratime hodnotu pro dotaz
}
//------------------------------------------------------------------
// funkce pro komunikaci s diplejem
//------------------------------------------------------------------
void page_Return(String page_ID) {
  // zde nic nedelame
}
//------------------------------------------------------------------
String Nextion_receive(boolean read_data) { //returns generic

  boolean answer = false; // znacka
  char bite; // promenna pro ulozeni znaku
  String cmd; // promenna pro ulozeni textu
  byte countEnd = 0; // pocitadlo
  unsigned long previous; // cas spusteni
  int timeout = 1000; // doba po kterou se ceka na prichozi data
  previous = millis();

  do { // cekani na spravnou odpoved
    if (nextion.available() > 0) { // kdyz jsou k dispozici data, precti data
      bite = nextion.read();
      cmd += bite;
      if ((byte)bite == 0xff) countEnd++;
      if (countEnd == 3) answer = true;
    }
  }
  while (!answer && !((unsigned long)(millis() - previous) >= timeout)); // ceka na spravnou hodnotu, nebo uplynuti casu

  if (read_data) { // read general data
    if (cmd[0] == 0x65) { // Touch event return data
      // 0X65 + Page ID + Component ID + TouchEvent + End
      touch_Return(String(cmd[1], DEC), String(cmd[2], DEC), String(cmd[3], DEC));
    }
    else if (cmd[0] == 0x66) { // Current page ID number returns
      // 0X66 + Page ID + End
      page_Return(String(cmd[1], DEC));
    }
    else if (cmd[0] == 0x67) { // Touch coordinate data returns
      // 0X67++ Coordinate X High-order+Coordinate X Low-order+Coordinate Y High-order+Coordinate Y Low-order+TouchEvent State+End
    }
    else if (cmd[0] == 0x68) { // Touch Event in sleep mode
      // 0X68++Coordinate X High-order+Coordinate X Low-order+Coordinate Y High-order+Coordinate Y Low-order+TouchEvent State+End
    }
  }
  else { //read get data
    if (cmd[0] == 0x70) { // String variable data returns
      // X70+Variable Content in ASCII code+End
      return cmd;
    }
    else if (cmd[0] == 0x71) { // Numeric variable data returns
      // 0X71+variable binary data(4 bytes little endian mode, low in front)+End
      return cmd;
    }
  }
}
//------------------------------------------------------------------
void nextion_init(int speed_init) { // nastaveni pri spusteni displeje
  nextion.begin(speed_init);
}
//------------------------------------------------------------------
void check_display() { // kontrola prijatych dat
  if (nextion.available() > 0) { // kontroluje obsah pameti, pokud nen nic odeslano, dalsi cast programu se neprovede
    Nextion_receive(true); // precist hodnoty z serial portu
  }
}
//------------------------------------------------------------------
void timer_Time(String componentID, int time) { // nastaveni casu behu casovace
  String timerTime = componentID + ".tim=" + String(time); // odesli hodnotu
  send_Command(timerTime.c_str());
}
//------------------------------------------------------------------
void timer_Start(String componentID, boolean start) { // spusteni/zastaveni timeru
  String timerStart = componentID + ".en=" + String(start); // odesli hodnotu
  send_Command(timerStart.c_str());
}
//------------------------------------------------------------------
void send_value(String componentID, int value) {
  String compValue = componentID + ".val=" + String(value); // odesli hodnotu
  send_Command(compValue.c_str());
}
//------------------------------------------------------------------
void send_Command(const char* cmd) { // odeslani dat do displeje
  nextion.print(cmd);
  nextion.write(0xFF);
  nextion.write(0xFF);
  nextion.write(0xFF);
  nextion.flush();
}

A tady jsem při přípravě článku udělal chybu. Protože jsem od přírody líný, použil jsem vzor z nějakého projektu a protože jsem si poctivě neprošel všechny objekty v displeji, zapomněl jsem tam jeden příkaz. Skoro půl hodiny jsem hledal co je špatně. Poučení – budu jako doposud tvořit vše od píky.

Odpočítávání

Spustíme nějakou akci a na displeji chceme vidět, kolik času zbývá do konce akce. Třeba odchodový čas po zakódování, chci vypnout displej, abych ho mohl očistit..... K tomu slouží následující příklad. Tady opět Arduino potřebovat nebudeme.

HMI soubor je ke stažení zde.

Stiskneme tlačítko, vypneme dotyk a běží čas. Když doběhne, opět vše povolíme. Čas, který máme nastaven k odpočítávání je zde uveden. Celý proces se opakuje do té doby, než se nám hodnota proměnné nastaví na nula. Pak vypneme časovač, povolíme dotyk a obnovíme tlačítko. Samozřejmě lze přidat libovolné funkce, pak se někam vrátíme, pošleme data Arduinu, tlačítky můžeme měnit dobu odpočítávání.....

Tady krátce odbočím. Displej neumí pracovat s desetinnými čísly. Řešení existuje, ale není to úplně jednoduché. Musíte s polem pracovat jako s textem a pak v Arduino převádět do desetinného čísla. Hlavně kód v displeji, pak ale začíná být opravdu velmi dlouhý.

Závěr

Vidíte, že do displeje se dá dostat opravdu hodně funkcí, aniž by bylo potřeba cokoliv dávat do Arduina. Jenom připomínám, že pokud chcete vidět co je v displeji naprogramováno, je potřeba zobrazit konkrétní prvek.

Také jsme si do sketche přidali dvě nové funkce pro práci s displejem.

Příště se podíváme na kreslení a zase si zobrazíme ty malované hodiny, kde součástí bude i funkce Gauge a ukážeme si jak si z displeje udělat stopky.

JB

jaroslav.bohac@arduinotech.cz

Přidat komentář

Zvýrazněné položky jsou povinné.

Přehled komentářů

  1. dtb (Martin, 7.2.2017 20:05:41) Odpovědět | Zobrazit odpovědi

    díky za super tutorial - jen tak dál! :)

    Měl bych námět pro některý z dalších dílů ->
    získávání informací např. z webové stránky/dtb a následné předání hodnot do displeje

    1. Re: dtb (Jaroslav Boháč, 9.2.2017 22:35:36) Odpovědět

      Děkuji za pochvalu. Za několik dílů ukáži jak ukládat logy na kartu SD a do EEPROm a jak je zobrazit na displeji.

  2. Opět super, jako vždy! (PavelDC, 7.2.2017 23:46:05) Odpovědět | Zobrazit odpovědi

    Bezkonkurenčně nejlepší návody na netu v českém jazyce! Díky za vaši práci pro komunitu, Pavel

    1. Re: Opět super, jako vždy! (Zdendis, 8.2.2017 9:17:50) Odpovědět

      Naprosto souhlasím!!!

  3. Další článek (Zdendis, 14.2.2017 13:34:04) Odpovědět | Zobrazit odpovědi

    Kdy se můžeme těšit na další článek?

    1. Re: Další článek (Zdendis, 15.2.2017 20:10:26) Odpovědět

      Bylo by fajn zobrazení hodin a datumu + nastavení hodin pomocí displeje a s třešničkou nějaký budik ;)?

      1. Re: Re: Další článek (Jaroslav Boháč, 21.2.2017 19:22:05) Odpovědět

        Přesně toto mám v plánu. Už brzo, ale postupně :-). Jsem rád, že jste si o to sami řekli.

        1. Re: Re: Re: Další článek (Zdendis, 21.2.2017 19:34:18) Odpovědět

          Jsem hrozně nedočkavej hltám každý članek je v nich nějaká pravidelnost nebo podle nálady :)?

          1. Re: Re: Re: Re: Další článek (Jaroslav Boháč, 21.2.2017 19:41:31) Odpovědět

            Bohužel mě živí něco jiného. Nechci sem tahat politiku, ale naši zákonodárci připravili takovou jobovku, díky níž se musím 25 hodin denně a 8 dní týdnu věnovat řešení jiných věci. Také všechny programy testuji, zapojení.... a ne vždy mám k dispozici všechny součástky a musím na ně čekat. Od března bude zase více času a součástky teď mám, tak bych chtěl dávat alespoň jeden článek za dva týdny.

            1. Re: Re: Re: Re: Re: Další článek (Zdendis, 21.2.2017 19:43:27)

              tak to chápu také to odlaďuji na svém eshopu přece jen 1.3 se blíží děkuji za info

  4. Taky děkuji (Ulrich, 28.2.2017 19:39:14) Odpovědět

    Super seriál, díky moc.

  5. Dalsi dil (Zdendis, 10.3.2017 13:21:09) Odpovědět | Zobrazit odpovědi

    Můžeme se těšit na dva díly po sobě :) ?

    1. Re: Dalsi dil (Jaroslav Boháč, 12.3.2017 19:10:24) Odpovědět

      Slibuji, že budou rychleji za sebou. První je zveřejněn :-).

      1. Re: Re: Dalsi dil (Zdendis, 12.3.2017 21:30:22) Odpovědět

        Už jsem zkoušel a díky skvělý jako vzdy

  6. Ulozeni casu do eeprom (Zdendis, 14.4.2017 18:21:38) Odpovědět | Zobrazit odpovědi

    Dobrý den,
    mám enhanced model a snažil jsem se uložit hodnotu timeru tm0 ale nedaří se stále je tam defaultní hodnota tm0.tim=20000.

    ulozena nová hodnota - wepo 1000,10

    tm0 - event - repo x.val,10
    postinitialize event na strance 0 - repo x.val,10 tm0.tim=x.val

    poradil by někdo ? chtěl bych některé uživatelské data jako jsou čas vypnutí displejem stmívaní atd uložit do displeje a nezatěžovat arduino
    Děkuji Vám

    1. Re: Ulozeni casu do eeprom (Jaroslav Boháč, 15.4.2017 21:16:32) Odpovědět

      Problém, který popisujete se týká dvou oblastí, deklarace proměnné a výpadku napájení.
      Proměnnou je zapotřebí deklarovat jako globální, pak je její hodnota udržována po celou dobu co je displej napájen. Jinak se Vám hodnota vždy vrátí do výchozí hodnoty po otevření stránky.
      Pak při výpadku napájení, dojde k nastavení hodnot tak jak jste je naprogramoval. V arduinu můžeme pro tento případ použít uložení proměnné do paměti EEPROM. Pokud ji displej má, pak se nikde nedočtete jak do ní zapsat. Tedy pro případ výpadku napájení, je zapotřebí načíst hodnotu proměnné z Arduina, kam jí nejdříve uložíte, třeba když jí změníte. Jiného východisko neznám.

      1. Re: Re: Ulozeni casu do eeprom (Zdendis, 16.4.2017 11:08:48) Odpovědět

        ok děkuji moc

  7. Timer (Zdendis, 18.4.2017 19:18:26) Odpovědět | Zobrazit odpovědi

    Timer je omezený na maximálně cca 65s ?

    1. Re: Timer (Jaroslav Boháč, 20.4.2017 19:56:51) Odpovědět

      Teď nemám přístup k soukromému počítači, tak nevím jaká je maximální hodnota. Je uvedená v nápovědě, přímo v Nextion Editoru a je uvedena v ms. Tedy je možné že je to maximálně 65 s. Pokud potřebujete počítat delší čas, dá se to vyřešit zvyšování sekundární proměnné. Např. potřebuji odpočítat 5 minut. Spustím časovač na 60 s. Po uplynutí času, nastavím připravenou proměnnou o 1 a znovu spustím časovač. Když proměnná dosáhne hodnoty 5, zastavím časovač (už ho opětovně nespouštím) a provedu požadovanou akci. Jsou to dva řádky kódu.

    2. Re: Timer (Zdendis, 21.4.2017 6:52:08) Odpovědět

      Chytré dekuji


TOP produkty

Kontakt

Ing. Petr Foltýn
Kunčice pod Ondřejníkem 814, 73913
TOPlist