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 » Arduino v příkladech - X. díl - Displej - tlačítka a akce

Arduino v příkladech - X. díl - Displej - tlačítka a akce

Displej máme zapojený, kalibrovaný, hlavně funguje a známe příkazy. To hlavní máme za sebou a teď se zaměříme na to jak ho využít. Základem je tlačítko, které spustí příkaz. A to je to, na co se zaměříme v tomto článku.

Hlavním popisem tedy bude práce s dotykovou plochou. Pro zapojení nám stačí to, co máme z minulého dílu. Pouze si k pinu 3 připojíme přes odpor diodu. Začneme popisem dotykové plochy.

Dotyková plocha

V úvodním dílu k displejům jste si jistě všimli, že když držíte stisknutou dotykovou plochu, neustále se vrací koordináty stisku a to ve frekvenci, než se provedou další příkazy, které jsou, nakresli kolečko, pošli na Serial koordináty stisku. To je dobré pro kreslení na displej, ale pro práci stiskni a zapni je to naprosto nevhodné. Také funkce kontroly stisku dotykové plochy nevyužívá přerušení, tedy pokud budete mít smyčku, která trvá déle než několik desítek milisekund, může se Vám stát, že stisknete dotykovou plochu a nic se nestane.

Jakou kombinaci možností tedy máme:

Stisknutím dotykové plochy způsobíme, že se stav pinu T_IRQ změní z LOW na HIGH. Dotaz touch.dataAvailable() nám vrací pouze stav pinu.

  1. Po stisku displeje počkáme, až dojde řada na kontrolu stisku a provedeme akci, to se opakuje ve smyčce. Vhodné pro kreslení na displej.
  2. Po stisku displeje počkáme, až dojde řada na kontrolu stisku a provedeme akci, pak na určitou dobu vypneme dotyk, aby nedocházelo k opakované akci. Jednoduché, ale pokud používáte delay(), případně máte jiné dlouhé časově náročné funkce, nespolehlivé.
  3. Po stisku displeje, vyvoláme přerušení a provedeme akci. Složité, ne na všech arduinech funguje korektně. Některé knihovny funkci přerušení vypínají.

Na první pohled se může zdát, že je nejlepší možnost s řerušením. ANO i NE – pokud ho chcete používat, doporučuji si buď na základě přerušení vytvořit značku a příkaz provést až na něj přijde řada, nebo si přerušení do vykonání příkazu vypnout, ale to se vracíme k variantě dva.

Samozřejmě i v průběhu práce s displejem lze využívat kombinaci všech tří možností čtení stisku dotykové plochy. Dokážu si představit, chci nechat vzkaz – režim jedna malujeme, normálně zapínám a vypínám – režim dva nespěchám a neriskuji, potřebuji zastavit otáčení zeměkoule – režim tři přerušení, protože toto nepočká.

V následující části se podíváme jak s tlačítky pracovat. Je to jednoduché – na displej nakreslíme něco, co chceme stisknout a pak když držíme stisknuté toto tlačítko, ověříme koordináty stisku a pokud souhlasí s nakresleným tlačítkem, provedeme akci.

Tlačítko malujeme

Sketch je jednoduchý, pouze kontrolujeme zda jsme stiskli a pokud ano, nakreslíme tečku. Tlačítka použijeme pro vymazání displeje a změnu barvy.

//------------------------------------------------------------------
// inicializace zakladnich knihoven
#include <SPI.h> // knihovna pro komunikacni rozhrani SP
#include <TFT_ILI9341.h> // knihovna displeje
#include <UTouch.h> // knihovna dotykové části
//------------------------------------------------------------------
// nastaveni pinu displej
//#define sclk 13  // Don't change, this is the hardware SPI SCLK line
//#define miso 12  // Don't change, this is the hardware SPI MISO line
//#define mosi 11  // Don't change, this is the hardware SPI MOSI line
#define TFT_CS    10   // Chip select for TFT display, don't change when using F_AS_T
#define TFT_DC     9   // Data/command line, don't change when using F_AS_T
//#define TFT_RST    8   // Reset, you could connect this to the Arduino reset pin
#define TOUCH_CLK  7   // Touch SCLK
#define TOUCH_CS   6   // Touch chip select
#define TOUCH_DIN  5   // Touch MOSI
#define TOUCH_DOUT 4   // Touch MISO
#define TOUCH_IRQ  2   // Touch IRQ
//------------------------------------------------------------------
// Promenne a nastaveni vstupu displej
TFT_ILI9341 tft = TFT_ILI9341(TFT_CS, TFT_DC);
// UTouch(byte clk, cs, din, dout, irq)
UTouch  touch(TOUCH_CLK, TOUCH_CS, TOUCH_DIN, TOUCH_DOUT, TOUCH_IRQ);
//------------------------------------------------------------------
// Promenne displej
byte TFT_rotation = 2; // nastaveni otoceni displeje
byte TOUCH_rotation; // nastaveni orientace dotykove plochy
int colorDraw = TFT_BLACK; // nastaveni vychozi barvy kresleni
int x; // radek x displej
int y; // radek y displej
//------------------------------------------------------------------
void setup() {
  tft.init(); // inicializace TFT displeje
  tft.setRotation(TFT_rotation); // nastaveni orientace displeje
  tft.setTextColor(TFT_BLACK); // nastaveni barvy pisma
  //------------------------------------------------------------------
  if (TFT_rotation == 0 || TFT_rotation == 2) TOUCH_rotation = PORTRAIT; // nastaveni otoceni dotykove plochy
  else if (TFT_rotation == 1 || TFT_rotation == 3) TOUCH_rotation = LANDSCAPE; // nastaveni otoceni dotykove plochy
  touch.InitTouch(TOUCH_rotation); // inicializuje dotykovou plochu
  touch.setPrecision(PREC_MEDIUM); // nastavi citlivost dotykove plochy
  strHlavni(); // zobrazeni uvodni stranky
}
//------------------------------------------------------------------
void loop() {
  //------------------------------------------------------------------
  // cteni dotykoveho displeje
  if (touch.dataAvailable()) { // kontrola prijatych dat z dotykoveho panelu
    dotyk(); // spust program dotyk
  }
}
//------------------------------------------------------------------
void dotyk() {
  //------------------------------------------------------------------
  // cteni hodnot z dotykoveho displeje
  touch.read(); // pokud jsou data precte je a ulozi do promenych
  x = touch.getX();
  y = touch.getY();
  //------------------------------------------------------------------
  // zjisteni stavu stranek, overeni stisku tlacitka a spusteni souvisejiciho programu
  if ((x != -1) && (y != -1)) { // a když není x a y menší než 0 ...
    //------------------------------------------------------------------
    // Kontrola stisku tlačítek
    if (y > 40) {// nakresli tecku
      //tft.drawPixel(x, y, colorDraw); // kresli tecku - vidime tenkou caru
      tft.fillCircle(x, y, 3, colorDraw); // nakresli kruh - vidime tlustou caru
    }
    else {
      if ((x >= 0 && x <= 39) && (y >= 0 && y <= 40)) { // vyber cerne barvy
        colorDraw = TFT_BLACK;
      }
      else if ((x >= 40 && x <= 79) && (y >= 0 && y <= 40)) { // vyber cervene barvy
        colorDraw = TFT_RED;
      }
      else if ((x >= 80 && x <= 119) && (y >= 0 && y <= 40)) { // vyber modre barvy
        colorDraw = TFT_BLUE;
      }
      else if ((x >= 120 && x <= 159) && (y >= 0 && y <= 40)) { // vyber zelene barvy
        colorDraw = TFT_GREEN;
      }
      else if ((x >= 160 && x <= 239) && (y >= 0 && y <= 40)) { // vymazani displeje
        strHlavni();
      }
    }
  }
}
//------------------------------------------------------------------
void strHlavni() {
  tft.fillScreen(TFT_WHITE); // nastaveni pozadi
  //------------------------------------------------------------------
  tft.fillRect(0, 0, 40, 40, TFT_BLACK); // zobrazeni tlacitka
  tft.fillRect(40, 0, 40, 40, TFT_RED); // zobrazeni tlacitka
  tft.fillRect(80, 0, 40, 40, TFT_BLUE); // zobrazeni tlacitka
  tft.fillRect(120, 0, 40, 40, TFT_GREEN); // zobrazeni tlacitka
  tft.fillRect(160, 0, 80, 40, TFT_LIGHTGREY); // zobrazeni tlacitka
  tft.drawCentreString("RESET", 200, 12, 2);
  //------------------------------------------------------------------
}

Tady se na chvíli zastavím. Část pro kreslení je hned v úvodu kontroly co jsme stiskli. Tady narážíme na rychlost Arduina, protože když to dáme nakonec kontroly a budete kreslit rychle, čáry budou přerušované. Prostě chvíli trvá, než Arduino projde všechny podmínky. Na toto je potřeba dávat pozor při tvorbě programu. Že to říkám už poněkolikáté, ANO.

Tlačítko čekáme

K tomuto využijeme režim dva a budeme měnit barvy pozadí, podle stisknutého tlačítka. Do programu jsme si přidali značku vypni dotyk, kterou v case kontrolujeme a pokud uplyne požadovaná doba prodlevy, povolíme reakci na dotyk.

//------------------------------------------------------------------
// inicializace zakladnich knihoven
#include <SPI.h> // knihovna pro komunikacni rozhrani SP
#include <TFT_ILI9341.h> // knihovna displeje
#include <UTouch.h> // knihovna dotykové části
//------------------------------------------------------------------
// nastaveni pinu displej
//#define sclk 13  // Don't change, this is the hardware SPI SCLK line
//#define miso 12  // Don't change, this is the hardware SPI MISO line
//#define mosi 11  // Don't change, this is the hardware SPI MOSI line
#define TFT_CS    10   // Chip select for TFT display, don't change when using F_AS_T
#define TFT_DC     9   // Data/command line, don't change when using F_AS_T
//#define TFT_RST    8   // Reset, you could connect this to the Arduino reset pin
#define TOUCH_CLK  7   // Touch SCLK
#define TOUCH_CS   6   // Touch chip select
#define TOUCH_DIN  5   // Touch MOSI
#define TOUCH_DOUT 4   // Touch MISO
#define TOUCH_IRQ  2   // Touch IRQ
//------------------------------------------------------------------
// Promenne a nastaveni vstupu displej
TFT_ILI9341 tft = TFT_ILI9341(TFT_CS, TFT_DC);
// UTouch(byte clk, cs, din, dout, irq)
UTouch  touch(TOUCH_CLK, TOUCH_CS, TOUCH_DIN, TOUCH_DOUT, TOUCH_IRQ);
//------------------------------------------------------------------
// Promenne displej
unsigned long casProdlevyDotyk; // cas posledniho dotyku
const byte prodlevaDotyk = 200; // nastaveni prodlevy mezi dotykem
boolean vypniDotyk = true; // povoleni
byte TFT_rotation = 2; // nastaveni otoceni displeje
byte TOUCH_rotation; // nastaveni orientace dotykove plochy
int x; // radek x displej
int y; // radek y displej
//------------------------------------------------------------------
void setup() {
  tft.init(); // inicializace TFT displeje
  tft.setRotation(TFT_rotation); // nastaveni orientace displeje
  tft.setTextColor(TFT_BLACK); // nastaveni barvy pisma
  //------------------------------------------------------------------
  if (TFT_rotation == 0 || TFT_rotation == 2) TOUCH_rotation = PORTRAIT; // nastaveni otoceni dotykove plochy
  else if (TFT_rotation == 1 || TFT_rotation == 3) TOUCH_rotation = LANDSCAPE; // nastaveni otoceni dotykove plochy
  touch.InitTouch(TOUCH_rotation); // inicializuje dotykovou plochu
  touch.setPrecision(PREC_MEDIUM); // nastavi citlivost dotykove plochy
  strHlavni(TFT_WHITE); // zobrazeni uvodni stranky
}
//------------------------------------------------------------------
void loop() {
  //------------------------------------------------------------------
  // cteni dotykoveho displeje
  if (touch.dataAvailable()) { // kontrola prijatych dat z dotykoveho panelu
    dotyk(); // spust program dotyk
  }
}
//------------------------------------------------------------------
void dotyk() {
  //------------------------------------------------------------------
  // omezeni opakovaneho stisku tlacitka
  if (!vypniDotyk) { // kdyz je dotyk vypnuty
    if ((unsigned long)(millis() - casProdlevyDotyk) >= prodlevaDotyk) { // pokud uplynula stanovena doba
      vypniDotyk = true; // zapni dotyk
    }
  }
  //------------------------------------------------------------------
  // cteni hodnot z dotykoveho displeje
  if (vypniDotyk) { // kdyz je dotyk zapnuty
    casProdlevyDotyk = millis(); // nastav novy cas pro vypocet prodlevy
    vypniDotyk = false; // vypni docasne dotyk
    touch.read(); // pokud jsou data precte je a ulozi do promenych
    x = touch.getX();
    y = touch.getY();
    //------------------------------------------------------------------
    // overeni stisku tlacitka a spusteni souvisejici akce
    if ((x != -1) && (y != -1)) { // a když není x a y menší než 0 ...
      if ((x >= 10 && x <= 110) && (y >= 10 && y <= 60)) { // cervene pozadi
        strHlavni(TFT_RED);
      }
      else if ((x >= 130 && x <= 230) && (y >= 10 && y <= 60)) { // zelene pozadi
        strHlavni(TFT_GREEN);
      }
      else if ((x >= 10 && x <= 110) && (y >= 260 && y <= 310)) { // modre pozadi
        strHlavni(TFT_BLUE);
      }
      else if ((x >= 130 && x <= 230) && (y >= 260 && y <= 310)) { // zlute pozadi
        strHlavni(TFT_YELLOW);
      }
      else if ((x >= 70 && x <= 170) && (y >= 135 && y <= 185)) { // bile pozadi
        strHlavni(TFT_WHITE);
      }
    }
  }
}
//------------------------------------------------------------------
void strHlavni(int color) {
  tft.fillScreen(color); // nastaveni pozadi
  //------------------------------------------------------------------
  // tlacitko cervena, vlevo nahore
  tft.fillRoundRect(9, 9, 102, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(10, 10, 100, 50, 10, TFT_RED); // zobrazeni tlacitka
  tft.drawCentreString("cervena", 60, 25, 2); // zobrazeni textu
  //------------------------------------------------------------------
  // tlacitko zelena, vpravo nahore
  tft.fillRoundRect(129, 9, 102, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(130, 10, 100, 50, 10, TFT_GREEN); // zobrazeni tlacitka
  tft.drawCentreString("zelena", 180, 25, 2); // zobrazeni textu
  //------------------------------------------------------------------
  // tlacitko modra, vlevo dole
  tft.fillRoundRect(9, 259, 102, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(10, 260, 100, 50, 10, TFT_BLUE); // zobrazeni tlacitka
  tft.drawCentreString("modra", 60, 275, 2); // zobrazeni textu
  //------------------------------------------------------------------
  // tlacitko zluta, vpravo dole
  tft.fillRoundRect(129, 259, 102, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(130, 260, 100, 50, 10, TFT_YELLOW); // zobrazeni tlacitka
  tft.drawCentreString("zluta", 180, 275, 2); // zobrazeni textu
  //------------------------------------------------------------------
  // tlacitko bila, na stredu
  tft.fillRoundRect(69, 134, 102, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(70, 135, 100, 50, 10, TFT_WHITE); // zobrazeni tlacitka
  tft.drawCentreString("bila", 120, 150, 2); // zobrazeni textu
}

Vidíte, že po stisku tlačítka, když máme provést zobrazení na displeji, nejdříve nakreslíme nové pozadí, čímž smažeme vše z displeje a pak tam tlačítka nakreslíme znovu.

Pokud neměníme pozadí, ale jenom část displeje, nemusíme překreslovat celý displej, ale pouze tu část, kterou měníme. Např. barvu tlačítka viz následující sketch, kde současně rozsvítíme i tu diodu a rovnou si otevřeme vrátka na kreslení ikon. Sluníčko s paprsky je krásné, ne?

//------------------------------------------------------------------
// inicializace zakladnich knihoven
#include <SPI.h> // knihovna pro komunikacni rozhrani SP
#include <TFT_ILI9341.h> // knihovna displeje
#include <UTouch.h> // knihovna dotykové části
//------------------------------------------------------------------
// nastaveni pinu displej
//#define sclk 13  // Don't change, this is the hardware SPI SCLK line
//#define miso 12  // Don't change, this is the hardware SPI MISO line
//#define mosi 11  // Don't change, this is the hardware SPI MOSI line
#define TFT_CS    10   // Chip select for TFT display, don't change when using F_AS_T
#define TFT_DC     9   // Data/command line, don't change when using F_AS_T
//#define TFT_RST    8   // Reset, you could connect this to the Arduino reset pin
#define TOUCH_CLK  7   // Touch SCLK
#define TOUCH_CS   6   // Touch chip select
#define TOUCH_DIN  5   // Touch MOSI
#define TOUCH_DOUT 4   // Touch MISO
#define DIODA      3   // dioda
#define TOUCH_IRQ  2   // Touch IRQ
//------------------------------------------------------------------
// Promenne a nastaveni vstupu displej
TFT_ILI9341 tft = TFT_ILI9341(TFT_CS, TFT_DC);
// UTouch(byte clk, cs, din, dout, irq)
UTouch  touch(TOUCH_CLK, TOUCH_CS, TOUCH_DIN, TOUCH_DOUT, TOUCH_IRQ);
//------------------------------------------------------------------
// Promenne displej
unsigned long casProdlevyDotyk; // cas posledniho dotyku
const byte prodlevaDotyk = 200; // nastaveni prodlevy mezi dotykem
boolean vypniDotyk = true; // povoleni
byte TFT_rotation = 2; // nastaveni otoceni displeje
byte TOUCH_rotation; // nastaveni orientace dotykove plochy
int x; // radek x displej
int y; // radek y displej
float sx, sy; // promenne pro kresleni paprsku
int x0, x1, y0, y1; // promenne pro kresleni paprsku
//------------------------------------------------------------------
void setup() {
  tft.init(); // inicializace TFT displeje
  tft.setRotation(TFT_rotation); // nastaveni orientace displeje
  tft.setTextColor(TFT_BLACK); // nastaveni barvy pisma
  //------------------------------------------------------------------
  if (TFT_rotation == 0 || TFT_rotation == 2) TOUCH_rotation = PORTRAIT; // nastaveni otoceni dotykove plochy
  else if (TFT_rotation == 1 || TFT_rotation == 3) TOUCH_rotation = LANDSCAPE; // nastaveni otoceni dotykove plochy
  touch.InitTouch(TOUCH_rotation); // inicializuje dotykovou plochu
  touch.setPrecision(PREC_MEDIUM); // nastavi citlivost dotykove plochy
  //------------------------------------------------------------------
  // zobrazeni uvodni stranky
  tft.fillScreen(TFT_WHITE); // nastaveni pozadi
  //------------------------------------------------------------------
  // nakreslime pozadi ktere se nebude menit
  tft.fillRoundRect(59, 134, 122, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillCircle(120, 60, 22, TFT_BLACK); // zobrazeni obrysu stavu diody
  //------------------------------------------------------------------
  // nakreslime zbytek uvodni stranky
  tft.fillCircle(120, 60, 20, TFT_LIGHTGREY); // zobrazeni stavu diody
  tft.fillRoundRect(60, 135, 120, 50, 10, TFT_GREEN); // zobrazeni tlacitka
  tft.drawCentreString("ON", 120, 150, 4); // zobrazeni textu
  paprsky(TFT_WHITE); // nakresli paprsky kolem ikony stavu
  //------------------------------------------------------------------
  pinMode(DIODA, OUTPUT); // vystup vystup pro diodu
}
//------------------------------------------------------------------
void loop() {
  //------------------------------------------------------------------
  // cteni dotykoveho displeje
  if (touch.dataAvailable()) { // kontrola prijatych dat z dotykoveho panelu
    dotyk(); // spust program dotyk
  }
}
//------------------------------------------------------------------
void dotyk() {
  //------------------------------------------------------------------
  // omezeni opakovaneho stisku tlacitka
  if (!vypniDotyk) { // kdyz je dotyk vypnuty
    if ((unsigned long)(millis() - casProdlevyDotyk) >= prodlevaDotyk) { // pokud uplynula stanovena doba
      vypniDotyk = true; // zapni dotyk
    }
  }
  //------------------------------------------------------------------
  // cteni hodnot z dotykoveho displeje
  if (vypniDotyk) { // kdyz je dotyk zapnuty
    casProdlevyDotyk = millis(); // nastav novy cas pro vypocet prodlevy
    vypniDotyk = false; // vypni docasne dotyk
    touch.read(); // pokud jsou data precte je a ulozi do promenych
    x = touch.getX();
    y = touch.getY();
    //------------------------------------------------------------------
    // overeni stisku tlacitka a spusteni souvisejici akce
    if ((x != -1) && (y != -1)) { // a když není x a y menší než 0 ...
      if ((x >= 70 && x <= 170) && (y >= 135 && y <= 185)) { // bile pozadi
        if (digitalRead(DIODA)) { // kdyz je dioda rozsvicena
          digitalWrite(DIODA, LOW); // vypni diodu
          tft.fillCircle(120, 60, 20, TFT_LIGHTGREY); // zobrazeni stavu diody
          paprsky(TFT_WHITE); // nakresli paprsky kolem ikony stavu
          tft.fillRoundRect(60, 135, 120, 50, 10, TFT_GREEN); // zobrazeni tlacitka
          tft.drawCentreString("ON", 120, 150, 4); // zobrazeni textu
        }
        else { // jinak kdyz je dioda zhasnuta
          digitalWrite(DIODA, HIGH); // zapni diodu
          tft.fillCircle(120, 60, 20, TFT_YELLOW); // zobrazeni stavu diody
          paprsky(TFT_YELLOW); // nakresli paprsky kolem ikony stavu
          tft.fillRoundRect(60, 135, 120, 50, 10, TFT_RED); // zobrazeni tlacitka
          tft.drawCentreString("OFF", 120, 150, 4); // zobrazeni textu
        }
      }
    }
  }
}
//------------------------------------------------------------------
// kresleni paprsku kolem ikony stavu
void paprsky(int color) {
  for (int i = 0; i < 360; i += 30) {
    sx = cos((i - 90) * 0.0174532925);
    sy = sin((i - 90) * 0.0174532925);
    x0 = sx * 35 + 120;
    y0 = sy * 35 + 60;
    x1 = sx * 25 + 120;
    y1 = sy * 25 + 60;
    tft.drawLine(x0 - 2, y0 - 2, x1 - 2, y1 - 2, color);
    tft.drawLine(x0 - 1, y0 - 1, x1 - 1, y1 - 1, color);
    tft.drawLine(x0, y0, x1, y1, color);
    tft.drawLine(x0 + 1, y0 + 1, x1 + 1, y1 + 1, color);
    tft.drawLine(x0 + 2, y0 + 2, x1 + 2, y1 + 2, color);
  }
}

Na "čekáme" se podíváme ještě jednou a pak to porovnáme s přerušením. Vytvoříme si jednoduchou obrazovku a držením tlačítka budeme měnit hodnoty. Současně můžeme nastavit i prodlevu tlačítka, která se hned projeví při dalším stisku. Zkuste nastavit prodlevu rovnající se 0 milisekund. Jde to, chce to trochu trpělivosti. Když se to povede, zjistíte, že jste přestali řídit počet stisků počítadla a po stisku se objevuje náhodná hodnota. Na druhou stranu mít prodlevu dvě sekundy je opravdu otrava, zkuste si to. Hledal jsem ideální hodnotu prodlevy. Ta neexistuje, mě nejlépe vyhovuje prodleva 200 milisekund. V tomto programu je zapotřebí udělat několik změn, které souvisí s převodem textu. drawString umí umístit text na požadované místo s požadovaným zarovnáním, ale pouze text. Čísla pro zobrazení je tedy nejprve nutné převést na text. Třeba další návod, i když trochu nechtěný.

//------------------------------------------------------------------
// inicializace zakladnich knihoven
#include <SPI.h> // knihovna pro komunikacni rozhrani SP
#include <TFT_ILI9341.h> // knihovna displeje
#include <UTouch.h> // knihovna dotykové části
//------------------------------------------------------------------
// nastaveni pinu displej
//#define sclk 13  // Don't change, this is the hardware SPI SCLK line
//#define miso 12  // Don't change, this is the hardware SPI MISO line
//#define mosi 11  // Don't change, this is the hardware SPI MOSI line
#define TFT_CS    10   // Chip select for TFT display, don't change when using F_AS_T
#define TFT_DC     9   // Data/command line, don't change when using F_AS_T
//#define TFT_RST    8   // Reset, you could connect this to the Arduino reset pin
#define TOUCH_CLK  7   // Touch SCLK
#define TOUCH_CS   6   // Touch chip select
#define TOUCH_DIN  5   // Touch MOSI
#define TOUCH_DOUT 4   // Touch MISO
#define TOUCH_IRQ  2   // Touch IRQ
//------------------------------------------------------------------
// Promenne a nastaveni vstupu displej
TFT_ILI9341 tft = TFT_ILI9341(TFT_CS, TFT_DC);
// UTouch(byte clk, cs, din, dout, irq)
UTouch  touch(TOUCH_CLK, TOUCH_CS, TOUCH_DIN, TOUCH_DOUT, TOUCH_IRQ);
//------------------------------------------------------------------
// Promenne displej
unsigned long casProdlevyDotyk; // cas posledniho dotyku
unsigned int prodlevaDotyk = 200; // nastaveni prodlevy mezi dotykem
boolean vypniDotyk = true; // povoleni
byte TFT_rotation = 2; // nastaveni otoceni displeje
byte TOUCH_rotation; // nastaveni orientace dotykove plochy
int x; // radek x displej
int y; // radek y displej
unsigned int count = 0; // pocitadlo
char charText[5]; // vytvoreni promenne pro zobrazeni textu
//------------------------------------------------------------------
void setup() {
  tft.init(); // inicializace TFT displeje
  tft.setRotation(TFT_rotation); // nastaveni orientace displeje
  tft.setTextColor(TFT_BLACK); // nastaveni barvy pisma
  //------------------------------------------------------------------
  if (TFT_rotation == 0 || TFT_rotation == 2) TOUCH_rotation = PORTRAIT; // nastaveni otoceni dotykove plochy
  else if (TFT_rotation == 1 || TFT_rotation == 3) TOUCH_rotation = LANDSCAPE; // nastaveni otoceni dotykove plochy
  touch.InitTouch(TOUCH_rotation); // inicializuje dotykovou plochu
  touch.setPrecision(PREC_MEDIUM); // nastavi citlivost dotykove plochy
  //------------------------------------------------------------------
  // zobrazeni uvodni stranky
  tft.fillScreen(TFT_WHITE); // nastaveni pozadi
  //------------------------------------------------------------------
  // nakreslime uvodni stranku
  tft.drawCentreString("POCITADLO", 120, 30, 4); // zobrazeni textu
  // leve tlacitko
  tft.fillRoundRect(24, 79, 52, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(25, 80, 50, 50, 10, TFT_GREEN); // zobrazeni tlacitka
  tft.drawCentreString("UP", 50, 95, 2); // zobrazeni textu
  // prave tlacitko
  tft.fillRoundRect(164, 79, 52, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(165, 80, 50, 50, 10, TFT_GREEN); // zobrazeni tlacitka
  tft.drawCentreString("DOWN", 190, 95, 2); // zobrazeni textu
  // nadpis
  tft.drawCentreString("PRODLEVA", 120, 160, 4); // zobrazeni textu
  // leve tlacitko
  tft.fillRoundRect(24, 209, 52, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(25, 210, 50, 50, 10, TFT_GREEN); // zobrazeni tlacitka
  tft.drawCentreString("UP", 50, 225, 2); // zobrazeni textu
  // prave tlacitko
  tft.fillRoundRect(164, 209, 52, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(165, 210, 50, 50, 10, TFT_GREEN); // zobrazeni tlacitka
  tft.drawCentreString("DOWN", 190, 225, 2); // zobrazeni textu
  // uprav nastaveni zobrazeni textu
  tft.setTextColor(TFT_BLACK, TFT_WHITE); // nastaveni barvy pisma
  // zobrazeni promennych
  itoa(count, charText, 10); // preved cislo na text
  tft.drawCentreString(charText, 120, 95, 4); // zobrazeni textu
  dtostrf((float)prodlevaDotyk / 1000, 4, 1, charText); // preved float na text
  tft.drawCentreString(charText, 120, 225, 4); // zobrazeni textu
}
//------------------------------------------------------------------
void loop() {
  //------------------------------------------------------------------
  // cteni dotykoveho displeje
  if (touch.dataAvailable()) { // kontrola prijatych dat z dotykoveho panelu
    dotyk(); // spust program dotyk
  }
}
//------------------------------------------------------------------
void dotyk() {
  //------------------------------------------------------------------
  // omezeni opakovaneho stisku tlacitka
  if (!vypniDotyk) { // kdyz je dotyk vypnuty
    if ((unsigned long)(millis() - casProdlevyDotyk) >= prodlevaDotyk) { // pokud uplynula stanovena doba
      vypniDotyk = true; // zapni dotyk
    }
  }
  //------------------------------------------------------------------
  // cteni hodnot z dotykoveho displeje
  if (vypniDotyk) { // kdyz je dotyk zapnuty
    casProdlevyDotyk = millis(); // nastav novy cas pro vypocet prodlevy
    vypniDotyk = false; // vypni docasne dotyk
    touch.read(); // pokud jsou data precte je a ulozi do promenych
    x = touch.getX();
    y = touch.getY();
    //------------------------------------------------------------------
    // overeni stisku tlacitka a spusteni souvisejici akce
    if ((x != -1) && (y != -1)) { // a když není x a y menší než 0 ...
      // tlacitka pocitadla
      if ((x >= 25 && x <= 75) && (y >= 80 && y <= 130)) { // pocitadlo nahoru
        count++; // pocitadlo +1
        count = count % 10; // omez promennou v rozsahu 0-9
        itoa(count, charText, 10); // preved cislo na text
        tft.drawCentreString(charText, 120, 95, 4); // zobrazeni textu
      }
      else if ((x >= 165 && x <= 215) && (y >= 80 && y <= 130)) { // pocitadlo dolu
        count--; // pocitadlo -1
        count = count % 10; // omez promennou v rozsahu 0-9
        itoa(count, charText, 10); // preved cislo na text
        tft.drawCentreString(charText, 120, 95, 4); // zobrazeni textu
      }
      // tlacitka prodlevy
      else if ((x >= 25 && x <= 75) && (y >= 210 && y <= 260)) { // prodleva nahoru
        prodlevaDotyk += 100; // zvyseni prodlevy o 100 millisekund
        prodlevaDotyk = prodlevaDotyk % 2100; // omez prodlevu v rozsahu 0-2000 millisekund
        dtostrf((float)prodlevaDotyk / 1000, 4, 1, charText); // preved float na text
        tft.drawCentreString(charText, 120, 225, 4); // zobrazeni textu
      }
      else if ((x >= 165 && x <= 215) && (y >= 210 && y <= 260)) { // prodleva dolu
        prodlevaDotyk -= 100; // snizeni prodlevy o 100 millisekund
        prodlevaDotyk = prodlevaDotyk % 2100; // omez prodlevu v rozsahu 0-2000 millisekund
        dtostrf((float)prodlevaDotyk / 1000, 4, 1, charText); // preved float na text
        tft.drawCentreString(charText, 120, 225, 4); // zobrazeni textu
      }
    }
  }
}

Tlačítko přerušení

To je poslední dostupný režim. Využijeme předcházející program, odstraníme z něj čekání, tlačítka změny prodlevy a přidáme reakci na přerušení při stisku tlačítka. Hlavní rozdíl v používání je, že pokud chceme znovu stisknout tlačítko, musíme ho nejdříve pustit a stisknout znovu. Čísla se nám nebudou počítat automaticky. Přerušení si nejprve otestujte, jak jsem psal výše – některé knihovny vypínají přerušení a nejde znovu pustit. To kdyby Vám to v jiném hotovém projektu nefungovalo.

POZOR – displej se nechová úplně korektně a proto je zapotřebí použít strukturu programu jak ji vidíte. Výhoda je že vám budou fungovat všechny funkce, které voláním ve funkci přerušení nefungují.

//------------------------------------------------------------------
// inicializace zakladnich knihoven
#include <SPI.h> // knihovna pro komunikacni rozhrani SP
#include <TFT_ILI9341.h> // knihovna displeje
#include <UTouch.h> // knihovna dotykové části
//------------------------------------------------------------------
// nastaveni pinu displej
//#define sclk 13  // Don't change, this is the hardware SPI SCLK line
//#define miso 12  // Don't change, this is the hardware SPI MISO line
//#define mosi 11  // Don't change, this is the hardware SPI MOSI line
#define TFT_CS    10   // Chip select for TFT display, don't change when using F_AS_T
#define TFT_DC     9   // Data/command line, don't change when using F_AS_T
//#define TFT_RST    8   // Reset, you could connect this to the Arduino reset pin
#define TOUCH_CLK  7   // Touch SCLK
#define TOUCH_CS   6   // Touch chip select
#define TOUCH_DIN  5   // Touch MOSI
#define TOUCH_DOUT 4   // Touch MISO
#define TOUCH_IRQ  2   // Touch IRQ
//------------------------------------------------------------------
// Promenne a nastaveni vstupu displej
TFT_ILI9341 tft = TFT_ILI9341(TFT_CS, TFT_DC);
// UTouch(byte clk, cs, din, dout, irq)
UTouch  touch(TOUCH_CLK, TOUCH_CS, TOUCH_DIN, TOUCH_DOUT, TOUCH_IRQ);
//------------------------------------------------------------------
// Promenne displej
byte TFT_rotation = 2; // nastaveni otoceni displeje
byte TOUCH_rotation; // nastaveni orientace dotykove plochy
int x; // radek x displej
int y; // radek y displej
unsigned int count = 0; // pocitadlo
char charText[5]; // vytvoreni promenne pro zobrazeni textu
boolean chekInterrupts = true; // kontrola spusteni preruseni
//------------------------------------------------------------------
void setup() {
  tft.init(); // inicializace TFT displeje
  tft.setRotation(TFT_rotation); // nastaveni orientace displeje
  tft.setTextColor(TFT_BLACK); // nastaveni barvy pisma
  //------------------------------------------------------------------
  if (TFT_rotation == 0 || TFT_rotation == 2) TOUCH_rotation = PORTRAIT; // nastaveni otoceni dotykove plochy
  else if (TFT_rotation == 1 || TFT_rotation == 3) TOUCH_rotation = LANDSCAPE; // nastaveni otoceni dotykove plochy
  touch.InitTouch(TOUCH_rotation); // inicializuje dotykovou plochu
  touch.setPrecision(PREC_MEDIUM); // nastavi citlivost dotykove plochy
  //------------------------------------------------------------------
  // zobrazeni uvodni stranky
  tft.fillScreen(TFT_WHITE); // nastaveni pozadi
  //------------------------------------------------------------------
  // nakreslime uvodni stranku
  tft.drawCentreString("POCITADLO", 120, 30, 4); // zobrazeni textu
  // leve tlacitko
  tft.fillRoundRect(24, 79, 52, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(25, 80, 50, 50, 10, TFT_GREEN); // zobrazeni tlacitka
  tft.drawCentreString("UP", 50, 95, 2); // zobrazeni textu
  // prave tlacitko
  tft.fillRoundRect(164, 79, 52, 52, 10, TFT_BLACK); // zobrazeni obrysu
  tft.fillRoundRect(165, 80, 50, 50, 10, TFT_GREEN); // zobrazeni tlacitka
  tft.drawCentreString("DOWN", 190, 95, 2); // zobrazeni textu
  // uprav nastaveni zobrazeni textu
  tft.setTextColor(TFT_BLACK, TFT_WHITE); // nastaveni barvy pisma
  // zobrazeni promennych
  itoa(count, charText, 10); // preved cislo na text
  tft.drawCentreString(charText, 120, 95, 4); // zobrazeni textu
}
//------------------------------------------------------------------
void loop() {
//------------------------------------------------------------------
// kontrola zapnuti preruseni
  if (chekInterrupts) { // kdyz je povolena kontrola zapnuti preruseni
    pinMode(TOUCH_IRQ,  INPUT); // at nemusime upravovat knihovnu
    if (digitalRead(TOUCH_IRQ)) { // kdyz neni dotyk stisknuty
      chekInterrupts = false; // zakaz kontrolu zapnuti preruseni
      attachInterrupt(digitalPinToInterrupt(TOUCH_IRQ), dotyk, LOW); // zapni preruseni
    }
  }
}
//------------------------------------------------------------------
void dotyk() {
  detachInterrupt(digitalPinToInterrupt(TOUCH_IRQ)); // vypni preruseni
  chekInterrupts = true; // povol kontrolu zapnuti preruseni
  //------------------------------------------------------------------
  // cteni hodnot z dotykoveho displeje
  touch.read(); // pokud jsou data precte je a ulozi do promenych
  x = touch.getX();
  y = touch.getY();
  //------------------------------------------------------------------
  // overeni stisku tlacitka a spusteni souvisejici akce
  if ((x != -1) && (y != -1)) { // a když není x a y menší než 0 ...
    // tlacitka pocitadla
    if ((x >= 25 && x <= 75) && (y >= 80 && y <= 130)) { // pocitadlo nahoru
      count++; // pocitadlo +1
      count = count % 10; // omez promennou v rozsahu 0-9
      itoa(count, charText, 10); // preved cislo na text
      tft.drawCentreString(charText, 120, 95, 4); // zobrazeni textu
    }
    else if ((x >= 165 && x <= 215) && (y >= 80 && y <= 130)) { // pocitadlo dolu
      count--; // pocitadlo -1
      count = count % 10; // omez promennou v rozsahu 0-9
      itoa(count, charText, 10); // preved cislo na text
      tft.drawCentreString(charText, 120, 95, 4); // zobrazeni textu
    }
  }
}

Závěr

Každý způsob se hodí pro jiný účel. Samozřejmě lze program napsat tak, aby se při zobrazení konkrétní stránky aktivoval příslušný mód. Osobně s úspěchem používám kombinaci varianty 1, 2 a program optimalizuji tak, aby hlavní smyčka byla opravdu rychlá. To jste si jistě všimli, že loop mívám opravdu krátký.

Příště se ještě vrátíme k tlačítkům, jenom trochu jinak.

JB

jaroslav.bohac@arduinotech.cz

Přidat komentář

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


TOP produkty

Kontakt

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